Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143880572
D13229.id35695.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D13229.id35695.diff
View Options
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 (®ctx->sctx_r14);
case VM_REG_GUEST_R15:
return (®ctx->sctx_r15);
+ case VM_REG_GUEST_DR0:
+ return (®ctx->sctx_dr0);
+ case VM_REG_GUEST_DR1:
+ return (®ctx->sctx_dr1);
+ case VM_REG_GUEST_DR2:
+ return (®ctx->sctx_dr2);
+ case VM_REG_GUEST_DR3:
+ return (®ctx->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
Details
Attached
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)
Attached To
Mode
D13229: Save and restore guest debug registers.
Attached
Detach File
Event Timeline
Log In to Comment