[PATCH v5 5/6] x86/virt/tdx: Make TDX module initialize the extensions
From: Xu Yilun
Date: Tue Nov 10 2026 - 22:59:47 EST
Continue fleshing out the extension initialization process. At this
point the kernel has provided all memory and the TDX module is ready to
initialize the extensions on the memory.
Initialize TDX module extensions via TDH.EXT.INIT. This process takes on
the order of 100's of milliseconds, during which the TDX module loads
its internal extension image into this memory and builds the execution
environment. Once initialized, those add-on features can use their
SEAMCALL leafs normally.
Note that TDH.EXT.INIT builds all configured extensions. The SEAMCALL
leaf fails if any extension fails to initialize. The kernel does simple
error handling - just fails the whole TDX initialization on any error.
This is OK cause all extensions are considered necessary for security.
If a nice-to-have extension appears in the future, this can be
revisited. A potential solution is to have a new metadata field
indicating which extensions get enabled/failed, then the kernel decides
whether to continue or abort.
The original changelog was written by hand. AI was used to help correct
grammatical errors and polish individual sentences for better
readability.
Signed-off-by: Xu Yilun <yilun.xu@xxxxxxxxxxxxxxx>
Reviewed-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx>
Reviewed-by: Tony Lindgren <tony.lindgren@xxxxxxxxxxxxxxx>
Reviewed-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@xxxxxxxxxx>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@xxxxxxxxx>
---
v5:
- A new paragraph to describe the error handling.
- Refactor the existing changelog.
- Better clarify the AI usage.
v4:
- Specify what TDH.EXT.INIT is doing in the changelog (Rick)
- Collect Reviewed-by tags
v1:
- Fix return value for SEAMCALL wrappers (Chao)
- Print SEAMCALL error code for SEAMCALL wrappers (Xiaoyao)
- Changelog & code comments
---
arch/x86/virt/vmx/tdx/tdx.h | 1 +
arch/x86/virt/vmx/tdx/tdx.c | 25 ++++++++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index 2adc5d31d258..cac0a5abbff1 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -50,6 +50,7 @@
#define TDH_SYS_UPDATE 53
#define TDH_PHYMEM_PAMT_ADD 58
#define TDH_PHYMEM_PAMT_REMOVE 59
+#define TDH_EXT_INIT 60
#define TDH_EXT_MEM_ADD 61
#define TDH_SYS_DISABLE 69
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 3440f1878978..3a1ba4e73cfe 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1343,12 +1343,35 @@ static __init int tdx_ext_mem_setup(void)
return ret;
}
+static __init int tdx_ext_init(void)
+{
+ struct tdx_module_args args = {};
+ u64 ret;
+
+ do {
+ ret = seamcall(TDH_EXT_INIT, &args);
+ } while (ret == TDX_INTERRUPTED_RESUMABLE);
+
+ if (ret != TDX_SUCCESS) {
+ pr_err("TDH.EXT.INIT failed: 0x%016llx\n", ret);
+ return -EIO;
+ }
+
+ return 0;
+}
+
static __init int init_tdx_module_extensions(void)
{
+ int ret;
+
if (!(tdx_sysinfo.features.tdx_features0 & TDX_FEATURES0_EXT))
return 0;
- return tdx_ext_mem_setup();
+ ret = tdx_ext_mem_setup();
+ if (ret)
+ return ret;
+
+ return tdx_ext_init();
}
static __init int init_tdx_module(void)
--
2.25.1