vmx(1): add support for (so far) crude 9p debugging fs; add gdb stub; clean up linux gdt code
This commit is contained in:
parent
37b9ab5a04
commit
5c0bff4ba2
11 changed files with 531 additions and 27 deletions
65
sys/src/cmd/vmx/9p.c
Normal file
65
sys/src/cmd/vmx/9p.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <fcall.h>
|
||||
#include <9p.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
extern int regsfd;
|
||||
char Egreg[] = "the front fell off";
|
||||
|
||||
enum {
|
||||
Qregs,
|
||||
Qmem,
|
||||
Qmax
|
||||
};
|
||||
|
||||
static Dir files[] = {
|
||||
[Qregs] {.name "regs", .mode 0440},
|
||||
[Qmem] {.name "mem", .mode 0440},
|
||||
};
|
||||
|
||||
void
|
||||
srvread(Req *r)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch(r->fid->qid.path){
|
||||
case Qregs:
|
||||
rc = pread(regsfd, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
|
||||
if(rc < 0)
|
||||
responderror(r);
|
||||
else{
|
||||
r->ofcall.count = rc;
|
||||
respond(r, nil);
|
||||
}
|
||||
break;
|
||||
case Qmem:
|
||||
r->ofcall.count = vmemread(r->ofcall.data, r->ifcall.count, r->ifcall.offset);
|
||||
if(r->ofcall.count == 0)
|
||||
respond(r, "fault");
|
||||
else
|
||||
respond(r, nil);
|
||||
break;
|
||||
default:
|
||||
respond(r, Egreg);
|
||||
}
|
||||
}
|
||||
|
||||
Srv vmxsrv = {
|
||||
.read srvread,
|
||||
};
|
||||
|
||||
void
|
||||
init9p(char *srvname)
|
||||
{
|
||||
char *uid;
|
||||
int i;
|
||||
|
||||
uid = getuser();
|
||||
vmxsrv.tree = alloctree(uid, uid, 0770, nil);
|
||||
for(i = 0; i < Qmax; i++)
|
||||
createfile(vmxsrv.tree->root, files[i].name, uid, files[i].mode, nil);
|
||||
threadpostmountsrv(&vmxsrv, srvname, nil, 0);
|
||||
}
|
|
@ -3,7 +3,14 @@ typedef struct PCICap PCICap;
|
|||
typedef struct PCIBar PCIBar;
|
||||
typedef struct Region Region;
|
||||
|
||||
extern int halt, irqactive;
|
||||
extern int irqactive;
|
||||
|
||||
enum {
|
||||
VMRUNNING,
|
||||
VMHALT,
|
||||
VMDEAD,
|
||||
};
|
||||
extern int state;
|
||||
|
||||
enum {
|
||||
BY2PG = 4096
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
int persist = 0;
|
||||
|
||||
typedef struct ExitInfo ExitInfo;
|
||||
struct ExitInfo {
|
||||
char *raw;
|
||||
|
@ -407,7 +409,7 @@ static void
|
|||
hlt(ExitInfo *ei)
|
||||
{
|
||||
if(irqactive == 0)
|
||||
halt = 1;
|
||||
state = VMHALT;
|
||||
skipinstr(ei);
|
||||
}
|
||||
|
||||
|
@ -484,5 +486,9 @@ processexit(char *msg)
|
|||
vmerror("vmx: unknown notification %s", f[0]+1);
|
||||
return;
|
||||
}
|
||||
sysfatal("unknown exit: %s", msg);
|
||||
if(persist){
|
||||
vmerror("unknown exit: %s", msg);
|
||||
state = VMDEAD;
|
||||
}else
|
||||
sysfatal("unknown exit: %s", msg);
|
||||
}
|
||||
|
|
|
@ -43,3 +43,4 @@ void i8042kick(void *);
|
|||
u32int roundpow2(u32int);
|
||||
u32int vgagetpal(u8int);
|
||||
void vgasetpal(u8int, u32int);
|
||||
uintptr vmemread(void *, uintptr, uintptr);
|
||||
|
|
|
@ -202,7 +202,8 @@ picupdate(Pic *p)
|
|||
if(m != 0 && irqactive != n){
|
||||
if(ctl("irq %d", n) < 0)
|
||||
sysfatal("ctl: %r");
|
||||
halt = 0;
|
||||
if(state == VMHALT)
|
||||
state = VMRUNNING;
|
||||
irqactive = n;
|
||||
}else if(m == 0 && irqactive >= 0){
|
||||
if(ctl("irq") < 0)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <libsec.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "x86.h"
|
||||
|
||||
static uchar hdr[8192];
|
||||
static int fd;
|
||||
|
@ -789,20 +790,6 @@ linuxscreeninfo(void *zp)
|
|||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
GDTRW = 2<<8,
|
||||
GDTRX = 10<<8,
|
||||
GDTS = 1<<12,
|
||||
GDTP = 1<<15,
|
||||
GDT64 = 1<<21,
|
||||
GDT32 = 1<<22,
|
||||
GDTG = 1<<23,
|
||||
};
|
||||
#define GDTLIM0(l) ((l) & 0x0ffff)
|
||||
#define GDTLIM1(l) ((l) & 0xf0000)
|
||||
#define GDTBASE0(b) ((b) << 16)
|
||||
#define GDTBASE1(b) ((b) >> 16 & 0xff | (b) & 0xff000000)
|
||||
|
||||
static void
|
||||
linuxgdt(void *v)
|
||||
{
|
||||
|
@ -810,10 +797,10 @@ linuxgdt(void *v)
|
|||
|
||||
base = gpa(v);
|
||||
rset("gdtrbase", base);
|
||||
v = pack(v, "ii", 0, 0);
|
||||
v = pack(v, "ii", 0, 0);
|
||||
v = pack(v, "ii", GDTLIM0(-1) | GDTBASE0(0), GDTLIM1(-1) | GDTBASE1(0) | GDTRX | GDTG | GDTS | GDTP | GDT32);
|
||||
v = pack(v, "ii", GDTLIM0(-1) | GDTBASE0(0), GDTLIM1(-1) | GDTBASE1(0) | GDTRW | GDTG | GDTS | GDTP | GDT32);
|
||||
v = pack(v, "vvvv", 0, 0,
|
||||
GDTBASE(0) | GDTLIM(-1) | GDTRX | GDTG | GDTP | GDT32,
|
||||
GDTBASE(0) | GDTLIM(-1) | GDTRW | GDTG | GDTP | GDT32
|
||||
);
|
||||
rset("gdtrlimit", gpa(v) - base - 1);
|
||||
rset("cs", 0x10);
|
||||
rset("ds", 0x18);
|
||||
|
@ -914,6 +901,7 @@ trylinux(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
loadkernel(char *fn)
|
||||
{
|
||||
|
@ -921,7 +909,13 @@ loadkernel(char *fn)
|
|||
if(fd < 0) sysfatal("open: %r");
|
||||
if(readn(fd, hdr, sizeof(hdr)) <= 0)
|
||||
sysfatal("readn: %r");
|
||||
if(!trymultiboot() && !tryelf() && !trylinux())
|
||||
sysfatal("%s: unknown format", fn);
|
||||
if(trymultiboot())
|
||||
goto done;
|
||||
if(tryelf())
|
||||
goto done;
|
||||
if(trylinux())
|
||||
goto done;
|
||||
sysfatal("%s: unknown format", fn);
|
||||
done:
|
||||
close(fd);
|
||||
}
|
||||
|
|
|
@ -12,5 +12,15 @@ OFILES=\
|
|||
pci.$O \
|
||||
virtio.$O \
|
||||
vesa.$O \
|
||||
9p.$O \
|
||||
x86.$O \
|
||||
|
||||
</sys/src/cmd/mkone
|
||||
|
||||
install:V: $BIN/vmxgdb
|
||||
|
||||
$BIN/vmxgdb: $O.vmxgdb
|
||||
cp $prereq $BIN/vmxgdb
|
||||
|
||||
$O.vmxgdb: vmxgdb.$O
|
||||
$LD $LDFLAGS -o $target $prereq
|
||||
|
|
|
@ -9,7 +9,7 @@ Region *mmap;
|
|||
int ctlfd, regsfd, waitfd;
|
||||
Channel *waitch, *sleepch, *notifch;
|
||||
enum { MSEC = 1000*1000, MinSleep = MSEC, SleeperPoll = 2000*MSEC } ;
|
||||
int getexit, halt;
|
||||
int getexit, state;
|
||||
typedef struct VmxNotif VmxNotif;
|
||||
struct VmxNotif {
|
||||
void (*f)(void *);
|
||||
|
@ -440,7 +440,7 @@ runloop(void)
|
|||
notif.f(notif.arg);
|
||||
break;
|
||||
}
|
||||
if(getexit == 0 && halt == 0)
|
||||
if(getexit == 0 && state == VMRUNNING)
|
||||
launch();
|
||||
}
|
||||
}
|
||||
|
@ -463,6 +463,7 @@ extern void pciinit(void);
|
|||
extern void pcibusmap(void);
|
||||
extern void cpuidinit(void);
|
||||
extern void vgafbparse(char *);
|
||||
extern void init9p(char *);
|
||||
|
||||
int cmdlinen;
|
||||
char **cmdlinev;
|
||||
|
@ -494,7 +495,7 @@ usage(void)
|
|||
for(p = blanks; *p != 0; p++)
|
||||
*p = ' ';
|
||||
fprint(2, "usage: %s [ -M mem ] [ -c com1rd[,com1wr] ] [ -C com2rd[,com2r] ] [ -n nic ]\n", argv0);
|
||||
fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v vga ] kernel [ args ... ]\n", blanks);
|
||||
fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v vga ] [ -9 srv ] kernel [ args ... ]\n", blanks);
|
||||
threadexitsall("usage");
|
||||
}
|
||||
|
||||
|
@ -506,6 +507,7 @@ threadmain(int argc, char **argv)
|
|||
static char *edevaux[nelem(edev)];
|
||||
static int edevn;
|
||||
static uvlong gmemsz = 64*1024*1024;
|
||||
static char *srvname;
|
||||
extern uintptr fbsz, fbaddr;
|
||||
int i;
|
||||
|
||||
|
@ -546,6 +548,10 @@ threadmain(int argc, char **argv)
|
|||
case 'v':
|
||||
vgafbparse(EARGF(usage()));
|
||||
break;
|
||||
case '9':
|
||||
if(srvname != nil) usage();
|
||||
srvname = EARGF(usage());
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
} ARGEND;
|
||||
|
@ -578,6 +584,8 @@ threadmain(int argc, char **argv)
|
|||
sysfatal("%s: %r", edevt[i]);
|
||||
|
||||
pcibusmap();
|
||||
|
||||
if(srvname != nil) init9p(srvname);
|
||||
runloop();
|
||||
exits(nil);
|
||||
}
|
||||
|
|
259
sys/src/cmd/vmx/vmxgdb.c
Normal file
259
sys/src/cmd/vmx/vmxgdb.c
Normal file
|
@ -0,0 +1,259 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
|
||||
char *vmxroot = "/n/vmx";
|
||||
|
||||
Biobuf *bin, *bout;
|
||||
int regsfd, memfd;
|
||||
int noack;
|
||||
|
||||
void *
|
||||
emalloc(ulong sz)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = malloc(sz);
|
||||
if(v == nil)
|
||||
sysfatal("malloc: %r");
|
||||
memset(v, 0, sz);
|
||||
setmalloctag(v, getcallerpc(&sz));
|
||||
return v;
|
||||
}
|
||||
|
||||
int
|
||||
eBgetc(Biobuf *bp)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = Bgetc(bp);
|
||||
if(c < 0) sysfatal("Bgetc: %r");
|
||||
return c;
|
||||
}
|
||||
|
||||
char *
|
||||
rpack(void)
|
||||
{
|
||||
int c;
|
||||
char *pkt;
|
||||
ulong npkt;
|
||||
u8int csum, csum2;
|
||||
char buf[3], *p;
|
||||
|
||||
while(eBgetc(bin) != '$')
|
||||
;
|
||||
if(0){
|
||||
repeat:
|
||||
free(pkt);
|
||||
}
|
||||
pkt = nil;
|
||||
npkt = 0;
|
||||
csum = 0;
|
||||
while(c = eBgetc(bin)){
|
||||
if(c == '#') break;
|
||||
if(c == '$') goto repeat;
|
||||
csum += c;
|
||||
if(c == '}'){
|
||||
c = eBgetc(bin);
|
||||
if(c == '#') break;
|
||||
if(c == '$') goto repeat;
|
||||
csum += c;
|
||||
c ^= 0x20;
|
||||
}
|
||||
if(npkt % 64 == 0)
|
||||
pkt = realloc(pkt, npkt + 64);
|
||||
pkt[npkt++] = c;
|
||||
}
|
||||
if(npkt % 64 == 0)
|
||||
pkt = realloc(pkt, npkt + 1);
|
||||
pkt[npkt] = 0;
|
||||
buf[0] = eBgetc(bin);
|
||||
if(buf[0] == '$') goto repeat;
|
||||
buf[1] = eBgetc(bin);
|
||||
if(buf[1] == '$') goto repeat;
|
||||
if(noack) return pkt;
|
||||
buf[2] = 0;
|
||||
csum2 = strtol(buf, &p, 16);
|
||||
if(p != &buf[2] || csum != csum2){
|
||||
Bputc(bout, '-');
|
||||
goto repeat;
|
||||
}
|
||||
Bputc(bout, '+');
|
||||
return pkt;
|
||||
}
|
||||
|
||||
int
|
||||
bflush(Biobufhdr *, void *v, long n)
|
||||
{
|
||||
Bflush(bout);
|
||||
return read(bin->fid, v, n);
|
||||
}
|
||||
|
||||
void
|
||||
wpack(char *p0)
|
||||
{
|
||||
u8int csum;
|
||||
char *p;
|
||||
|
||||
fprint(2, "-> %s\n", p0);
|
||||
again:
|
||||
p = p0;
|
||||
csum = 0;
|
||||
Bputc(bout, '$');
|
||||
for(; *p != 0; p++)
|
||||
switch(*p){
|
||||
case '$': case '#': case '{': case '*':
|
||||
Bputc(bout, '{');
|
||||
Bputc(bout, *p ^ 0x20);
|
||||
csum += '{' + (*p ^ 0x20);
|
||||
break;
|
||||
default:
|
||||
Bputc(bout, *p);
|
||||
csum += *p;
|
||||
}
|
||||
Bprint(bout, "#%.2uX", csum);
|
||||
if(noack) return;
|
||||
for(;;)
|
||||
switch(eBgetc(bin)){
|
||||
case '+': return;
|
||||
case '-': goto again;
|
||||
case '$': Bungetc(bin); return;
|
||||
}
|
||||
}
|
||||
|
||||
static char *regname[] = {
|
||||
"ax", "cx", "dx", "bx",
|
||||
"sp", "bp", "si", "di",
|
||||
"pc", "flags", "cs", "ss",
|
||||
"ds", "es", "fs", "gs",
|
||||
};
|
||||
|
||||
char *
|
||||
regpacket(void)
|
||||
{
|
||||
char *buf;
|
||||
char rbuf[8192];
|
||||
int rc;
|
||||
char *p, *q, *f[2];
|
||||
int pos, i, l;
|
||||
uvlong v;
|
||||
char tbuf[3];
|
||||
|
||||
l = 4 * nelem(regname);
|
||||
buf = emalloc(2 * l + 1);
|
||||
memset(buf, 'x', 2 * l);
|
||||
rc = pread(regsfd, rbuf, sizeof(rbuf)-1, 0);
|
||||
if(rc < 0){
|
||||
free(buf);
|
||||
return strdup("");
|
||||
}
|
||||
rbuf[rc] = 0;
|
||||
p = rbuf;
|
||||
for(;; p = q + 1){
|
||||
q = strchr(p, '\n');
|
||||
if(q == nil) break;
|
||||
*q = 0;
|
||||
if(tokenize(p, f, nelem(f)) < 2) continue;
|
||||
v = strtoull(f[1], nil, 0);
|
||||
pos = 0;
|
||||
for(i = 0; i < nelem(regname); i++){
|
||||
if(strcmp(f[0], regname[i]) == 0)
|
||||
break;
|
||||
pos += 4;
|
||||
}
|
||||
if(i == nelem(regname)) continue;
|
||||
l = 4;
|
||||
while(l--){
|
||||
sprint(tbuf, "%.2ux", (u8int)v);
|
||||
((u16int*)buf)[pos++] = *(u16int*)tbuf;
|
||||
v >>= 8;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
memread(char *p)
|
||||
{
|
||||
char *q;
|
||||
uvlong addr, count;
|
||||
char *buf;
|
||||
int rc, i;
|
||||
char tbuf[3];
|
||||
|
||||
addr = strtoull(p, &q, 16);
|
||||
if(p == q || *q != ',') return strdup("E99");
|
||||
count = strtoull(q + 1, &p, 16);
|
||||
if(q+1 == p || *p != 0) return strdup("E99");
|
||||
if(count > 65536) count = 65536;
|
||||
buf = emalloc(2*count+4);
|
||||
rc = pread(memfd, buf, count, addr);
|
||||
if(rc <= 0) return strcpy(buf, "E01");
|
||||
for(i = rc; --i >= 0; ){
|
||||
sprint(tbuf, "%.2ux", (uchar)buf[i]);
|
||||
((u16int*)buf)[i] = *(u16int*)tbuf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
main(int, char **)
|
||||
{
|
||||
char *p, *msg;
|
||||
|
||||
bin = Bfdopen(0, OREAD);
|
||||
if(bin == nil) sysfatal("Bfdopen: %r");
|
||||
bout = Bfdopen(1, OWRITE);
|
||||
if(bout == nil) sysfatal("Bfdpen: %r");
|
||||
Biofn(bin, bflush);
|
||||
|
||||
p = smprint("%s/mem", vmxroot);
|
||||
memfd = open(p, OREAD);
|
||||
free(p);
|
||||
if(memfd < 0) sysfatal("open: %r");
|
||||
|
||||
p = smprint("%s/regs", vmxroot);
|
||||
regsfd = open(p, OREAD);
|
||||
free(p);
|
||||
if(regsfd < 0) sysfatal("open: %r");
|
||||
|
||||
for(;;){
|
||||
msg = rpack();
|
||||
fprint(2, "<- %s\n", msg);
|
||||
reinterpret:
|
||||
switch(*msg){
|
||||
case 'g':
|
||||
p = regpacket();
|
||||
wpack(p);
|
||||
free(p);
|
||||
break;
|
||||
case '?':
|
||||
wpack("S00");
|
||||
break;
|
||||
case 'm':
|
||||
p = memread(msg+1);
|
||||
wpack(p);
|
||||
free(p);
|
||||
break;
|
||||
case 'q':
|
||||
if(strncmp(msg, "qSupported", 10) == 0 && (msg[10] == ':' || msg[10] == 0)){
|
||||
wpack("PacketSize=4096;QStartNoAckMode+");
|
||||
}else
|
||||
goto no;
|
||||
break;
|
||||
case 'Q':
|
||||
if(strcmp(msg, "QStartNoAckMode") == 0){
|
||||
wpack("OK");
|
||||
noack = 1;
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
msg[0] = msg[1];
|
||||
msg[1] = 0;
|
||||
goto reinterpret;
|
||||
default: no: wpack(""); break;
|
||||
}
|
||||
free(msg);
|
||||
}
|
||||
|
||||
}
|
124
sys/src/cmd/vmx/x86.c
Normal file
124
sys/src/cmd/vmx/x86.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "x86.h"
|
||||
|
||||
typedef struct VMemReq VMemReq;
|
||||
struct VMemReq {
|
||||
QLock;
|
||||
uintptr va, len;
|
||||
void *buf;
|
||||
uintptr rc;
|
||||
};
|
||||
|
||||
static uintptr
|
||||
translateflat(uintptr va, uintptr *pa, uintptr)
|
||||
{
|
||||
*pa = va;
|
||||
if(va == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr
|
||||
translate32(uintptr va, uintptr *pa, uintptr cr4)
|
||||
{
|
||||
void *pd, *pt;
|
||||
u32int pde, pte;
|
||||
|
||||
if(sizeof(uintptr) != 4 && va >> 32 != 0) return -1;
|
||||
pd = gptr(rget("cr3") & ~0xfff, 4096);
|
||||
if(pd == nil) return 0;
|
||||
pde = GET32(pd, (va >> 22) * 4);
|
||||
if((pde & 1) == 0) return 0;
|
||||
if((pde & 0x80) != 0 && (cr4 & Cr4Pse) != 0){
|
||||
*pa = pde & (1<<22) - 1 | (uintptr)(pde & 0xfe000) << 19;
|
||||
return (1<<22) - (va & (1<<22)-1);
|
||||
}
|
||||
pt = gptr(pde & ~0xfff, 4096);
|
||||
if(pt == nil) return 0;
|
||||
pte = GET32(pt, va >> 10 & 0xffc);
|
||||
if((pte & 1) == 0) return 0;
|
||||
*pa = pte & ~0xfff | va & 0xfff;
|
||||
return 0x1000 - (va & 0xfff);
|
||||
}
|
||||
|
||||
static uintptr
|
||||
translatepae(uintptr, uintptr *, uintptr)
|
||||
{
|
||||
vmerror("PAE translation not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr
|
||||
translate64(uintptr, uintptr *, uintptr)
|
||||
{
|
||||
vmerror("long mode translation not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uintptr (*
|
||||
translator(uintptr *cr4p))(uintptr, uintptr *, uintptr)
|
||||
{
|
||||
uintptr cr0, cr4, efer;
|
||||
|
||||
cr0 = rget("cr0real");
|
||||
if((cr0 & Cr0Pg) == 0)
|
||||
return translateflat;
|
||||
efer = rget("efer");
|
||||
if((efer & EferLme) != 0)
|
||||
return translate64;
|
||||
cr4 = rget("cr4real");
|
||||
*cr4p = cr4;
|
||||
if((cr4 & Cr4Pae) != 0)
|
||||
return translatepae;
|
||||
return translate32;
|
||||
}
|
||||
|
||||
static void
|
||||
vmemread0(void *aux)
|
||||
{
|
||||
VMemReq *req;
|
||||
uintptr va, pa, n, ok, pok, cr4;
|
||||
void *v;
|
||||
uintptr (*trans)(uintptr, uintptr *, uintptr);
|
||||
uchar *p;
|
||||
|
||||
req = aux;
|
||||
va = req->va;
|
||||
n = req->len;
|
||||
p = req->buf;
|
||||
trans = translator(&cr4);
|
||||
while(n > 0){
|
||||
ok = trans(va, &pa, cr4);
|
||||
if(ok == 0) break;
|
||||
if(ok > n) ok = n;
|
||||
v = gptr(pa, 1);
|
||||
if(v == nil) break;
|
||||
pok = gavail(v);
|
||||
if(ok > pok) ok = pok;
|
||||
memmove(p, v, ok);
|
||||
n -= ok;
|
||||
p += ok;
|
||||
va += ok;
|
||||
}
|
||||
req->rc = req->len - n;
|
||||
qunlock(req);
|
||||
}
|
||||
|
||||
uintptr
|
||||
vmemread(void *buf, uintptr len, uintptr va)
|
||||
{
|
||||
VMemReq req;
|
||||
|
||||
memset(&req, 0, sizeof(VMemReq));
|
||||
req.buf = buf;
|
||||
req.len = len;
|
||||
req.va = va;
|
||||
qlock(&req);
|
||||
sendnotif(vmemread0, &req);
|
||||
qlock(&req);
|
||||
return req.rc;
|
||||
}
|
29
sys/src/cmd/vmx/x86.h
Normal file
29
sys/src/cmd/vmx/x86.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#define GDTTYPE(x) ((uvlong)(x)<<40)
|
||||
enum {
|
||||
GDTR = GDTTYPE(0x10), /* read-only */
|
||||
GDTRW = GDTTYPE(0x12), /* read-write *
|
||||
GDTX = GDTTYPE(0x18), /* execute-only */
|
||||
GDTRX = GDTTYPE(0x1A), /* read-execute */
|
||||
|
||||
GDTTSS = GDTTYPE(0x09),
|
||||
|
||||
GDTA = 1ULL<<40, /* accessed */
|
||||
GDTE = 1ULL<<42, /* expand down (data only) */
|
||||
GDTC = GDTE, /* conforming (code only) */
|
||||
GDTP = 1ULL<<47, /* present */
|
||||
GDT64 = 1ULL<<53, /* 64-bit code segment */
|
||||
GDT32 = 1ULL<<54, /* 32-bit segment */
|
||||
GDTG = 1ULL<<55, /* granularity */
|
||||
};
|
||||
#define GDTLIM(l) ((l) & 0xffff | (uvlong)((l) & 0xf0000)<<32)
|
||||
#define GDTBASE(l) (((uvlong)(l) & 0xffffff)<<16 | (uvlong)((l) & 0xff000000)<<32)
|
||||
#define GDTDPL(l) ((uvlong)(l)<<45)
|
||||
|
||||
enum {
|
||||
Cr0Pg = 1<<31,
|
||||
|
||||
Cr4Pse = 1<<4,
|
||||
Cr4Pae = 1<<5,
|
||||
|
||||
EferLme = 1<<8,
|
||||
};
|
Loading…
Reference in a new issue