|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] x86/nestedhvm: load host state at virtual VM exit as the SDM does
load_vvmcs_host_state() leaves the GDTR and IDTR limits at L1's earlier
values instead of 0xffff, and zeroes the VM-entry interruption-information
field, of which a VM exit clears only the valid bit. It also never brings
L1's EFER up to date. With "load IA32_EFER" L1 keeps L2's EFER.SCE and
EFER.NXE instead of HOST_EFER's, and without it L1 gets its own earlier
EFER back instead of keeping L2's.
Fixes: 9390642b7fa5 ("Nested VMX: Switch shadow/virtual VMCS between n1/n2
guests.")
Signed-off-by: Mahmoud Abumandour <ma.mandourr@xxxxxxxxx>
---
xen/arch/x86/hvm/vmx/vvmx.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 29e48387a1..fc2cf08fef 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1317,9 +1317,24 @@ static void load_vvmcs_host_state(struct vcpu *v)
if ( rc == X86EMUL_EXCEPTION )
hvm_inject_hw_exception(X86_EXC_GP, 0);
+ /* SDM 28.5.2 (Loading Host Segment and Descriptor-Table Registers). */
+ __vmwrite(GUEST_GDTR_LIMIT, 0xffff);
+ __vmwrite(GUEST_IDTR_LIMIT, 0xffff);
+
control = get_vvmcs(v, VM_EXIT_CONTROLS);
if ( control & VM_EXIT_LOAD_HOST_PAT )
hvm_set_guest_pat(v, get_vvmcs(v, HOST_PAT));
+
+ /*
+ * LMA and LME follow "host address-space size" (virtual_vmexit()); the
+ * other bits are HOST_EFER's with "load IA32_EFER", and L2's without.
+ */
+ if ( control & VM_EXIT_LOAD_HOST_EFER )
+ v->arch.hvm.guest_efer =
+ (get_vvmcs(v, HOST_EFER) & ~(EFER_LMA | EFER_LME)) |
+ (v->arch.hvm.guest_efer & (EFER_LMA | EFER_LME));
+ hvm_update_guest_efer(v);
+
if ( control & VM_EXIT_LOAD_PERF_GLOBAL_CTRL )
{
rc = hvm_msr_write_intercept(MSR_CORE_PERF_GLOBAL_CTRL,
@@ -1330,7 +1345,9 @@ static void load_vvmcs_host_state(struct vcpu *v)
hvm_set_tsc_offset(v, v->arch.hvm.cache_tsc_offset);
- set_vvmcs(v, VM_ENTRY_INTR_INFO, 0);
+ /* A VM exit clears only the valid bit of this entry control. */
+ set_vvmcs(v, VM_ENTRY_INTR_INFO,
+ get_vvmcs(v, VM_ENTRY_INTR_INFO) & ~INTR_INFO_VALID_MASK);
if ( v->arch.hvm.vmx.exec_control & CPU_BASED_ACTIVATE_MSR_BITMAP )
__vmwrite(MSR_BITMAP, virt_to_maddr(v->arch.hvm.vmx.msr_bitmap));
--
2.25.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |