KVM: vmx, svm: always run with EFER.NXE=1 when shadow paging is active
authorPaolo Bonzini <pbonzini@redhat.com>
Sun, 27 Oct 2019 15:23:23 +0000 (16:23 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 16 Nov 2019 09:29:53 +0000 (10:29 +0100)
commit 9167ab79936206118cc60e47dcb926c3489f3bd5 upstream.

VMX already does so if the host has SMEP, in order to support the combination of
CR0.WP=1 and CR4.SMEP=1.  However, it is perfectly safe to always do so, and in
fact VMX already ends up running with EFER.NXE=1 on old processors that lack the
"load EFER" controls, because it may help avoiding a slow MSR write.  Removing
all the conditionals simplifies the code.

SVM does not have similar code, but it should since recent AMD processors do
support SMEP.  So this patch also makes the code for the two vendors more similar
while fixing NPT=0, CR0.WP=1 and CR4.SMEP=1 on AMD processors.

Cc: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[bwh: Backported to 4.9: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c

index f7a7b98b3271a6fc5df234854d86174c8222a5a0..1079228e4fefffbf8a2abbd69244d7e82dbc1c08 100644 (file)
@@ -590,8 +590,14 @@ static int get_npt_level(void)
 static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
 {
        vcpu->arch.efer = efer;
-       if (!npt_enabled && !(efer & EFER_LMA))
-               efer &= ~EFER_LME;
+
+       if (!npt_enabled) {
+               /* Shadow paging assumes NX to be available.  */
+               efer |= EFER_NX;
+
+               if (!(efer & EFER_LMA))
+                       efer &= ~EFER_LME;
+       }
 
        to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME;
        mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
index 2d8378d5832f3c29cf96c72d11649f868fd4be37..4c0d6d0d6337f0cbe2fde4796a95dfe5c1ecfc7f 100644 (file)
@@ -2219,17 +2219,9 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
        u64 guest_efer = vmx->vcpu.arch.efer;
        u64 ignore_bits = 0;
 
-       if (!enable_ept) {
-               /*
-                * NX is needed to handle CR0.WP=1, CR4.SMEP=1.  Testing
-                * host CPUID is more efficient than testing guest CPUID
-                * or CR4.  Host SMEP is anyway a requirement for guest SMEP.
-                */
-               if (boot_cpu_has(X86_FEATURE_SMEP))
-                       guest_efer |= EFER_NX;
-               else if (!(guest_efer & EFER_NX))
-                       ignore_bits |= EFER_NX;
-       }
+       /* Shadow paging assumes NX to be available.  */
+       if (!enable_ept)
+               guest_efer |= EFER_NX;
 
        /*
         * LMA and LME handled by hardware; SCE meaningless outside long mode.