diff options
author | John Baldwin <jhb@FreeBSD.org> | 2018-10-11 18:27:19 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2018-10-11 18:27:19 +0000 |
commit | b843f9be5e77e2ff653d12965351239811a61b1c (patch) | |
tree | 3d73af5b415531ec930fdb4f4cc734b98fb8c4ca | |
parent | bd52a4d9e3ec2f5de2b73cb425c1f22f65d9fbd6 (diff) | |
download | src-test2-b843f9be5e77e2ff653d12965351239811a61b1c.tar.gz src-test2-b843f9be5e77e2ff653d12965351239811a61b1c.zip |
Notes
-rw-r--r-- | sys/amd64/include/cpufunc.h | 9 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vmx.c | 22 |
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(); |