mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
x86/tdx: Use PFN directly for unmapping guest private memory
Remove struct page assumptions/constraints in APIs for unmapping guest private memory and have them take physical address directly. Having core TDX make assumptions that guest private memory must be backed by struct page (and/or folio) will create subtle dependencies on how KVM/guest_memfd allocates/manages memory (e.g., whether it uses memory allocated from core MM, if the memory is refcounted, or if the folio is split) that are easily avoided. [1]. KVM's MMUs work with PFNs. This is very much an intentional design choice. It ensures that the KVM MMUs remain flexible and are not too tightly tied to the regular CPU MMUs and the kernel code around them. Using "struct page" for TDX guest memory is not a good fit anywhere near the KVM MMU code [2]. Therefore, for unmapping guest private memory: export tdx_quirk_reset_paddr() for direct KVM invocation, and convert the SEAMCALL wrapper API tdh_phymem_page_wbinvd_hkid() to take PFN as input (thus updating mk_keyed_paddr() and tdh_phymem_page_wbinvd_tdr()). Intentionally have KVM pass PAGE_SIZE (rather than KVM_HPAGE_SIZE(level)) to tdx_quirk_reset_paddr() in tdx_sept_remove_private_spte() to avoid mixing in huge page changes. The KVM_BUG_ON() check for !PG_LEVEL_4K in tdx_sept_remove_private_spte() justifies using PAGE_SIZE. Do not convert tdx_reclaim_page() to use PFN as input since it currently does not remove guest private memory. Use "kvm_pfn_t pfn" for type safety. Using this KVM type is appropriate since APIs tdh_phymem_page_wbinvd_hkid() and tdx_quirk_reset_paddr() are exported to KVM only. [Yan: Use kvm_pfn_t,exclude tdx_reclaim_page(),use tdx_quirk_reset_paddr()] Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> Link: https://lore.kernel.org/all/aWgyhmTJphGQqO0Y@google.com [1] Link: https://lore.kernel.org/all/ac7V0g2q2hN3dU5u@google.com [2] Acked-by: Kiryl Shutsemau <kas@kernel.org> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Reviewed-by: Ackerley Tng <ackerleytng@google.com> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> Link: https://patch.msgid.link/20260430014948.24226-1-yan.y.zhao@intel.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
6ad0badd76
commit
4c7a124764
|
|
@ -154,6 +154,7 @@ u32 tdx_get_nr_guest_keyids(void);
|
|||
void tdx_guest_keyid_free(unsigned int keyid);
|
||||
|
||||
void tdx_quirk_reset_page(struct page *page);
|
||||
void tdx_quirk_reset_paddr(unsigned long base, unsigned long size);
|
||||
|
||||
struct tdx_td {
|
||||
/* TD root structure: */
|
||||
|
|
@ -177,15 +178,10 @@ struct tdx_vp {
|
|||
struct page **tdcx_pages;
|
||||
};
|
||||
|
||||
static inline u64 mk_keyed_paddr(u16 hkid, struct page *page)
|
||||
static inline u64 mk_keyed_paddr(u16 hkid, kvm_pfn_t pfn)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
ret = page_to_phys(page);
|
||||
/* KeyID bits are just above the physical address bits: */
|
||||
ret |= (u64)hkid << boot_cpu_data.x86_phys_bits;
|
||||
|
||||
return ret;
|
||||
/* KeyID bits are just above the physical address bits. */
|
||||
return PFN_PHYS(pfn) | ((u64)hkid << boot_cpu_data.x86_phys_bits);
|
||||
}
|
||||
|
||||
u64 tdh_vp_enter(struct tdx_vp *vp, struct tdx_module_args *args);
|
||||
|
|
@ -215,7 +211,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, struct page *page);
|
||||
u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, kvm_pfn_t pfn);
|
||||
#else
|
||||
static inline void tdx_init(void) { }
|
||||
static inline u32 tdx_get_nr_guest_keyids(void) { return 0; }
|
||||
|
|
|
|||
|
|
@ -1774,8 +1774,8 @@ static int tdx_sept_free_private_spt(struct kvm *kvm, gfn_t gfn,
|
|||
static void tdx_sept_remove_private_spte(struct kvm *kvm, gfn_t gfn,
|
||||
enum pg_level level, u64 mirror_spte)
|
||||
{
|
||||
struct page *page = pfn_to_page(spte_to_pfn(mirror_spte));
|
||||
struct kvm_tdx *kvm_tdx = to_kvm_tdx(kvm);
|
||||
kvm_pfn_t pfn = spte_to_pfn(mirror_spte);
|
||||
gpa_t gpa = gfn_to_gpa(gfn);
|
||||
u64 err, entry, level_state;
|
||||
|
||||
|
|
@ -1814,11 +1814,11 @@ 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, page);
|
||||
err = tdh_phymem_page_wbinvd_hkid((u16)kvm_tdx->hkid, pfn);
|
||||
if (TDX_BUG_ON(err, TDH_PHYMEM_PAGE_WBINVD, kvm))
|
||||
return;
|
||||
|
||||
tdx_quirk_reset_page(page);
|
||||
tdx_quirk_reset_paddr(PFN_PHYS(pfn), PAGE_SIZE);
|
||||
}
|
||||
|
||||
void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
|
||||
|
|
|
|||
|
|
@ -710,7 +710,7 @@ static __init int tdmrs_set_up_pamt_all(struct tdmr_info_list *tdmr_list,
|
|||
* to normal kernel memory. Systems with the X86_BUG_TDX_PW_MCE erratum need to
|
||||
* do the conversion explicitly via MOVDIR64B.
|
||||
*/
|
||||
static void tdx_quirk_reset_paddr(unsigned long base, unsigned long size)
|
||||
void tdx_quirk_reset_paddr(unsigned long base, unsigned long size)
|
||||
{
|
||||
const void *zero_page = (const void *)page_address(ZERO_PAGE(0));
|
||||
unsigned long phys, end;
|
||||
|
|
@ -729,6 +729,7 @@ static void tdx_quirk_reset_paddr(unsigned long base, unsigned long size)
|
|||
*/
|
||||
mb();
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_KVM(tdx_quirk_reset_paddr);
|
||||
|
||||
void tdx_quirk_reset_page(struct page *page)
|
||||
{
|
||||
|
|
@ -1920,17 +1921,17 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td)
|
|||
{
|
||||
struct tdx_module_args args = {};
|
||||
|
||||
args.rcx = mk_keyed_paddr(tdx_global_keyid, td->tdr_page);
|
||||
args.rcx = mk_keyed_paddr(tdx_global_keyid, page_to_pfn(td->tdr_page));
|
||||
|
||||
return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args);
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_KVM(tdh_phymem_page_wbinvd_tdr);
|
||||
|
||||
u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, struct page *page)
|
||||
u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, kvm_pfn_t pfn)
|
||||
{
|
||||
struct tdx_module_args args = {};
|
||||
|
||||
args.rcx = mk_keyed_paddr(hkid, page);
|
||||
args.rcx = mk_keyed_paddr(hkid, pfn);
|
||||
|
||||
return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user