]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: x86/mmu: hard code more bits in kvm_init_shadow_npt_mmu
authorPaolo Bonzini <pbonzini@redhat.com>
Mon, 27 Apr 2026 15:30:56 +0000 (11:30 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Sun, 10 May 2026 12:55:08 +0000 (14:55 +0200)
The host CR0 does not really reflect onto the NPT format because
hCR0.PG=1 must be set and hCR0.WP is ignored.  Carve that in stone
by removing the cr0 argument from kvm_init_shadow_npt_mmu.

Pass in WP=1 as well; it does not matter for GMET disabled because
PFERR_USER_MASK is always set, but a cleared W bit in the nested page
tables cannot be overridden in supervisor mode when GMET is enabled,
either.  In fact, since CR0.WP=0 is the weird "extra accesses allowed"
mode, it is acutally easier think about it being always set.

Likewise, clear X86_CR4_SMAP to avoid that KVM erroneously faults on
supervisor accesses to an U=1 page.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/mmu.h
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/svm/nested.c

index e1e3869f568b5101ca99a238b44680529838395c..1b354e1f2d812f34286446f33be3df6ba5f5dc47 100644 (file)
@@ -96,8 +96,8 @@ void kvm_mmu_set_me_spte_mask(u64 me_value, u64 me_mask);
 void kvm_mmu_set_ept_masks(bool has_ad_bits);
 
 void kvm_init_mmu(struct kvm_vcpu *vcpu);
-void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0,
-                            unsigned long cr4, u64 efer, gpa_t nested_cr3);
+void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr4,
+                            u64 efer, gpa_t nested_cr3);
 void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly,
                             int huge_page_level, bool accessed_dirty,
                             bool mbec, gpa_t new_eptp);
index 1860e4f3fb008391c1c650e3ff4bbdc4547b5861..b8ff834abf8861055969c71e86e2c3ff2df74150 100644 (file)
@@ -5939,13 +5939,13 @@ static void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu,
        shadow_mmu_init_context(vcpu, context, cpu_role, root_role);
 }
 
-void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0,
-                            unsigned long cr4, u64 efer, gpa_t nested_cr3)
+void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr4,
+                            u64 efer, gpa_t nested_cr3)
 {
        struct kvm_mmu *context = &vcpu->arch.guest_mmu;
        struct kvm_mmu_role_regs regs = {
-               .cr0 = cr0,
-               .cr4 = cr4 & ~X86_CR4_PKE,
+               .cr0 = X86_CR0_PG | X86_CR0_WP,
+               .cr4 = cr4 & ~(X86_CR4_PKE | X86_CR4_SMAP),
                .efer = efer,
        };
        union kvm_cpu_role cpu_role = kvm_calc_cpu_role(vcpu, &regs);
index df232153eb247f2b6b69aaaa0c97feded8d662e8..a1cffd27400052b552b36046d3884a1dd81c4716 100644 (file)
@@ -93,7 +93,7 @@ static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
         * when called via KVM_SET_NESTED_STATE, that state may _not_ match current
         * vCPU state.  CR0.WP is explicitly ignored, while CR0.PG is required.
         */
-       kvm_init_shadow_npt_mmu(vcpu, X86_CR0_PG, svm->vmcb01.ptr->save.cr4,
+       kvm_init_shadow_npt_mmu(vcpu, svm->vmcb01.ptr->save.cr4,
                                svm->vmcb01.ptr->save.efer,
                                svm->nested.ctl.nested_cr3);
        vcpu->arch.mmu->get_guest_pgd     = nested_svm_get_tdp_cr3;