[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




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.