[PATCH v4 3/6] KVM: x86: Ignore CR0.WP toggles in non-paging mode

Mathias Krause
2023-03-22T01:34:45Z

If paging is disabled, there are no permission bits to emulate.
Micro-optimize this case to avoid unnecessary work.

Suggested-and-co-developed-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Mathias Krause <minipli@grsecurity.net>
---
arch/x86/kvm/x86.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c6d909778b2c..8a66ac7a4878 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -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) {
--
2.39.2