Message ID | 20250101074959.412696-11-pbonzini@redhat.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | x86/virt/tdx: Add SEAMCALL wrappers for KVM | expand |
On Wed, 2025-01-01 at 02:49 -0500, Paolo Bonzini wrote: > From: Isaku Yamahata <isaku.yamahata@intel.com> > > TDX architecture introduces the concept of private GPA vs shared GPA, > depending on the GPA.SHARED bit. The TDX module maintains a single Secure > EPT (S-EPT or SEPT) tree per TD to translate TD's private memory accessed > using a private GPA. Wrap the SEAMCALL TDH.MEM.PAGE.REMOVE with > tdh_mem_page_remove() and TDH_PHYMEM_PAGE_WBINVD with > tdh_phymem_page_wbinvd_hkid() to unmap a TD private page from the SEPT, > remove the TD private page from the TDX module and flush cache lines to > memory after removal of the private page. > > Callers should specify "GPA" and "level" when calling tdh_mem_page_remove() > to indicate to the TDX module which TD private page to unmap and remove. > > TDH.MEM.PAGE.REMOVE may fail, and the caller of tdh_mem_page_remove() can > check the function return value and retrieve extended error information > from the function output parameters. Follow the TLB tracking protocol > before calling tdh_mem_page_remove() to remove a TD private page to avoid > SEAMCALL failure. > > After removing a TD's private page, the TDX module does not write back and > invalidate cache lines associated with the page and the page's keyID (i.e., > the TD's guest keyID). Therefore, provide tdh_phymem_page_wbinvd_hkid() to > allow the caller to pass in the TD's guest keyID and invoke > TDH_PHYMEM_PAGE_WBINVD to perform this action. > > Before reusing the page, the host kernel needs to map the page with keyID 0 > and invoke movdir64b() to convert the TD private page to a normal shared > page. > > TDH.MEM.PAGE.REMOVE and TDH_PHYMEM_PAGE_WBINVD may meet contentions inside > the TDX module for TDX's internal resources. To avoid staying in SEAM mode > for too long, TDX module will return a BUSY error code to the kernel > instead of spinning on the locks. The caller may need to handle this error > in specific ways (e.g., retry). The wrappers return the SEAMCALL error code > directly to the caller. Don't attempt to handle it in the core kernel. > > [Kai: Switched from generic seamcall export] > [Yan: Re-wrote the changelog] > Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com> > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> > Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> > Signed-off-by: Kai Huang <kai.huang@intel.com> > Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> > Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> > Message-ID: <20241112073658.22157-1-yan.y.zhao@intel.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > arch/x86/include/asm/tdx.h | 2 ++ > arch/x86/virt/vmx/tdx/tdx.c | 27 +++++++++++++++++++++++++++ > arch/x86/virt/vmx/tdx/tdx.h | 1 + > 3 files changed, 30 insertions(+) > > diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h > index f0b7b7b7d506..74938f725481 100644 > --- a/arch/x86/include/asm/tdx.h > +++ b/arch/x86/include/asm/tdx.h > @@ -157,8 +157,10 @@ u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask); > u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid); > u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner, u64 *tdx_size); > u64 tdh_mem_track(struct tdx_td *tdr); > +u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, u64 level, u64 *rcx, u64 *rdx); > u64 tdh_phymem_cache_wb(bool resume); > u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); > +u64 tdh_phymem_page_wbinvd_hkid(u64 hpa, u64 hkid); > #else > static inline void tdx_init(void) { } > static inline int tdx_cpu_enable(void) { return -ENODEV; } > diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c > index c7e6f30d0a14..cde55e9b3280 100644 > --- a/arch/x86/virt/vmx/tdx/tdx.c > +++ b/arch/x86/virt/vmx/tdx/tdx.c > @@ -1761,6 +1761,23 @@ u64 tdh_mem_track(struct tdx_td *td) > } > EXPORT_SYMBOL_GPL(tdh_mem_track); > > +u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, u64 level, u64 *rcx, u64 *rdx) level could be an int instead of a u64. An enum was also discussed, but considered to be not completely necessary. Probably we could even lose the level arg, depending on what we want to do about the one for page.aug. > +{ > + struct tdx_module_args args = { > + .rcx = gpa | level, Yan had "= gpa | (level & 0x7)" here, to make sure to only apply bits 0-2. > + .rdx = tdx_tdr_pa(td), > + }; > + u64 ret; > + > + ret = seamcall_ret(TDH_MEM_PAGE_REMOVE, &args); > + > + *rcx = args.rcx; > + *rdx = args.rdx; Switch to extended_err1/2 if the others get changed. > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(tdh_mem_page_remove); > + > u64 tdh_phymem_cache_wb(bool resume) > { > struct tdx_module_args args = { > @@ -1780,3 +1797,13 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td) > return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); > } > EXPORT_SYMBOL_GPL(tdh_phymem_page_wbinvd_tdr); > + > +u64 tdh_phymem_page_wbinvd_hkid(u64 hpa, u64 hkid) > +{ > + struct tdx_module_args args = {}; > + > + args.rcx = hpa | (hkid << boot_cpu_data.x86_phys_bits); > + > + return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); > +} > +EXPORT_SYMBOL_GPL(tdh_phymem_page_wbinvd_hkid); > diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h > index 4b0ad536afd9..d49cdd9b0577 100644 > --- a/arch/x86/virt/vmx/tdx/tdx.h > +++ b/arch/x86/virt/vmx/tdx/tdx.h > @@ -33,6 +33,7 @@ > #define TDH_PHYMEM_PAGE_RDMD 24 > #define TDH_VP_RD 26 > #define TDH_PHYMEM_PAGE_RECLAIM 28 > +#define TDH_MEM_PAGE_REMOVE 29 > #define TDH_SYS_KEY_CONFIG 31 > #define TDH_SYS_INIT 33 > #define TDH_SYS_RD 34
New diffs and changelog: SEAMCALL RFC: - For tdh_mem_page_remove() a) Use struct tdx_td instead of raw TDR u64 b) Change "u64 level" to "int tdx_level". c) Change "u64 gpa" to "gfn_t gfn". (Reinette) d) Use union tdx_sept_gpa_mapping_info to initialize args.rcx. (Reinette) e) Use extended_err1/2 instead of rcx/rdx for output. - For tdh_phymem_page_wbinvd_hkid() a) Use "struct page *" instead of raw hpa. b) Change "u64 hkid" to "u16 hkid" (Reinette) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 980daa142e92..be0fc55186a8 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -168,8 +168,11 @@ u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask); u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid); u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner, u64 *tdx_size); u64 tdh_mem_track(struct tdx_td *td); +u64 tdh_mem_page_remove(struct tdx_td *td, gfn_t gfn, int tdx_level, + u64 *extended_err1, u64 *extended_err2); u64 tdh_phymem_cache_wb(bool resume); u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); +u64 tdh_phymem_page_wbinvd_hkid(struct page *page, u16 hkid); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 120a415c1d7a..b4e4cfce3475 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1862,6 +1862,25 @@ u64 tdh_mem_track(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_mem_track); +u64 tdh_mem_page_remove(struct tdx_td *td, gfn_t gfn, int tdx_level, + u64 *extended_err1, u64 *extended_err2) +{ + union tdx_sept_gpa_mapping_info gpa_info = { .level = tdx_level, .gfn = gfn, }; + struct tdx_module_args args = { + .rcx = gpa_info.full, + .rdx = tdx_tdr_pa(td), + }; + u64 ret; + + ret = seamcall_ret(TDH_MEM_PAGE_REMOVE, &args); + + *extended_err1 = args.rcx; + *extended_err2 = args.rdx; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_mem_page_remove); + u64 tdh_phymem_cache_wb(bool resume) { struct tdx_module_args args = { @@ -1882,3 +1901,12 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_phymem_page_wbinvd_tdr); +u64 tdh_phymem_page_wbinvd_hkid(struct page *page, u16 hkid) +{ + struct tdx_module_args args = {}; + + args.rcx = page_to_phys(page) | ((hpa_t)hkid << boot_cpu_data.x86_phys_bits); + + return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); +} +EXPORT_SYMBOL_GPL(tdh_phymem_page_wbinvd_hkid); diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 24e32c838926..4de17d9c2e8c 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -35,6 +35,7 @@ #define TDH_PHYMEM_PAGE_RDMD 24 #define TDH_VP_RD 26 #define TDH_PHYMEM_PAGE_RECLAIM 28 +#define TDH_MEM_PAGE_REMOVE 29 #define TDH_SYS_KEY_CONFIG 31 #define TDH_SYS_INIT 33 #define TDH_SYS_RD 34
On Tue, Jan 07, 2025 at 02:43:11PM +0800, Yan Zhao wrote: ... > +u64 tdh_phymem_page_wbinvd_hkid(struct page *page, u16 hkid) > +{ > + struct tdx_module_args args = {}; > + > + args.rcx = page_to_phys(page) | ((hpa_t)hkid << boot_cpu_data.x86_phys_bits); > + > + return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); > +} For type of hkid is changed from u64 to u16. Here's a fixup patch to further have tdh_phymem_page_wbinvd_tdr() in [1] and the tdh_phymem_page_wbinvd_hkid() in this patch to use the common helper set_hkid_to_hpa(). [1] https://lore.kernel.org/kvm/20250101074959.412696-11-pbonzini@redhat.com/ commit 41f66e12a400516c6a851f0755f8abbe4dacb39b Author: Yan Zhao <yan.y.zhao@intel.com> Date: Wed Dec 11 18:11:24 2024 +0800 x86/virt/tdx: Move set_hkid_to_hpa() to x86 common header and use it Move set_hkid_to_hpa() from KVM TDX to x86 common header and have tdh_phymem_page_wbinvd_tdr() and tdh_phymem_page_wbinvd_hkid() to use it. Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 5420d07ee81c..5f3931e62c06 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -144,7 +144,13 @@ struct tdx_vp { struct page **tdcx_pages; }; +static __always_inline hpa_t set_hkid_to_hpa(hpa_t pa, u16 hkid) +{ + return pa | ((hpa_t)hkid << boot_cpu_data.x86_phys_bits); +} + /* SEAMCALL wrappers for creating/destroying/running TDX guests */ +u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page); u64 tdh_vp_enter(u64 tdvpr, struct tdx_module_args *args); u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page); u64 tdh_mem_page_add(struct tdx_td *td, gfn_t gfn, struct page *private_page, diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index c3a84eb4694a..d86bfcbd6873 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -222,11 +222,6 @@ static inline int pg_level_to_tdx_sept_level(enum pg_level level) */ static DEFINE_PER_CPU(struct list_head, associated_tdvcpus); -static __always_inline hpa_t set_hkid_to_hpa(hpa_t pa, u16 hkid) -{ - return pa | ((hpa_t)hkid << boot_cpu_data.x86_phys_bits); -} - static __always_inline union vmx_exit_reason tdexit_exit_reason(struct kvm_vcpu *vcpu) { return (union vmx_exit_reason)(u32)(to_tdx(vcpu)->vp_enter_ret); diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 6f002e36e421..0d7a0a27bd3e 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1930,7 +1930,7 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td) { struct tdx_module_args args = {}; - args.rcx = tdx_tdr_pa(td) | ((u64)tdx_global_keyid << boot_cpu_data.x86_phys_bits); + args.rcx = set_hkid_to_hpa(tdx_tdr_pa(td), tdx_global_keyid); return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); } @@ -1940,7 +1940,7 @@ u64 tdh_phymem_page_wbinvd_hkid(struct page *page, u16 hkid) { struct tdx_module_args args = {}; - args.rcx = page_to_phys(page) | ((hpa_t)hkid << boot_cpu_data.x86_phys_bits); + args.rcx = set_hkid_to_hpa(page_to_phys(page), hkid); return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); }
On 1/6/25 22:43, Yan Zhao wrote: > +u64 tdh_phymem_page_wbinvd_hkid(struct page *page, u16 hkid) > +{ > + struct tdx_module_args args = {}; > + > + args.rcx = page_to_phys(page) | ((hpa_t)hkid << boot_cpu_data.x86_phys_bits); I've seen this idiom enough times. You need a helper: u64 mk_keyed_paddr(struct page *page, u64 keyid) { u64 ret; ret = page_to_phys(page); /* KeyID bits are just above the physical address bits: */ ret |= keyid << boot_cpu_data.x86_phys_bits; return ret; } Although I'm also debating a bit what the typing on 'keyid' should be. Right now it's quite tied to the physical address width, but that's not fundamental to TDX. It could absolutely change in the future.
On Tue, Jan 07, 2025 at 02:13:19PM -0800, Dave Hansen wrote: > On 1/6/25 22:43, Yan Zhao wrote: > > +u64 tdh_phymem_page_wbinvd_hkid(struct page *page, u16 hkid) > > +{ > > + struct tdx_module_args args = {}; > > + > > + args.rcx = page_to_phys(page) | ((hpa_t)hkid << boot_cpu_data.x86_phys_bits); > > I've seen this idiom enough times. You need a helper: > > u64 mk_keyed_paddr(struct page *page, u64 keyid) > { > u64 ret; > > ret = page_to_phys(page); > /* KeyID bits are just above the physical address bits: */ > ret |= keyid << boot_cpu_data.x86_phys_bits; > > return ret; > } Thanks. There's actually a helper at [1]. I made the helper in [1] as a fixup patch since it needs to be applied to both tdh_phymem_page_wbinvd_tdr() and tdh_phymem_page_wbinvd_hkid(). [1] https://lore.kernel.org/all/Z3zPSPrFtxM7l5cD@yzhao56-desk.sh.intel.com/ > > Although I'm also debating a bit what the typing on 'keyid' should be. > Right now it's quite tied to the physical address width, but that's not > fundamental to TDX. It could absolutely change in the future. Changing from "u64" to "u16" was raised during our internal review. The main reasons for this change are to avoid overflow and also because: - In MSR IA32_TME_ACTIVATE, MK_TME_KEYID_BITS and TDX_RESERVED_KEYID_BITS are only defined with 4 bits, so at most 16 bits in HPA can be configured as KeyIDs. - TDX spec explictly requires KeyID to be 16 bits for SEAMCALLs TDH.SYS.CONFIG and TDH.MNG.CREATE. - Corresponding variables for tdx_global_keyid, tdx_guest_keyid_start, tdx_nr_guest_keyids, nr_tdx_keyids, tdx_keyid_start are all u16 in TDX module code. There is a proposed fix to change the type of KeyID to u16 as shown below (not yet split and sent out). Do you think this change to u16 makes sense? diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 296d123a6c1c..5f3931e62c06 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -122,7 +122,7 @@ const char *tdx_dump_mce_info(struct mce *m); const struct tdx_sys_info *tdx_get_sysinfo(void); int tdx_guest_keyid_alloc(void); -void tdx_guest_keyid_free(unsigned int keyid); +void tdx_guest_keyid_free(u16 keyid); struct tdx_td { /* TD root structure: */ @@ -164,7 +164,7 @@ u64 tdh_mem_page_aug(struct tdx_td *td, gfn_t gfn, struct page *private_page, u64 tdh_mem_range_block(struct tdx_td *td, gfn_t gfn, int tdx_level, u64 *extended_err1, u64 *extended_err2); u64 tdh_mng_key_config(struct tdx_td *td); -u64 tdh_mng_create(struct tdx_td *td, u64 hkid); +u64 tdh_mng_create(struct tdx_td *td, u16 hkid); u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp); u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data); u64 tdh_mr_extend(struct tdx_td *td, gpa_t gpa, u64 *extended_err1, u64 *extended_err2); diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index d86bfcbd6873..4e7330df4e32 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -308,13 +308,13 @@ static __always_inline void tdvmcall_set_return_val(struct kvm_vcpu *vcpu, static inline void tdx_hkid_free(struct kvm_tdx *kvm_tdx) { tdx_guest_keyid_free(kvm_tdx->hkid); - kvm_tdx->hkid = -1; + kvm_tdx->hkid_assigned = false; atomic_dec(&nr_configured_hkid); } static inline bool is_hkid_assigned(struct kvm_tdx *kvm_tdx) { - return kvm_tdx->hkid > 0; + return kvm_tdx->hkid_assigned; } static inline void tdx_disassociate_vp(struct kvm_vcpu *vcpu) @@ -2354,7 +2354,8 @@ static int __tdx_td_init(struct kvm *kvm, struct td_params *td_params, ret = tdx_guest_keyid_alloc(); if (ret < 0) return ret; - kvm_tdx->hkid = ret; + kvm_tdx->hkid = (u16)ret; + kvm_tdx->hkid_assigned = true; atomic_inc(&nr_configured_hkid); diff --git a/arch/x86/kvm/vmx/tdx.h b/arch/x86/kvm/vmx/tdx.h index b07ca9ecaf95..67b44e98bf49 100644 --- a/arch/x86/kvm/vmx/tdx.h +++ b/arch/x86/kvm/vmx/tdx.h @@ -29,7 +29,8 @@ struct kvm_tdx { u64 attributes; u64 xfam; - int hkid; + u16 hkid; + bool hkid_assigned; u64 tsc_offset; diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 1986d360e9b7..5dd83e59c5b6 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -40,9 +40,9 @@ #include <asm/mce.h> #include "tdx.h" -static u32 tdx_global_keyid __ro_after_init; -static u32 tdx_guest_keyid_start __ro_after_init; -static u32 tdx_nr_guest_keyids __ro_after_init; +static u16 tdx_global_keyid __ro_after_init; +static u16 tdx_guest_keyid_start __ro_after_init; +static u16 tdx_nr_guest_keyids __ro_after_init; static DEFINE_IDA(tdx_guest_keyid_pool); @@ -979,7 +979,7 @@ static int construct_tdmrs(struct list_head *tmb_list, return ret; } -static int config_tdx_module(struct tdmr_info_list *tdmr_list, u64 global_keyid) +static int config_tdx_module(struct tdmr_info_list *tdmr_list, u16 global_keyid) { struct tdx_module_args args = {}; u64 *tdmr_pa_array; @@ -1375,8 +1375,8 @@ const char *tdx_dump_mce_info(struct mce *m) return "TDX private memory error. Possible kernel bug."; } -static __init int record_keyid_partitioning(u32 *tdx_keyid_start, - u32 *nr_tdx_keyids) +static __init int record_keyid_partitioning(u16 *tdx_keyid_start, + u16 *nr_tdx_keyids) { u32 _nr_mktme_keyids, _tdx_keyid_start, _nr_tdx_keyids; int ret; @@ -1394,6 +1394,11 @@ static __init int record_keyid_partitioning(u32 *tdx_keyid_start, /* TDX KeyIDs start after the last MKTME KeyID. */ _tdx_keyid_start = _nr_mktme_keyids + 1; + /* + * In IA32_TME_ACTIVATE, MK_TME_KEYID_BITS and TDX_RESERVED_KEYID_BITS + * are only 4 bits, so at most 16 bits in HPA can be configured as + * KeyIDs. + */ *tdx_keyid_start = _tdx_keyid_start; *nr_tdx_keyids = _nr_tdx_keyids; @@ -1467,7 +1472,7 @@ static void __init check_tdx_erratum(void) void __init tdx_init(void) { - u32 tdx_keyid_start, nr_tdx_keyids; + u16 tdx_keyid_start, nr_tdx_keyids; int err; err = record_keyid_partitioning(&tdx_keyid_start, &nr_tdx_keyids); @@ -1544,7 +1549,7 @@ int tdx_guest_keyid_alloc(void) } EXPORT_SYMBOL_GPL(tdx_guest_keyid_alloc); -void tdx_guest_keyid_free(unsigned int keyid) +void tdx_guest_keyid_free(u16 keyid) { ida_free(&tdx_guest_keyid_pool, keyid); } @@ -1697,7 +1702,7 @@ u64 tdh_mng_key_config(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_mng_key_config); -u64 tdh_mng_create(struct tdx_td *td, u64 hkid) +u64 tdh_mng_create(struct tdx_td *td, u16 hkid) { struct tdx_module_args args = { .rcx = tdx_tdr_pa(td),
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index f0b7b7b7d506..74938f725481 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -157,8 +157,10 @@ u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask); u64 tdh_vp_init_apicid(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid); u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner, u64 *tdx_size); u64 tdh_mem_track(struct tdx_td *tdr); +u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, u64 level, u64 *rcx, u64 *rdx); u64 tdh_phymem_cache_wb(bool resume); u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); +u64 tdh_phymem_page_wbinvd_hkid(u64 hpa, u64 hkid); #else static inline void tdx_init(void) { } static inline int tdx_cpu_enable(void) { return -ENODEV; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index c7e6f30d0a14..cde55e9b3280 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1761,6 +1761,23 @@ u64 tdh_mem_track(struct tdx_td *td) } EXPORT_SYMBOL_GPL(tdh_mem_track); +u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, u64 level, u64 *rcx, u64 *rdx) +{ + struct tdx_module_args args = { + .rcx = gpa | level, + .rdx = tdx_tdr_pa(td), + }; + u64 ret; + + ret = seamcall_ret(TDH_MEM_PAGE_REMOVE, &args); + + *rcx = args.rcx; + *rdx = args.rdx; + + return ret; +} +EXPORT_SYMBOL_GPL(tdh_mem_page_remove); + u64 tdh_phymem_cache_wb(bool resume) { struct tdx_module_args args = { @@ -1780,3 +1797,13 @@ u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td) return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); } EXPORT_SYMBOL_GPL(tdh_phymem_page_wbinvd_tdr); + +u64 tdh_phymem_page_wbinvd_hkid(u64 hpa, u64 hkid) +{ + struct tdx_module_args args = {}; + + args.rcx = hpa | (hkid << boot_cpu_data.x86_phys_bits); + + return seamcall(TDH_PHYMEM_PAGE_WBINVD, &args); +} +EXPORT_SYMBOL_GPL(tdh_phymem_page_wbinvd_hkid); diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 4b0ad536afd9..d49cdd9b0577 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -33,6 +33,7 @@ #define TDH_PHYMEM_PAGE_RDMD 24 #define TDH_VP_RD 26 #define TDH_PHYMEM_PAGE_RECLAIM 28 +#define TDH_MEM_PAGE_REMOVE 29 #define TDH_SYS_KEY_CONFIG 31 #define TDH_SYS_INIT 33 #define TDH_SYS_RD 34