summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2018-10-11 18:27:19 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2018-10-11 18:27:19 +0000
commitb843f9be5e77e2ff653d12965351239811a61b1c (patch)
tree3d73af5b415531ec930fdb4f4cc734b98fb8c4ca
parentbd52a4d9e3ec2f5de2b73cb425c1f22f65d9fbd6 (diff)
downloadsrc-test2-b843f9be5e77e2ff653d12965351239811a61b1c.tar.gz
src-test2-b843f9be5e77e2ff653d12965351239811a61b1c.zip
Notes
-rw-r--r--sys/amd64/include/cpufunc.h9
-rw-r--r--sys/amd64/vmm/intel/vmx.c22
2 files changed, 31 insertions, 0 deletions
diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h
index a0ea1b2f1701..e04e50cfe19f 100644
--- a/sys/amd64/include/cpufunc.h
+++ b/sys/amd64/include/cpufunc.h
@@ -730,6 +730,15 @@ lldt(u_short sel)
__asm __volatile("lldt %0" : : "r" (sel));
}
+static __inline u_short
+sldt(void)
+{
+ u_short sel;
+
+ __asm __volatile("sldt %0" : "=r" (sel));
+ return (sel);
+}
+
static __inline void
ltr(u_short sel)
{
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 61871e9338eb..f138e57130df 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -2833,6 +2833,8 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap,
struct vm_exit *vmexit;
struct vlapic *vlapic;
uint32_t exit_reason;
+ struct region_descriptor gdtr, idtr;
+ uint16_t ldt_sel;
vmx = arg;
vm = vmx->vm;
@@ -2924,11 +2926,31 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap,
break;
}
+ /*
+ * VM exits restore the base address but not the
+ * limits of GDTR and IDTR. The VMCS only stores the
+ * base address, so VM exits set the limits to 0xffff.
+ * Save and restore the full GDTR and IDTR to restore
+ * the limits.
+ *
+ * The VMCS does not save the LDTR at all, and VM
+ * exits clear LDTR as if a NULL selector were loaded.
+ * The userspace hypervisor probably doesn't use a
+ * LDT, but save and restore it to be safe.
+ */
+ sgdt(&gdtr);
+ sidt(&idtr);
+ ldt_sel = sldt();
+
vmx_run_trace(vmx, vcpu);
vmx_dr_enter_guest(vmxctx);
rc = vmx_enter_guest(vmxctx, vmx, launched);
vmx_dr_leave_guest(vmxctx);
+ bare_lgdt(&gdtr);
+ lidt(&idtr);
+ lldt(ldt_sel);
+
/* Collect some information for VM exit processing */
vmexit->rip = rip = vmcs_guest_rip();
vmexit->inst_length = vmexit_instruction_length();