[PATCH v2 08/31] x86/virt/tdx: Configure TDX Module with optional TDX Connect feature

Xu Yilun
2026-03-27T16:23:03Z

TDX Module supports optional TDX features (e.g. TDX Connect & TDX Module
Extensions) that won't be enabled by default. It extends TDH.SYS.CONFIG
for host to choose to enable them on bootup.

Call TDH.SYS.CONFIG with a new bitmap input parameter to specify which
features to enable. The bitmap uses the same definitions as
TDX_FEATURES0. But note not all bits in TDX_FEATURES0 are valid for
configuration, e.g. TDX Module Extensions is a service that supports TDX
Connect, it is implicitly enabled when TDX Connect is enabled. Setting
TDX_FEATURES0_EXT in the bitmap has no effect.

TDX Module advances the version of TDH.SYS.CONFIG for the change, so
use the latest version (v1) for optional feature enabling. But
supporting existing Modules which only support v0 is still necessary
until they are deprecated, enumerate via TDX_FEATURES0 to decide which
version to use.

TDX Module updates global metadata when optional features are enabled.
Host should update the cached tdx_sysinfo to reflect these changes.

Co-developed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
---
arch/x86/virt/vmx/tdx/tdx.h | 3 ++-
arch/x86/virt/vmx/tdx/tdx.c | 16 +++++++++++++++-
2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index e5a9331df451..870bb75da3ba 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -58,7 +58,8 @@
#define TDH_PHYMEM_CACHE_WB 40
#define TDH_PHYMEM_PAGE_WBINVD 41
#define TDH_VP_WR 43
-#define TDH_SYS_CONFIG 45
+#define TDH_SYS_CONFIG_V0 45
+#define TDH_SYS_CONFIG SEAMCALL_LEAF_VER(TDH_SYS_CONFIG_V0, 1)

/* TDX page types */
#define PT_NDA 0x0
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 130214933c2f..0c5d6bdd810f 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1353,6 +1353,7 @@ static int construct_tdmrs(struct list_head *tmb_list,
static int config_tdx_module(struct tdmr_info_list *tdmr_list, u64 global_keyid)
{
struct tdx_module_args args = {};
+ u64 seamcall_fn = TDH_SYS_CONFIG_V0;
u64 *tdmr_pa_array;
size_t array_sz;
int i, ret;
@@ -1377,7 +1378,15 @@ static int config_tdx_module(struct tdmr_info_list *tdmr_list, u64 global_keyid)
args.rcx = __pa(tdmr_pa_array);
args.rdx = tdmr_list->nr_consumed_tdmrs;
args.r8 = global_keyid;
- ret = seamcall_prerr(TDH_SYS_CONFIG, &args);
+
+ if (tdx_sysinfo.features.tdx_features0 & TDX_FEATURES0_TDXCONNECT) {
+ args.r9 |= TDX_FEATURES0_TDXCONNECT;
+ args.r11 = ktime_get_real_seconds();
+ /* These parameters requires version >= 1 */
+ seamcall_fn = TDH_SYS_CONFIG;
+ }
+
+ ret = seamcall_prerr(seamcall_fn, &args);

/* Free the array as it is not required anymore. */
kfree(tdmr_pa_array);
@@ -1537,6 +1546,11 @@ static int init_tdx_module(void)
if (ret)
goto err_free_pamts;

+ /* configuration to tdx module may change tdx_sysinfo, update it */
+ ret = get_tdx_sys_info(&tdx_sysinfo);
+ if (ret)
+ goto err_reset_pamts;
+
/* Config the key of global KeyID on all packages */
ret = config_global_keyid();
if (ret)
--
2.25.1