Introduce a helper to directly fault-in a TDP page without going
through the full page fault path.  This allows SEV-SNP to build
the netsted-page-table while handling the page state change VMGEXIT.
A guest may issue a page state change VMGEXIT before accessing the
page. Creating a fault-in, we can get the TDP page level and PFN
which will be used while calculating the RMP page size.

SEV-SNP guest calls, page state change VMGEXIT followed by the PVALIDATE.
If the page is not present in the TDP then PVALIDATE will cause a nested
page fault. If we can build the TDP while handling the page state change
VMGEXIT, it can also avoid a nested page fault due to the page not
being present.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Borislav Petkov <b...@alien8.de>
Cc: Joerg Roedel <jroe...@suse.de>
Cc: "H. Peter Anvin" <h...@zytor.com>
Cc: Tony Luck <tony.l...@intel.com>
Cc: Dave Hansen <dave.han...@intel.com>
Cc: "Peter Zijlstra (Intel)" <pet...@infradead.org>
Cc: Paolo Bonzini <pbonz...@redhat.com>
Cc: Tom Lendacky <thomas.lenda...@amd.com>
Cc: David Rientjes <rient...@google.com>
Cc: Sean Christopherson <sea...@google.com>
Cc: x...@kernel.org
Cc: k...@vger.kernel.org
Signed-off-by: Brijesh Singh <brijesh.si...@amd.com>
---
 arch/x86/kvm/mmu.h     |  2 ++
 arch/x86/kvm/mmu/mmu.c | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 261be1d2032b..70dce26a5882 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -109,6 +109,8 @@ static inline void kvm_mmu_load_pgd(struct kvm_vcpu *vcpu)
 int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
                       bool prefault);
 
+int kvm_mmu_map_tdp_page(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, int 
max_level);
+
 static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t 
cr2_or_gpa,
                                        u32 err, bool prefault)
 {
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index e55df7b4e297..33104943904b 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -3808,6 +3808,26 @@ int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, 
u32 error_code,
                                 max_level, true);
 }
 
+int kvm_mmu_map_tdp_page(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, int 
max_level)
+{
+       int r;
+
+       /*
+        * 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);
+       } while (r == RET_PF_RETRY);
+
+       return r;
+}
+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