KVM: VMX: fix SMEP and SMAP without EPT
authorRadim Krčmář <rkrcmar@redhat.com>
Mon, 2 Nov 2015 21:20:00 +0000 (22:20 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 4 Nov 2015 15:24:37 +0000 (16:24 +0100)
The comment in code had it mostly right, but we enable paging for
emulated real mode regardless of EPT.

Without EPT (which implies emulated real mode), secondary VCPUs won't
start unless we disable SM[AE]P when the guest doesn't use paging.

Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx.c

index 4d0aa31a42baa885851135b86c97420c946127af..2ac11641758374d4c15f8a29a4105a095395b5ff 100644 (file)
@@ -3788,20 +3788,21 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                if (!is_paging(vcpu)) {
                        hw_cr4 &= ~X86_CR4_PAE;
                        hw_cr4 |= X86_CR4_PSE;
-                       /*
-                        * SMEP/SMAP is disabled if CPU is in non-paging mode
-                        * in hardware. However KVM always uses paging mode to
-                        * emulate guest non-paging mode with TDP.
-                        * To emulate this behavior, SMEP/SMAP needs to be
-                        * manually disabled when guest switches to non-paging
-                        * mode.
-                        */
-                       hw_cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP);
                } else if (!(cr4 & X86_CR4_PAE)) {
                        hw_cr4 &= ~X86_CR4_PAE;
                }
        }
 
+       if (!enable_unrestricted_guest && !is_paging(vcpu))
+               /*
+                * SMEP/SMAP is disabled if CPU is in non-paging mode in
+                * hardware.  However KVM always uses paging mode without
+                * unrestricted guest.
+                * To emulate this behavior, SMEP/SMAP needs to be manually
+                * disabled when guest switches to non-paging mode.
+                */
+               hw_cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP);
+
        vmcs_writel(CR4_READ_SHADOW, cr4);
        vmcs_writel(GUEST_CR4, hw_cr4);
        return 0;