Reload the LDT selector after an AMD-v #VMEXIT.

cpu_switch() always reloads the LDT, so this can only affect the
hypervisor process itself.  Fix this by explicitly reloading the host
LDT selector after each #VMEXIT.  The stock bhyve process on FreeBSD
never uses a custom LDT, so this change is cosmetic.

Reviewed by:	kib
Tested by:	Mike Tancsa <mike@sentex.net>
Approved by:	re (gjb)
MFC after:	2 weeks
This commit is contained in:
John Baldwin 2018-10-15 18:12:25 +00:00
parent 1d7da823b4
commit de679f6efa
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339364

View file

@ -1940,6 +1940,7 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
struct vm *vm; struct vm *vm;
uint64_t vmcb_pa; uint64_t vmcb_pa;
int handled; int handled;
uint16_t ldt_sel;
svm_sc = arg; svm_sc = arg;
vm = svm_sc->vm; vm = svm_sc->vm;
@ -2024,6 +2025,15 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
break; break;
} }
/*
* #VMEXIT resumes the host with the guest LDTR, so
* save the current LDT selector so it can be restored
* after an exit. The userspace hypervisor probably
* doesn't use a LDT, but save and restore it to be
* safe.
*/
ldt_sel = sldt();
svm_inj_interrupts(svm_sc, vcpu, vlapic); svm_inj_interrupts(svm_sc, vcpu, vlapic);
/* Activate the nested pmap on 'curcpu' */ /* Activate the nested pmap on 'curcpu' */
@ -2054,6 +2064,9 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
*/ */
restore_host_tss(); restore_host_tss();
/* Restore host LDTR. */
lldt(ldt_sel);
/* #VMEXIT disables interrupts so re-enable them here. */ /* #VMEXIT disables interrupts so re-enable them here. */
enable_gintr(); enable_gintr();