Skip to content

Commit

Permalink
KVM: nVMX: always use early vmcs check when EPT is disabled
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
bonzini committed Apr 16, 2019
1 parent 6909081 commit 2b27924
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
1 change: 1 addition & 0 deletions arch/x86/include/uapi/asm/vmx.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@

#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
#define VMX_ABORT_VMCS_CORRUPTED 3
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4

#endif /* _UAPIVMX_H */
22 changes: 20 additions & 2 deletions arch/x86/kvm/vmx/nested.c
Original file line number Diff line number Diff line change
Expand Up @@ -3796,8 +3796,18 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
vmx_set_cr4(vcpu, vmcs_readl(CR4_READ_SHADOW));

nested_ept_uninit_mmu_context(vcpu);
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
__set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);

/*
* This is only valid if EPT is in use, otherwise the vmcs01 GUEST_CR3
* points to shadow pages! Fortunately we only get here after a WARN_ON
* if EPT is disabled, so a VMabort is perfectly fine.
*/
if (enable_ept) {
vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
__set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
} else {
nested_vmx_abort(vcpu, VMX_ABORT_VMCS_CORRUPTED);
}

/*
* Use ept_save_pdptrs(vcpu) to load the MMU's cached PDPTRs
Expand Down Expand Up @@ -5745,6 +5755,14 @@ __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *))
{
int i;

/*
* Without EPT it is not possible to restore L1's CR3 and PDPTR on
* VMfail, because they are not available in vmcs01. Just always
* use hardware checks.
*/
if (!enable_ept)
nested_early_check = 1;

if (!cpu_has_vmx_shadow_vmcs())
enable_shadow_vmcs = 0;
if (enable_shadow_vmcs) {
Expand Down

0 comments on commit 2b27924

Please sign in to comment.