KVM: x86: Ignore CR0.WP toggles in non-paging mode
authorMathias Krause <minipli@grsecurity.net>
Wed, 22 Mar 2023 01:37:28 +0000 (02:37 +0100)
committerSean Christopherson <seanjc@google.com>
Wed, 22 Mar 2023 14:47:24 +0000 (07:47 -0700)
If paging is disabled, there are no permission bits to emulate.
Micro-optimize this case to avoid unnecessary work.

Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Mathias Krause <minipli@grsecurity.net>
Link: https://lore.kernel.org/r/20230322013731.102955-4-minipli@grsecurity.net
Co-developed-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/x86.c

index c6d9097..8a66ac7 100644 (file)
@@ -908,14 +908,20 @@ void kvm_post_set_cr0(struct kvm_vcpu *vcpu, unsigned long old_cr0, unsigned lon
 {
        /*
         * CR0.WP is incorporated into the MMU role, but only for non-nested,
-        * indirect shadow MMUs.  If TDP is enabled, the MMU's metadata needs
-        * to be updated, e.g. so that emulating guest translations does the
-        * right thing, but there's no need to unload the root as CR0.WP
-        * doesn't affect SPTEs.
+        * indirect shadow MMUs.  If paging is disabled, no updates are needed
+        * as there are no permission bits to emulate.  If TDP is enabled, the
+        * MMU's metadata needs to be updated, e.g. so that emulating guest
+        * translations does the right thing, but there's no need to unload the
+        * root as CR0.WP doesn't affect SPTEs.
         */
-       if (tdp_enabled && (cr0 ^ old_cr0) == X86_CR0_WP) {
-               kvm_init_mmu(vcpu);
-               return;
+       if ((cr0 ^ old_cr0) == X86_CR0_WP) {
+               if (!(cr0 & X86_CR0_PG))
+                       return;
+
+               if (tdp_enabled) {
+                       kvm_init_mmu(vcpu);
+                       return;
+               }
        }
 
        if ((cr0 ^ old_cr0) & X86_CR0_PG) {