From 2bb65c40ab0713b011ff758cc2d8bc20e885fe85 Mon Sep 17 00:00:00 2001 From: aiju Date: Sat, 17 Jun 2017 22:38:16 +0000 Subject: [PATCH] devvmx: support debug registers; simplify assembly --- sys/src/9/pc/devvmx.c | 64 ++++++++++++++++++++++++++++++++++--------- sys/src/9/pc/fns.h | 1 + sys/src/9/pc/l.s | 40 +++++++-------------------- 3 files changed, 62 insertions(+), 43 deletions(-) diff --git a/sys/src/9/pc/devvmx.c b/sys/src/9/pc/devvmx.c index 7a8ddae14..91c92e0ff 100644 --- a/sys/src/9/pc/devvmx.c +++ b/sys/src/9/pc/devvmx.c @@ -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){ diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 7b91ed4df..cf2e20576 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -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); diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 4e0a9a031..955c0fd93 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -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