KVM: x86/mmu: load new PGD after the shadow MMU is initialized
authorPaolo Bonzini <pbonzini@redhat.com>
Fri, 4 Feb 2022 09:12:31 +0000 (04:12 -0500)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 21 Feb 2022 14:34:33 +0000 (09:34 -0500)
Now that __kvm_mmu_new_pgd does not look at the MMU's root_level and
shadow_root_level anymore, pull the PGD load after the initialization of
the shadow MMUs.

Besides being more intuitive, this enables future simplifications
and optimizations because it's not necessary anymore to compute the
role outside kvm_init_mmu.  In particular, kvm_mmu_reset_context was not
attempting to use a cached PGD to avoid having to figure out the new role.
With this change, it could follow what nested_{vmx,svm}_load_cr3 are doing,
and avoid unloading all the cached roots.

Reviewed-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/svm/nested.c
arch/x86/kvm/vmx/nested.c

index 9783d74b3f954f756716ec5839c1c7f45dea89dd..8464cd6814f2576f88c9992223f7a37d7b556cea 100644 (file)
@@ -4881,9 +4881,8 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0,
 
        new_role = kvm_calc_shadow_npt_root_page_role(vcpu, &regs);
 
-       __kvm_mmu_new_pgd(vcpu, nested_cr3, new_role.base);
-
        shadow_mmu_init_context(vcpu, context, &regs, new_role);
+       __kvm_mmu_new_pgd(vcpu, nested_cr3, new_role.base);
 }
 EXPORT_SYMBOL_GPL(kvm_init_shadow_npt_mmu);
 
@@ -4921,27 +4920,25 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly,
                kvm_calc_shadow_ept_root_page_role(vcpu, accessed_dirty,
                                                   execonly, level);
 
-       __kvm_mmu_new_pgd(vcpu, new_eptp, new_role.base);
-
-       if (new_role.as_u64 == context->mmu_role.as_u64)
-               return;
-
-       context->mmu_role.as_u64 = new_role.as_u64;
-
-       context->shadow_root_level = level;
-
-       context->ept_ad = accessed_dirty;
-       context->page_fault = ept_page_fault;
-       context->gva_to_gpa = ept_gva_to_gpa;
-       context->sync_page = ept_sync_page;
-       context->invlpg = ept_invlpg;
-       context->root_level = level;
-       context->direct_map = false;
+       if (new_role.as_u64 != context->mmu_role.as_u64) {
+               context->mmu_role.as_u64 = new_role.as_u64;
+
+               context->shadow_root_level = level;
+
+               context->ept_ad = accessed_dirty;
+               context->page_fault = ept_page_fault;
+               context->gva_to_gpa = ept_gva_to_gpa;
+               context->sync_page = ept_sync_page;
+               context->invlpg = ept_invlpg;
+               context->root_level = level;
+               context->direct_map = false;
+               update_permission_bitmask(context, true);
+               context->pkru_mask = 0;
+               reset_rsvds_bits_mask_ept(vcpu, context, execonly, huge_page_level);
+               reset_ept_shadow_zero_bits_mask(context, execonly);
+       }
 
-       update_permission_bitmask(context, true);
-       context->pkru_mask = 0;
-       reset_rsvds_bits_mask_ept(vcpu, context, execonly, huge_page_level);
-       reset_ept_shadow_zero_bits_mask(context, execonly);
+       __kvm_mmu_new_pgd(vcpu, new_eptp, new_role.base);
 }
 EXPORT_SYMBOL_GPL(kvm_init_shadow_ept_mmu);
 
index f284e61451c872b776b95b43fed095236fab7bec..96bab464967f24cdbeb22f987932abc92a527c74 100644 (file)
@@ -492,14 +492,14 @@ static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
            CC(!load_pdptrs(vcpu, cr3)))
                return -EINVAL;
 
-       if (!nested_npt)
-               kvm_mmu_new_pgd(vcpu, cr3);
-
        vcpu->arch.cr3 = cr3;
 
        /* Re-initialize the MMU, e.g. to pick up CR4 MMU role changes. */
        kvm_init_mmu(vcpu);
 
+       if (!nested_npt)
+               kvm_mmu_new_pgd(vcpu, cr3);
+
        return 0;
 }
 
index b7bc634d35e2ad5bf832dc4e500e6ffa6e60d901..1dfe23963a9e6b09d14ca71d8ecd506995a82bdb 100644 (file)
@@ -1126,15 +1126,15 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
                return -EINVAL;
        }
 
-       if (!nested_ept)
-               kvm_mmu_new_pgd(vcpu, cr3);
-
        vcpu->arch.cr3 = cr3;
        kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3);
 
        /* Re-initialize the MMU, e.g. to pick up CR4 MMU role changes. */
        kvm_init_mmu(vcpu);
 
+       if (!nested_ept)
+               kvm_mmu_new_pgd(vcpu, cr3);
+
        return 0;
 }