ref: 2bb65c40ab0713b011ff758cc2d8bc20e885fe85
parent: cbcd9b1d718bb827432c944620fac09847c6abc0
author: aiju <devnull@localhost>
date: Sat Jun 17 18:38:16 EDT 2017
devvmx: support debug registers; simplify assembly
--- a/sys/src/9/pc/devvmx.c
+++ b/sys/src/9/pc/devvmx.c
@@ -10,7 +10,7 @@
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 @@
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 @@
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 @@
} state;
char errstr[ERRMAX];
Ureg ureg;
+ uintptr dr[8]; /* DR7 is also kept in VMCS */
FPsave *fp;
u8int launched;
u8int vpid;
@@ -401,11 +404,31 @@
}
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 @@
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 @@
{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,7 +770,7 @@
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);
@@ -747,7 +777,7 @@
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 @@
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 @@
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 @@
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 @@
static void
vmxproc(void *)
{
- int init;
+ int init, rc, x;
u32int procbctls, defprocbctls;
procwired(up, 0);
@@ -1425,7 +1455,15 @@
}
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){
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -167,6 +167,7 @@
void putcr3(ulong);
void putcr4(ulong);
void putdr(u32int*);
+void putdr01236(uintptr*);
void putdr6(u32int);
void putdr7(u32int);
void* rampage(void);
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -851,6 +851,7 @@
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 @@
MOVL AX, DR6
RET
+TEXT putdr01236(SB), $0
+ MOVL p+0(FP), SI
+ JMP _putdr01236
+
TEXT getdr6(SB), $0
MOVL DR6, AX
RET
@@ -893,22 +898,15 @@
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
+ JBE _vmout
- FPON
- MOVL fp+8(FP), AX
- FXRSTOR 0(AX)
-
MOVL resume+4(FP), AX
TESTL AX, AX
MOVL ureg+0(FP), DI
@@ -923,26 +921,12 @@
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 @@
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