x86/virt/tdx: Add SEAMCALL wrappers for TDX VM/vCPU field access
authorRick Edgecombe <rick.p.edgecombe@intel.com>
Tue, 3 Dec 2024 01:03:15 +0000 (17:03 -0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 14 Mar 2025 18:20:49 +0000 (14:20 -0400)
Intel TDX protects guest VMs from malicious host and certain physical
attacks. The TDX module has TD scoped and vCPU scoped "metadata fields".
These fields are a bit like VMCS fields, and stored in data structures
maintained by the TDX module. Export 3 SEAMCALLs for use in reading and
writing these fields:

Make tdh_mng_rd() use MNG.VP.RD to read the TD scoped metadata.

Make tdh_vp_rd()/tdh_vp_wr() use TDH.VP.RD/WR to read/write the vCPU
scoped metadata.

KVM will use these by creating inline helpers that target various metadata
sizes. Export the raw SEAMCALL leaf, to avoid exporting the large number
of various sized helpers.

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>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Yuan Yao <yuan.yao@intel.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Message-ID: <20241203010317.827803-6-rick.p.edgecombe@intel.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/tdx.h
arch/x86/virt/vmx/tdx/tdx.c
arch/x86/virt/vmx/tdx/tdx.h

index 41a72ce961f32a33ff8122d2f6faca5e11801a1a..22ffb8dfe994e6e564f1bee36db6019c8ffcacc3 100644 (file)
@@ -160,9 +160,12 @@ u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page);
 u64 tdh_mng_key_config(struct tdx_td *td);
 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_mng_key_freeid(struct tdx_td *td);
 u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err);
 u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid);
+u64 tdh_vp_rd(struct tdx_vp *vp, u64 field, u64 *data);
+u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask);
 u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner, u64 *tdx_size);
 u64 tdh_phymem_cache_wb(bool resume);
 u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td);
index 2350d25b4ca3b410b39cdc5386d4c3da6ae539a2..93150f3c11125c07cd79145121d56a63f0bea19f 100644 (file)
@@ -1537,6 +1537,23 @@ u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp)
 }
 EXPORT_SYMBOL_GPL(tdh_vp_create);
 
+u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data)
+{
+       struct tdx_module_args args = {
+               .rcx = tdx_tdr_pa(td),
+               .rdx = field,
+       };
+       u64 ret;
+
+       ret = seamcall_ret(TDH_MNG_RD, &args);
+
+       /* R8: Content of the field, or 0 in case of error. */
+       *data = args.r8;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tdh_mng_rd);
+
 u64 tdh_mng_key_freeid(struct tdx_td *td)
 {
        struct tdx_module_args args = {
@@ -1563,6 +1580,36 @@ u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err)
 }
 EXPORT_SYMBOL_GPL(tdh_mng_init);
 
+u64 tdh_vp_rd(struct tdx_vp *vp, u64 field, u64 *data)
+{
+       struct tdx_module_args args = {
+               .rcx = tdx_tdvpr_pa(vp),
+               .rdx = field,
+       };
+       u64 ret;
+
+       ret = seamcall_ret(TDH_VP_RD, &args);
+
+       /* R8: Content of the field, or 0 in case of error. */
+       *data = args.r8;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tdh_vp_rd);
+
+u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask)
+{
+       struct tdx_module_args args = {
+               .rcx = tdx_tdvpr_pa(vp),
+               .rdx = field,
+               .r8 = data,
+               .r9 = mask,
+       };
+
+       return seamcall(TDH_VP_WR, &args);
+}
+EXPORT_SYMBOL_GPL(tdh_vp_wr);
+
 u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid)
 {
        struct tdx_module_args args = {
index 7a15c9afcdfa1ab2fae20ec7c3e8117fcd67e3b8..aacd38b1298944b2b79000dc032cc23177b3bec6 100644 (file)
 #define TDH_VP_ADDCX                   4
 #define TDH_MNG_KEY_CONFIG             8
 #define TDH_MNG_CREATE                 9
+#define TDH_MNG_RD                     11
 #define TDH_VP_CREATE                  10
 #define TDH_MNG_KEY_FREEID             20
 #define TDH_MNG_INIT                   21
 #define TDH_VP_INIT                    22
 #define TDH_PHYMEM_PAGE_RDMD           24
+#define TDH_VP_RD                      26
 #define TDH_PHYMEM_PAGE_RECLAIM                28
 #define TDH_SYS_KEY_CONFIG             31
 #define TDH_SYS_INIT                   33
@@ -32,6 +34,7 @@
 #define TDH_SYS_TDMR_INIT              36
 #define TDH_PHYMEM_CACHE_WB            40
 #define TDH_PHYMEM_PAGE_WBINVD         41
+#define TDH_VP_WR                      43
 #define TDH_SYS_CONFIG                 45
 
 /*