From: Sean Christopherson <[email protected]>

Introduce a helper to directly (pun intented) fault-in a TDP page
without having to go through the full page fault path.  This allows
TDX to get the resulting pfn and also allows the RET_PF_* enums to
stay in mmu.c where they belong.

Signed-off-by: Sean Christopherson <[email protected]>
---
 arch/x86/kvm/mmu.h     |  3 +++
 arch/x86/kvm/mmu/mmu.c | 25 +++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 3b1243cfc280..a6bb930d1549 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -115,6 +115,9 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu 
*vcpu, gpa_t cr2_or_gpa,
        return vcpu->arch.mmu->page_fault(vcpu, cr2_or_gpa, err, prefault);
 }
 
+kvm_pfn_t kvm_mmu_map_tdp_page(struct kvm_vcpu *vcpu, gpa_t gpa,
+                              u32 error_code, int max_level);
+
 /*
  * Currently, we have two sorts of write-protection, a) the first one
  * write-protects guest page to sync the guest modification, b) another one is
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 474173bceb54..bb59e80ade81 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -4034,6 +4034,31 @@ int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, 
u32 error_code,
                                 max_level, true, &pfn);
 }
 
+kvm_pfn_t kvm_mmu_map_tdp_page(struct kvm_vcpu *vcpu, gpa_t gpa,
+                              u32 error_code, int max_level)
+{
+       kvm_pfn_t pfn;
+       int r;
+
+       if (mmu_topup_memory_caches(vcpu, false))
+               return KVM_PFN_ERR_FAULT;
+
+       /*
+        * Loop on the page fault path to handle the case where an mmu_notifier
+        * invalidation triggers RET_PF_RETRY.  In the normal page fault path,
+        * KVM needs to resume the guest in case the invalidation changed any
+        * of the page fault properties, i.e. the gpa or error code.  For this
+        * path, the gpa and error code are fixed by the caller, and the caller
+        * expects failure if and only if the page fault can't be fixed.
+        */
+       do {
+               r = direct_page_fault(vcpu, gpa, error_code, false, max_level,
+                                     true, &pfn);
+       } while (r == RET_PF_RETRY && !is_error_noslot_pfn(pfn));
+       return pfn;
+}
+EXPORT_SYMBOL_GPL(kvm_mmu_map_tdp_page);
+
 static void nonpaging_init_context(struct kvm_vcpu *vcpu,
                                   struct kvm_mmu *context)
 {
-- 
2.17.1

Reply via email to