Page MenuHomeFreeBSD

D13229.id35695.diff
No OneTemporary

D13229.id35695.diff

Index: sys/amd64/include/vmm.h
===================================================================
--- sys/amd64/include/vmm.h
+++ sys/amd64/include/vmm.h
@@ -83,6 +83,11 @@
VM_REG_GUEST_PDPTE2,
VM_REG_GUEST_PDPTE3,
VM_REG_GUEST_INTR_SHADOW,
+ VM_REG_GUEST_DR0,
+ VM_REG_GUEST_DR1,
+ VM_REG_GUEST_DR2,
+ VM_REG_GUEST_DR3,
+ VM_REG_GUEST_DR6,
VM_REG_LAST
};
Index: sys/amd64/vmm/amd/svm.h
===================================================================
--- sys/amd64/vmm/amd/svm.h
+++ sys/amd64/vmm/amd/svm.h
@@ -49,6 +49,18 @@
register_t sctx_r13;
register_t sctx_r14;
register_t sctx_r15;
+ register_t sctx_dr0;
+ register_t sctx_dr1;
+ register_t sctx_dr2;
+ register_t sctx_dr3;
+
+ register_t host_dr0;
+ register_t host_dr1;
+ register_t host_dr2;
+ register_t host_dr3;
+ register_t host_dr6;
+ register_t host_dr7;
+ uint64_t host_debugctl;
};
void svm_launch(uint64_t pa, struct svm_regctx *gctx, struct pcpu *pcpu);
Index: sys/amd64/vmm/amd/svm.c
===================================================================
--- sys/amd64/vmm/amd/svm.c
+++ sys/amd64/vmm/amd/svm.c
@@ -87,6 +87,7 @@
VMCB_CACHE_TPR | \
VMCB_CACHE_CR2 | \
VMCB_CACHE_CR | \
+ VMCB_CACHE_DR | \
VMCB_CACHE_DT | \
VMCB_CACHE_SEG | \
VMCB_CACHE_NP)
@@ -1900,6 +1901,60 @@
__asm __volatile("stgi");
}
+static __inline void
+svm_dr_enter_guest(struct svm_regctx *gctx)
+{
+
+ /* Save host control debug registers. */
+ gctx->host_dr7 = rdr7();
+ gctx->host_debugctl = rdmsr(MSR_DEBUGCTLMSR);
+
+ /*
+ * Disable debugging in DR7 and DEBUGCTL to avoid triggering
+ * exceptions in the host based on the guest DRx values. The
+ * guest DR6, DR7, and DEBUGCTL are saved/restored in the
+ * VMCB.
+ */
+ load_dr7(0);
+ wrmsr(MSR_DEBUGCTLMSR, 0);
+
+ /* Save host debug registers. */
+ gctx->host_dr0 = rdr0();
+ gctx->host_dr1 = rdr1();
+ gctx->host_dr2 = rdr2();
+ gctx->host_dr3 = rdr3();
+ gctx->host_dr6 = rdr6();
+
+ /* Restore guest debug registers. */
+ load_dr0(gctx->sctx_dr0);
+ load_dr1(gctx->sctx_dr1);
+ load_dr2(gctx->sctx_dr2);
+ load_dr3(gctx->sctx_dr3);
+}
+
+static __inline void
+svm_dr_leave_guest(struct svm_regctx *gctx)
+{
+
+ /* Save guest debug registers. */
+ gctx->sctx_dr0 = rdr0();
+ gctx->sctx_dr1 = rdr1();
+ gctx->sctx_dr2 = rdr2();
+ gctx->sctx_dr3 = rdr3();
+
+ /*
+ * Restore host debug registers. Restore DR7 and DEBUGCTL
+ * last.
+ */
+ load_dr0(gctx->host_dr0);
+ load_dr1(gctx->host_dr1);
+ load_dr2(gctx->host_dr2);
+ load_dr3(gctx->host_dr3);
+ load_dr6(gctx->host_dr6);
+ wrmsr(MSR_DEBUGCTLMSR, gctx->host_debugctl);
+ load_dr7(gctx->host_dr7);
+}
+
/*
* Start vcpu with specified RIP.
*/
@@ -2012,7 +2067,9 @@
/* Launch Virtual Machine. */
VCPU_CTR1(vm, vcpu, "Resume execution at %#lx", state->rip);
+ svm_dr_enter_guest(gctx);
svm_launch(vmcb_pa, gctx, &__pcpu[curcpu]);
+ svm_dr_leave_guest(gctx);
CPU_CLR_ATOMIC(curcpu, &pmap->pm_active);
@@ -2079,6 +2136,14 @@
return (&regctx->sctx_r14);
case VM_REG_GUEST_R15:
return (&regctx->sctx_r15);
+ case VM_REG_GUEST_DR0:
+ return (&regctx->sctx_dr0);
+ case VM_REG_GUEST_DR1:
+ return (&regctx->sctx_dr1);
+ case VM_REG_GUEST_DR2:
+ return (&regctx->sctx_dr2);
+ case VM_REG_GUEST_DR3:
+ return (&regctx->sctx_dr3);
default:
return (NULL);
}
Index: sys/amd64/vmm/amd/vmcb.c
===================================================================
--- sys/amd64/vmm/amd/vmcb.c
+++ sys/amd64/vmm/amd/vmcb.c
@@ -187,6 +187,10 @@
*retval = state->cr4;
break;
+ case VM_REG_GUEST_DR6:
+ *retval = state->dr6;
+ break;
+
case VM_REG_GUEST_DR7:
*retval = state->dr7;
break;
@@ -278,8 +282,14 @@
svm_set_dirty(sc, vcpu, VMCB_CACHE_CR);
break;
+ case VM_REG_GUEST_DR6:
+ state->dr6 = val;
+ svm_set_dirty(sc, vcpu, VMCB_CACHE_DR);
+ break;
+
case VM_REG_GUEST_DR7:
state->dr7 = val;
+ svm_set_dirty(sc, vcpu, VMCB_CACHE_DR);
break;
case VM_REG_GUEST_EFER:
Index: sys/amd64/vmm/intel/vmx.h
===================================================================
--- sys/amd64/vmm/intel/vmx.h
+++ sys/amd64/vmm/intel/vmx.h
@@ -50,6 +50,11 @@
register_t guest_r14;
register_t guest_r15;
register_t guest_cr2;
+ register_t guest_dr0;
+ register_t guest_dr1;
+ register_t guest_dr2;
+ register_t guest_dr3;
+ register_t guest_dr6;
register_t host_r15; /* Host state */
register_t host_r14;
@@ -58,9 +63,14 @@
register_t host_rbp;
register_t host_rsp;
register_t host_rbx;
- /*
- * XXX todo debug registers and fpu state
- */
+ register_t host_dr0;
+ register_t host_dr1;
+ register_t host_dr2;
+ register_t host_dr3;
+ register_t host_dr6;
+ register_t host_dr7;
+ uint64_t host_debugctl;
+ int host_tf;
int inst_fail_status;
Index: sys/amd64/vmm/intel/vmx.c
===================================================================
--- sys/amd64/vmm/intel/vmx.c
+++ sys/amd64/vmm/intel/vmx.c
@@ -96,18 +96,20 @@
#define PROCBASED_CTLS2_ZERO_SETTING 0
#define VM_EXIT_CTLS_ONE_SETTING \
- (VM_EXIT_HOST_LMA | \
+ (VM_EXIT_SAVE_DEBUG_CONTROLS | \
+ VM_EXIT_HOST_LMA | \
VM_EXIT_SAVE_EFER | \
VM_EXIT_LOAD_EFER | \
VM_EXIT_ACKNOWLEDGE_INTERRUPT)
-#define VM_EXIT_CTLS_ZERO_SETTING VM_EXIT_SAVE_DEBUG_CONTROLS
+#define VM_EXIT_CTLS_ZERO_SETTING 0
-#define VM_ENTRY_CTLS_ONE_SETTING (VM_ENTRY_LOAD_EFER)
+#define VM_ENTRY_CTLS_ONE_SETTING \
+ (VM_ENTRY_LOAD_DEBUG_CONTROLS | \
+ VM_ENTRY_LOAD_EFER)
#define VM_ENTRY_CTLS_ZERO_SETTING \
- (VM_ENTRY_LOAD_DEBUG_CONTROLS | \
- VM_ENTRY_INTO_SMM | \
+ (VM_ENTRY_INTO_SMM | \
VM_ENTRY_DEACTIVATE_DUAL_MONITOR)
#define HANDLED 1
@@ -2569,6 +2571,73 @@
}
}
+static __inline void
+vmx_dr_enter_guest(struct vmxctx *vmxctx)
+{
+ register_t rflags;
+
+ /* Save host control debug registers. */
+ vmxctx->host_dr7 = rdr7();
+ vmxctx->host_debugctl = rdmsr(MSR_DEBUGCTLMSR);
+
+ /*
+ * Disable debugging in DR7 and DEBUGCTL to avoid triggering
+ * exceptions in the host based on the guest DRx values. The
+ * guest DR7 and DEBUGCTL are saved/restored in the VMCS.
+ */
+ load_dr7(0);
+ wrmsr(MSR_DEBUGCTLMSR, 0);
+
+ /*
+ * Disable single stepping the kernel to avoid corrupting the
+ * guest DR6. A debugger might still be able to corrupt the
+ * guest DR6 by setting a breakpoint after this point and then
+ * single stepping.
+ */
+ rflags = read_rflags();
+ vmxctx->host_tf = rflags & PSL_T;
+ write_rflags(rflags & ~PSL_T);
+
+ /* Save host debug registers. */
+ vmxctx->host_dr0 = rdr0();
+ vmxctx->host_dr1 = rdr1();
+ vmxctx->host_dr2 = rdr2();
+ vmxctx->host_dr3 = rdr3();
+ vmxctx->host_dr6 = rdr6();
+
+ /* Restore guest debug registers. */
+ load_dr0(vmxctx->guest_dr0);
+ load_dr1(vmxctx->guest_dr1);
+ load_dr2(vmxctx->guest_dr2);
+ load_dr3(vmxctx->guest_dr3);
+ load_dr6(vmxctx->guest_dr6);
+}
+
+static __inline void
+vmx_dr_leave_guest(struct vmxctx *vmxctx)
+{
+
+ /* Save guest debug registers. */
+ vmxctx->guest_dr0 = rdr0();
+ vmxctx->guest_dr1 = rdr1();
+ vmxctx->guest_dr2 = rdr2();
+ vmxctx->guest_dr3 = rdr3();
+ vmxctx->guest_dr6 = rdr6();
+
+ /*
+ * Restore host debug registers. Restore DR7, DEBUGCTL, and
+ * PSL_T last.
+ */
+ load_dr0(vmxctx->host_dr0);
+ load_dr1(vmxctx->host_dr1);
+ load_dr2(vmxctx->host_dr2);
+ load_dr3(vmxctx->host_dr3);
+ load_dr6(vmxctx->host_dr6);
+ wrmsr(MSR_DEBUGCTLMSR, vmxctx->host_debugctl);
+ load_dr7(vmxctx->host_dr7);
+ write_rflags(read_rflags() | vmxctx->host_tf);
+}
+
static int
vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap,
struct vm_eventinfo *evinfo)
@@ -2667,7 +2736,9 @@
}
vmx_run_trace(vmx, vcpu);
+ vmx_dr_enter_guest(vmxctx);
rc = vmx_enter_guest(vmxctx, vmx, launched);
+ vmx_dr_leave_guest(vmxctx);
/* Collect some information for VM exit processing */
vmexit->rip = rip = vmcs_guest_rip();
@@ -2767,6 +2838,16 @@
return (&vmxctx->guest_r15);
case VM_REG_GUEST_CR2:
return (&vmxctx->guest_cr2);
+ case VM_REG_GUEST_DR0:
+ return (&vmxctx->guest_dr0);
+ case VM_REG_GUEST_DR1:
+ return (&vmxctx->guest_dr1);
+ case VM_REG_GUEST_DR2:
+ return (&vmxctx->guest_dr2);
+ case VM_REG_GUEST_DR3:
+ return (&vmxctx->guest_dr3);
+ case VM_REG_GUEST_DR6:
+ return (&vmxctx->guest_dr6);
default:
break;
}
Index: usr.sbin/bhyvectl/bhyvectl.c
===================================================================
--- usr.sbin/bhyvectl/bhyvectl.c
+++ usr.sbin/bhyvectl/bhyvectl.c
@@ -111,6 +111,16 @@
" [--get-cr3]\n"
" [--set-cr4=<CR4>]\n"
" [--get-cr4]\n"
+ " [--set-dr0=<DR0>]\n"
+ " [--get-dr0]\n"
+ " [--set-dr1=<DR1>]\n"
+ " [--get-dr1]\n"
+ " [--set-dr2=<DR2>]\n"
+ " [--get-dr2]\n"
+ " [--set-dr3=<DR3>]\n"
+ " [--get-dr3]\n"
+ " [--set-dr6=<DR6>]\n"
+ " [--get-dr6]\n"
" [--set-dr7=<DR7>]\n"
" [--get-dr7]\n"
" [--set-rsp=<RSP>]\n"
@@ -244,6 +254,11 @@
static uint64_t memsize;
static int set_cr0, get_cr0, set_cr3, get_cr3, set_cr4, get_cr4;
static int set_efer, get_efer;
+static int set_dr0, get_dr0;
+static int set_dr1, get_dr1;
+static int set_dr2, get_dr2;
+static int set_dr3, get_dr3;
+static int set_dr6, get_dr6;
static int set_dr7, get_dr7;
static int set_rsp, get_rsp, set_rip, get_rip, set_rflags, get_rflags;
static int set_rax, get_rax;
@@ -536,6 +551,11 @@
SET_CR0,
SET_CR3,
SET_CR4,
+ SET_DR0,
+ SET_DR1,
+ SET_DR2,
+ SET_DR3,
+ SET_DR6,
SET_DR7,
SET_RSP,
SET_RIP,
@@ -640,7 +660,8 @@
static int
get_all_registers(struct vmctx *ctx, int vcpu)
{
- uint64_t cr0, cr3, cr4, dr7, rsp, rip, rflags, efer;
+ uint64_t cr0, cr3, cr4, dr0, dr1, dr2, dr3, dr6, dr7;
+ uint64_t rsp, rip, rflags, efer;
uint64_t rax, rbx, rcx, rdx, rsi, rdi, rbp;
uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
int error = 0;
@@ -669,6 +690,36 @@
printf("cr4[%d]\t\t0x%016lx\n", vcpu, cr4);
}
+ if (!error && (get_dr0 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR0, &dr0);
+ if (error == 0)
+ printf("dr0[%d]\t\t0x%016lx\n", vcpu, dr0);
+ }
+
+ if (!error && (get_dr1 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR1, &dr1);
+ if (error == 0)
+ printf("dr1[%d]\t\t0x%016lx\n", vcpu, dr1);
+ }
+
+ if (!error && (get_dr2 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR2, &dr2);
+ if (error == 0)
+ printf("dr2[%d]\t\t0x%016lx\n", vcpu, dr2);
+ }
+
+ if (!error && (get_dr3 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR3, &dr3);
+ if (error == 0)
+ printf("dr3[%d]\t\t0x%016lx\n", vcpu, dr3);
+ }
+
+ if (!error && (get_dr6 || get_all)) {
+ error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR6, &dr6);
+ if (error == 0)
+ printf("dr6[%d]\t\t0x%016lx\n", vcpu, dr6);
+ }
+
if (!error && (get_dr7 || get_all)) {
error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR7, &dr7);
if (error == 0)
@@ -1271,6 +1322,11 @@
{ "set-cr0", REQ_ARG, 0, SET_CR0 },
{ "set-cr3", REQ_ARG, 0, SET_CR3 },
{ "set-cr4", REQ_ARG, 0, SET_CR4 },
+ { "set-dr0", REQ_ARG, 0, SET_DR0 },
+ { "set-dr1", REQ_ARG, 0, SET_DR1 },
+ { "set-dr2", REQ_ARG, 0, SET_DR2 },
+ { "set-dr3", REQ_ARG, 0, SET_DR3 },
+ { "set-dr6", REQ_ARG, 0, SET_DR6 },
{ "set-dr7", REQ_ARG, 0, SET_DR7 },
{ "set-rsp", REQ_ARG, 0, SET_RSP },
{ "set-rip", REQ_ARG, 0, SET_RIP },
@@ -1328,6 +1384,11 @@
{ "get-cr0", NO_ARG, &get_cr0, 1 },
{ "get-cr3", NO_ARG, &get_cr3, 1 },
{ "get-cr4", NO_ARG, &get_cr4, 1 },
+ { "get-dr0", NO_ARG, &get_dr0, 1 },
+ { "get-dr1", NO_ARG, &get_dr1, 1 },
+ { "get-dr2", NO_ARG, &get_dr2, 1 },
+ { "get-dr3", NO_ARG, &get_dr3, 1 },
+ { "get-dr6", NO_ARG, &get_dr6, 1 },
{ "get-dr7", NO_ARG, &get_dr7, 1 },
{ "get-rsp", NO_ARG, &get_rsp, 1 },
{ "get-rip", NO_ARG, &get_rip, 1 },
@@ -1605,7 +1666,8 @@
int error, ch, vcpu, ptenum;
vm_paddr_t gpa_pmap;
struct vm_exit vmexit;
- uint64_t rax, cr0, cr3, cr4, dr7, rsp, rip, rflags, efer, pat;
+ uint64_t rax, cr0, cr3, cr4, dr0, dr1, dr2, dr3, dr6, dr7;
+ uint64_t rsp, rip, rflags, efer, pat;
uint64_t eptp, bm, addr, u64, pteval[4], *pte, info[2];
struct vmctx *ctx;
cpuset_t cpus;
@@ -1652,6 +1714,26 @@
cr4 = strtoul(optarg, NULL, 0);
set_cr4 = 1;
break;
+ case SET_DR0:
+ dr0 = strtoul(optarg, NULL, 0);
+ set_dr0 = 1;
+ break;
+ case SET_DR1:
+ dr1 = strtoul(optarg, NULL, 0);
+ set_dr1 = 1;
+ break;
+ case SET_DR2:
+ dr2 = strtoul(optarg, NULL, 0);
+ set_dr2 = 1;
+ break;
+ case SET_DR3:
+ dr3 = strtoul(optarg, NULL, 0);
+ set_dr3 = 1;
+ break;
+ case SET_DR6:
+ dr6 = strtoul(optarg, NULL, 0);
+ set_dr6 = 1;
+ break;
case SET_DR7:
dr7 = strtoul(optarg, NULL, 0);
set_dr7 = 1;
@@ -1793,6 +1875,21 @@
if (!error && set_cr4)
error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR4, cr4);
+ if (!error && set_dr0)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR0, dr0);
+
+ if (!error && set_dr1)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR1, dr1);
+
+ if (!error && set_dr2)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR2, dr2);
+
+ if (!error && set_dr3)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR3, dr3);
+
+ if (!error && set_dr6)
+ error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR6, dr6);
+
if (!error && set_dr7)
error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR7, dr7);

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 2, 10:56 AM (12 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28412484
Default Alt Text
D13229.id35695.diff (13 KB)

Event Timeline