From: "Edgecombe, Rick P" Disallow page merging (huge page adjustment) for the mirror root by utilizing disallowed_hugepage_adjust(). Make the mirror root check asymmetric with NX huge pages and not to litter the generic MMU code: Invoke disallowed_hugepage_adjust() in kvm_tdp_mmu_map() when necessary, specifically when KVM has mirrored TDP or the NX huge page workaround is enabled. Check and reduce the goal_level of a fault internally in disallowed_hugepage_adjust() when the fault is for a mirror root and there's a shadow present non-leaf entry at the original goal_level. Signed-off-by: Edgecombe, Rick P Co-developed-by: Yan Zhao Signed-off-by: Yan Zhao --- RFC v2: - Check is_mirror_sp() in disallowed_hugepage_adjust() instead of passing in an is_mirror arg. (Rick) - Check kvm_has_mirrored_tdp() in kvm_tdp_mmu_map() to determine whether to invoke disallowed_hugepage_adjust(). (Rick) RFC v1: - new patch --- arch/x86/kvm/mmu/mmu.c | 3 ++- arch/x86/kvm/mmu/tdp_mmu.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 3f76415cec71..9182192daa3a 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -3412,7 +3412,8 @@ void disallowed_hugepage_adjust(struct kvm_page_fault *fault, u64 spte, int cur_ cur_level == fault->goal_level && is_shadow_present_pte(spte) && !is_large_pte(spte) && - spte_to_child_sp(spte)->nx_huge_page_disallowed) { + ((spte_to_child_sp(spte)->nx_huge_page_disallowed) || + is_mirror_sp(spte_to_child_sp(spte)))) { /* * A small SPTE exists for this pfn, but FNAME(fetch), * direct_map(), or kvm_tdp_mmu_map() would like to create a diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index bb95c95f6531..f9a054754544 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1243,6 +1243,8 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) struct tdp_iter iter; struct kvm_mmu_page *sp; int ret = RET_PF_RETRY; + bool hugepage_adjust_disallowed = fault->nx_huge_page_workaround_enabled || + kvm_has_mirrored_tdp(kvm); kvm_mmu_hugepage_adjust(vcpu, fault); @@ -1253,7 +1255,7 @@ int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) for_each_tdp_pte(iter, kvm, root, fault->gfn, fault->gfn + 1) { int r; - if (fault->nx_huge_page_workaround_enabled) + if (hugepage_adjust_disallowed) disallowed_hugepage_adjust(fault, iter.old_spte, iter.level); /* -- 2.43.2