devvmx: support debug registers; simplify assembly
This commit is contained in:
parent
cbcd9b1d71
commit
2bb65c40ab
3 changed files with 62 additions and 43 deletions
|
@ -10,7 +10,7 @@ extern int vmxon(u64int);
|
|||
extern int vmxoff(void);
|
||||
extern int vmclear(u64int);
|
||||
extern int vmptrld(u64int);
|
||||
extern int vmlaunch(Ureg *, int, FPsave *);
|
||||
extern int vmlaunch(Ureg *, int);
|
||||
extern int vmread(u32int, uintptr *);
|
||||
extern int vmwrite(u32int, uintptr);
|
||||
extern int invept(u32int, uvlong, uvlong);
|
||||
|
@ -71,6 +71,7 @@ enum {
|
|||
CR3_TARGCNT = 0x400a,
|
||||
|
||||
VMEXIT_CTLS = 0x400c,
|
||||
VMEXIT_ST_DEBUG = 1<<2,
|
||||
VMEXIT_HOST64 = 1<<9,
|
||||
VMEXIT_LD_IA32_PERF_GLOBAL_CTRL = 1<<12,
|
||||
VMEXIT_ST_IA32_PAT = 1<<18,
|
||||
|
@ -82,6 +83,7 @@ enum {
|
|||
VMEXIT_MSRLDCNT = 0x4010,
|
||||
|
||||
VMENTRY_CTLS = 0x4012,
|
||||
VMENTRY_LD_DEBUG = 1<<2,
|
||||
VMENTRY_GUEST64 = 1<<9,
|
||||
VMENTRY_LD_IA32_PERF_GLOBAL_CTRL = 1<<13,
|
||||
VMENTRY_LD_IA32_PAT = 1<<14,
|
||||
|
@ -235,6 +237,7 @@ struct Vmx {
|
|||
} state;
|
||||
char errstr[ERRMAX];
|
||||
Ureg ureg;
|
||||
uintptr dr[8]; /* DR7 is also kept in VMCS */
|
||||
FPsave *fp;
|
||||
u8int launched;
|
||||
u8int vpid;
|
||||
|
@ -400,12 +403,32 @@ cr4maskwrite(char *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dr7write(char *s)
|
||||
{
|
||||
uvlong v;
|
||||
|
||||
v = (u32int) parseval(s, 8);
|
||||
vmcswrite(GUEST_DR7, vmx.dr[7] = (u32int) v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
readonly(char *)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
dr6write(char *s)
|
||||
{
|
||||
uvlong v;
|
||||
|
||||
v = parseval(s, 8);
|
||||
vmx.dr[6] = (u32int) v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct GuestReg GuestReg;
|
||||
struct GuestReg {
|
||||
int offset;
|
||||
|
@ -414,7 +437,8 @@ struct GuestReg {
|
|||
char *(*read)(char *, char *);
|
||||
int (*write)(char *);
|
||||
};
|
||||
#define UREG(x) ~(ulong)&((Ureg*)0)->x
|
||||
#define VMXVAR(x) ~(ulong)&(((Vmx*)0)->x)
|
||||
#define UREG(x) VMXVAR(ureg.x)
|
||||
static GuestReg guestregs[] = {
|
||||
{GUEST_RIP, 0, "pc"},
|
||||
{GUEST_RSP, 0, "sp"},
|
||||
|
@ -472,6 +496,12 @@ static GuestReg guestregs[] = {
|
|||
{GUEST_CR4MASK, 0, "cr4mask", nil, cr4maskwrite},
|
||||
{GUEST_IA32_PAT, 8, "pat"},
|
||||
{GUEST_IA32_EFER, 8, "efer"},
|
||||
{VMXVAR(dr[0]), 0, "dr0"},
|
||||
{VMXVAR(dr[1]), 0, "dr1"},
|
||||
{VMXVAR(dr[2]), 0, "dr2"},
|
||||
{VMXVAR(dr[3]), 0, "dr3"},
|
||||
{VMXVAR(dr[6]), 0, "dr6", nil, dr6write},
|
||||
{GUEST_DR7, 0, "dr7", nil, dr7write},
|
||||
{VM_INSTRERR, 4, "instructionerror", nil, readonly},
|
||||
{VM_EXREASON, 4, "exitreason", nil, readonly},
|
||||
{VM_EXQUALIF, 0, "exitqualification", nil, readonly},
|
||||
|
@ -740,14 +770,14 @@ vmcsinit(void)
|
|||
if(rdmsr(VMX_VMEXIT_CTLS_MSR, &msr) < 0) error("rdmsr(VMX_VMEXIT_CTLS_MSR failed");
|
||||
x = (u32int)msr;
|
||||
if(sizeof(uintptr) == 8) x |= VMEXIT_HOST64;
|
||||
x |= VMEXIT_LD_IA32_PAT | VMEXIT_LD_IA32_EFER;
|
||||
x |= VMEXIT_LD_IA32_PAT | VMEXIT_LD_IA32_EFER | VMEXIT_ST_DEBUG;
|
||||
x &= msr >> 32;
|
||||
vmcswrite(VMEXIT_CTLS, x);
|
||||
|
||||
if(rdmsr(VMX_VMENTRY_CTLS_MSR, &msr) < 0) error("rdmsr(VMX_VMENTRY_CTLS_MSR failed");
|
||||
x = (u32int)msr;
|
||||
if(sizeof(uintptr) == 8) x |= VMENTRY_GUEST64;
|
||||
x |= VMENTRY_LD_IA32_PAT | VMENTRY_LD_IA32_EFER;
|
||||
x |= VMENTRY_LD_IA32_PAT | VMENTRY_LD_IA32_EFER | VMENTRY_LD_DEBUG;
|
||||
x &= msr >> 32;
|
||||
vmcswrite(VMENTRY_CTLS, x);
|
||||
|
||||
|
@ -780,7 +810,7 @@ vmcsinit(void)
|
|||
if(rdmsr(0xc0000080, &msr) < 0) error("rdmsr(IA32_EFER) failed");
|
||||
vmcswrite(HOST_IA32_EFER, msr);
|
||||
|
||||
vmcswrite(EXC_BITMAP, 1<<18);
|
||||
vmcswrite(EXC_BITMAP, 1<<18|1<<1);
|
||||
vmcswrite(PFAULT_MASK, 0);
|
||||
vmcswrite(PFAULT_MATCH, 0);
|
||||
|
||||
|
@ -967,7 +997,7 @@ cmdgetregs(VmCmd *, va_list va)
|
|||
if(r->offset >= 0)
|
||||
val = vmcsread(r->offset);
|
||||
else
|
||||
val = *(uintptr*)((uchar*)&vmx.ureg + ~r->offset);
|
||||
val = *(uintptr*)((uchar*)&vmx + ~r->offset);
|
||||
s = r->size;
|
||||
if(s == 0) s = sizeof(uintptr);
|
||||
p = seprint(p, e, "%s %#.*llux\n", r->name, s * 2, val);
|
||||
|
@ -1011,12 +1041,12 @@ setregs(char *p0, char rs, char *fs)
|
|||
if(r->offset >= 0)
|
||||
vmcswrite(r->offset, val);
|
||||
else{
|
||||
assert((u32int)~r->offset + sz <= sizeof(Ureg));
|
||||
assert((u32int)~r->offset + sz <= sizeof(Vmx));
|
||||
switch(sz){
|
||||
case 1: *(u8int*)((u8int*)&vmx.ureg + (u32int)~r->offset) = val; break;
|
||||
case 2: *(u16int*)((u8int*)&vmx.ureg + (u32int)~r->offset) = val; break;
|
||||
case 4: *(u32int*)((u8int*)&vmx.ureg + (u32int)~r->offset) = val; break;
|
||||
case 8: *(u64int*)((u8int*)&vmx.ureg + (u32int)~r->offset) = val; break;
|
||||
case 1: *(u8int*)((u8int*)&vmx + (u32int)~r->offset) = val; break;
|
||||
case 2: *(u16int*)((u8int*)&vmx + (u32int)~r->offset) = val; break;
|
||||
case 4: *(u32int*)((u8int*)&vmx + (u32int)~r->offset) = val; break;
|
||||
case 8: *(u64int*)((u8int*)&vmx + (u32int)~r->offset) = val; break;
|
||||
default: error(Egreg);
|
||||
}
|
||||
}
|
||||
|
@ -1367,7 +1397,7 @@ dostep(int setup)
|
|||
static void
|
||||
vmxproc(void *)
|
||||
{
|
||||
int init;
|
||||
int init, rc, x;
|
||||
u32int procbctls, defprocbctls;
|
||||
|
||||
procwired(up, 0);
|
||||
|
@ -1425,7 +1455,15 @@ vmxproc(void *)
|
|||
}
|
||||
vmcswrite(PROCB_CTLS, procbctls);
|
||||
vmx.got &= ~GOTEXIT;
|
||||
if(vmlaunch(&vmx.ureg, vmx.launched, vmx.fp) < 0)
|
||||
|
||||
x = splhi();
|
||||
if((vmx.dr[7] & ~0xd400) != 0)
|
||||
putdr01236(vmx.dr);
|
||||
fpsserestore0(vmx.fp);
|
||||
rc = vmlaunch(&vmx.ureg, vmx.launched);
|
||||
fpssesave0(vmx.fp);
|
||||
splx(x);
|
||||
if(rc < 0)
|
||||
error("vmlaunch failed");
|
||||
vmx.launched = 1;
|
||||
if((vmx.onentry & STEP) != 0){
|
||||
|
|
|
@ -167,6 +167,7 @@ void putcr0(ulong);
|
|||
void putcr3(ulong);
|
||||
void putcr4(ulong);
|
||||
void putdr(u32int*);
|
||||
void putdr01236(uintptr*);
|
||||
void putdr6(u32int);
|
||||
void putdr7(u32int);
|
||||
void* rampage(void);
|
||||
|
|
|
@ -851,6 +851,7 @@ TEXT putdr(SB), $0
|
|||
MOVL p+0(FP), SI
|
||||
MOVL 28(SI), AX
|
||||
MOVL AX, DR7
|
||||
_putdr01236:
|
||||
MOVL 0(SI), AX
|
||||
MOVL AX, DR0
|
||||
MOVL 4(SI), AX
|
||||
|
@ -863,6 +864,10 @@ TEXT putdr(SB), $0
|
|||
MOVL AX, DR6
|
||||
RET
|
||||
|
||||
TEXT putdr01236(SB), $0
|
||||
MOVL p+0(FP), SI
|
||||
JMP _putdr01236
|
||||
|
||||
TEXT getdr6(SB), $0
|
||||
MOVL DR6, AX
|
||||
RET
|
||||
|
@ -893,21 +898,14 @@ TEXT vmclear(SB), $0
|
|||
JMP _vmout
|
||||
|
||||
TEXT vmlaunch(SB), $0
|
||||
PUSHFL
|
||||
CLI
|
||||
|
||||
MOVL $0x6C14, DI
|
||||
MOVL SP, DX
|
||||
BYTE $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
|
||||
JBE _launchout
|
||||
JBE _vmout
|
||||
MOVL $0x6C16, DI
|
||||
MOVL $vmrestore+1(SB), DX /* add 1 to skip extra PUSHFL */
|
||||
MOVL $vmrestore(SB), DX
|
||||
BYTE $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */
|
||||
JBE _launchout
|
||||
|
||||
FPON
|
||||
MOVL fp+8(FP), AX
|
||||
FXRSTOR 0(AX)
|
||||
JBE _vmout
|
||||
|
||||
MOVL resume+4(FP), AX
|
||||
TESTL AX, AX
|
||||
|
@ -923,26 +921,12 @@ TEXT vmlaunch(SB), $0
|
|||
MOVL 0(DI), DI
|
||||
JNE _vmresume
|
||||
BYTE $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */
|
||||
JMP _launchout
|
||||
JMP _vmout
|
||||
_vmresume:
|
||||
BYTE $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */
|
||||
_launchout:
|
||||
JC _launchout1
|
||||
JZ _launchout2
|
||||
XORL AX, AX
|
||||
_launchret:
|
||||
FPOFF
|
||||
POPFL
|
||||
RET
|
||||
_launchout1:
|
||||
MOVL $-1, AX
|
||||
JMP _launchret
|
||||
_launchout2:
|
||||
MOVL $-2, AX
|
||||
JMP _launchret
|
||||
JMP _vmout
|
||||
|
||||
TEXT vmrestore(SB), $0
|
||||
PUSHFL /* stupid hack to make 8l happy; nexer executed */
|
||||
PUSHL DI
|
||||
MOVL ureg+0(FP), DI
|
||||
POPL 0(DI)
|
||||
|
@ -954,11 +938,7 @@ TEXT vmrestore(SB), $0
|
|||
MOVL AX, 28(DI)
|
||||
MOVL CR2, AX
|
||||
MOVL AX, 32(DI)
|
||||
MOVL fp+8(FP), AX
|
||||
FXSAVE 0(AX)
|
||||
FPOFF
|
||||
XORL AX, AX
|
||||
POPFL
|
||||
RET
|
||||
|
||||
TEXT vmptrld(SB), $0
|
||||
|
|
Loading…
Reference in a new issue