From: Yan Zhao After removing a TD's private page, the TDX module does not write back and invalidate cache lines associated with the page and its keyID (i.e., the TD's guest keyID). The SEAMCALL wrapper tdh_phymem_page_wbinvd_hkid() enables the caller to provide the TD's guest keyID and physical memory address to invoke the SEAMCALL TDH_PHYMEM_PAGE_WBINVD to perform cache line invalidation. Enhance the SEAMCALL wrapper tdh_phymem_page_wbinvd_hkid() to support cache line invalidation for huge pages by introducing the parameters "folio", "start_idx", and "npages". These parameters specify the physical memory starting from the page at "start_idx" within a "folio" and spanning "npages" contiguous PFNs. Return TDX_OPERAND_INVALID if the specified memory is not entirely contained within a single folio. Signed-off-by: Xiaoyao Li Signed-off-by: Isaku Yamahata Suggested-by: Rick Edgecombe Signed-off-by: Yan Zhao Signed-off-by: Sean Christopherson --- arch/x86/include/asm/tdx.h | 2 +- arch/x86/kvm/vmx/tdx.c | 2 +- arch/x86/virt/vmx/tdx/tdx.c | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 1f57f7721286..8ceaebc6c1a9 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -237,7 +237,7 @@ u64 tdh_mem_track(struct tdx_td *tdr); u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, enum pg_level level, u64 *ext_err1, u64 *ext_err2); u64 tdh_phymem_cache_wb(bool resume); u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); -u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, u64 pfn); +u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, u64 pfn, enum pg_level level); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index 4ac312376ac9..90133e8f5c53 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -1867,7 +1867,7 @@ static void tdx_sept_remove_private_spte(struct kvm *kvm, gfn_t gfn, if (TDX_BUG_ON_2(err, TDH_MEM_PAGE_REMOVE, entry, level_state, kvm)) return; - err = tdh_phymem_page_wbinvd_hkid((u16)kvm_tdx->hkid, pfn); + err = tdh_phymem_page_wbinvd_hkid((u16)kvm_tdx->hkid, pfn, level); if (TDX_BUG_ON(err, TDH_PHYMEM_PAGE_WBINVD, kvm)) return; diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 37776ea56eb7..367df9366d57 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -2071,13 +2071,21 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td) } EXPORT_SYMBOL_FOR_KVM(tdh_phymem_page_wbinvd_tdr); -u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, u64 pfn) +u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, u64 pfn, enum pg_level level) { - struct tdx_module_args args = {}; + unsigned long npages = page_level_size(level) / PAGE_SIZE; + u64 err; - args.rcx = mk_keyed_paddr(hkid, pfn); + for (unsigned long i = 0; i < npages; i++) { + struct tdx_module_args args = { + .rcx = mk_keyed_paddr(hkid, pfn + i), + }; - return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); + err = seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); + if (err) + break; + } + return err; } EXPORT_SYMBOL_FOR_KVM(tdh_phymem_page_wbinvd_hkid); -- 2.53.0.rc1.217.geba53bf80e-goog