aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2019-04-15 09:57:19 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2019-04-16 09:37:12 -0400
commit2b27924bb1d48e3775f432b70bdad5e6dd4e7798 (patch)
treef93f3634ecc1f4d83e7d3ebbd923078b3c46e675
parent690908104e39d37947f89d76388c876ce4ec5fda (diff)
KVM: nVMX: always use early vmcs check when EPT is disabled
The remaining failures of vmx.flat when EPT is disabled are caused by incorrectly reflecting VMfails to the L1 hypervisor. What happens is that nested_vmx_restore_host_state corrupts the guest CR3, reloading it with the host's shadow CR3 instead, because it blindly loads GUEST_CR3 from the vmcs01. For simplicity let's just always use hardware VMCS checks when EPT is disabled. This way, nested_vmx_restore_host_state is not reached at all (or at least shouldn't be reached). Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/include/uapi/asm/vmx.h1
-rw-r--r--arch/x86/kvm/vmx/nested.c22
2 files changed, 21 insertions, 2 deletions
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
index f0b0c90dd398..d213ec5c3766 100644
--- a/arch/x86/include/uapi/asm/vmx.h
+++ b/arch/x86/include/uapi/asm/vmx.h
@@ -146,6 +146,7 @@
146 146
147#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1 147#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
148#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2 148#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
149#define VMX_ABORT_VMCS_CORRUPTED 3
149#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4 150#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
150 151
151#endif /* _UAPIVMX_H */ 152#endif /* _UAPIVMX_H */
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index a22af5a85540..6401eb7ef19c 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -3796,8 +3796,18 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
3796 vmx_set_cr4(vcpu, vmcs_readl(CR4_READ_SHADOW)); 3796 vmx_set_cr4(vcpu, vmcs_readl(CR4_READ_SHADOW));
3797 3797
3798 nested_ept_uninit_mmu_context(vcpu); 3798 nested_ept_uninit_mmu_context(vcpu);
3799 vcpu->arch.cr3 = vmcs_readl(GUEST_CR3); 3799
3800 __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail); 3800 /*
3801 * This is only valid if EPT is in use, otherwise the vmcs01 GUEST_CR3
3802 * points to shadow pages! Fortunately we only get here after a WARN_ON
3803 * if EPT is disabled, so a VMabort is perfectly fine.
3804 */
3805 if (enable_ept) {
3806 vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
3807 __set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
3808 } else {
3809 nested_vmx_abort(vcpu, VMX_ABORT_VMCS_CORRUPTED);
3810 }
3801 3811
3802 /* 3812 /*
3803 * Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs 3813 * Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs
@@ -5745,6 +5755,14 @@ __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *))
5745{ 5755{
5746 int i; 5756 int i;
5747 5757
5758 /*
5759 * Without EPT it is not possible to restore L1's CR3 and PDPTR on
5760 * VMfail, because they are not available in vmcs01. Just always
5761 * use hardware checks.
5762 */
5763 if (!enable_ept)
5764 nested_early_check = 1;
5765
5748 if (!cpu_has_vmx_shadow_vmcs()) 5766 if (!cpu_has_vmx_shadow_vmcs())
5749 enable_shadow_vmcs = 0; 5767 enable_shadow_vmcs = 0;
5750 if (enable_shadow_vmcs) { 5768 if (enable_shadow_vmcs) {