* [PATCH v4 00/24] Runtime TDX Module update support
@ 2026-02-12 14:35 Chao Gao
2026-02-12 14:35 ` [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates Chao Gao
2026-02-12 14:46 ` [PATCH v4 00/24] Runtime TDX Module update support Chao Gao
0 siblings, 2 replies; 5+ messages in thread
From: Chao Gao @ 2026-02-12 14:35 UTC (permalink / raw)
To: linux-coco, linux-kernel, kvm, x86, linux-doc
Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu,
sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc,
rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, binbin.wu,
tony.lindgren, Chao Gao, Borislav Petkov, H. Peter Anvin,
Ingo Molnar, Jonathan Corbet, Paolo Bonzini, Thomas Gleixner
Hi Reviewers,
With this posting, I'm hoping to collect more Reviewed-by or Acked-by tags.
In the last round of review, the first 6 patches received thorough reviews
from Dave and others. I believe they are in good shape after incorporating
all feedback, so I'm hoping to get more reviews on patch 7 and beyond.
Kai, please take a look at patch 10, which has been updated per your
suggestions.
Note that like v3, this v4 is not based on Sean's VMXON series to make this
series more reviewable.
For transparency, I should note that I used an Intel-operated AI tool to
help proofread this cover-letter and commit messages.
Changelog:
v3->v4:
- Drop INTEL_TDX_MODULE_UPDATE kconfig [Dave]
- Drop two unnecessary cleanup patches [Dave]
- Drop VMCS save/restore across P-SEAMLDR calls [Dave]
(We are pursuing microcode changes to preserve the current VMCS
across P-SEAMLDR calls. Until then, we still need the last patch in
this series which wraps P-SEAMLDR calls with VMCS save/restore for
testing)
- Don't handle P-SEAMLDR's "no_entropy" error [Dave]
- Put seamldr_info on stack and change seamldr attributes permission
to 0x400 [Dave]
- Correct copyright notices [Dave]
- Document TDX Module updates in tdx.rst
- Improve changelogs and comments [Dave, Kai]
- Rename the TDX Module update sysfs directory from "seamldr_upload" to
"tdx_module" [Cedric]
- Merge the patch that support 16KB sigstruct to a previous patch [Kai]
- Update tdx_blob definition to match this series' implementation [Kai]
- Remove tdx_blob checksum verification as it is really optional
- Don't support update canceling [Yilun]
- Other minor code changes and changelog improvements
- Collect review tags from Tony and Yilun
- v3: https://lore.kernel.org/kvm/20260123145645.90444-1-chao.gao@intel.com/
This series adds support for runtime TDX Module updates that preserve
running TDX guests. It is also available at:
https://github.com/gaochaointel/linux-dev/commits/tdx-module-updates-v4/
== Background ==
Intel TDX isolates Trusted Domains (TDs), or confidential guests, from the
host. A key component of Intel TDX is the TDX Module, which enforces
security policies to protect the memory and CPU states of TDs from the
host. However, the TDX Module is software that require updates.
== Problems ==
Currently, the TDX Module is loaded by the BIOS at boot time, and the only
way to update it is through a reboot, which results in significant system
downtime. Users expect the TDX Module to be updatable at runtime without
disrupting TDX guests.
== Solution ==
On TDX platforms, P-SEAMLDR[1] is a component within the protected SEAM
range. It is loaded by the BIOS and provides the host with functions to
install a TDX Module at runtime.
Implement a TDX Module update facility via the fw_upload mechanism. Given
that there is variability in which module update to load based on features,
fix levels, and potentially reloading the same version for error recovery
scenarios, the explicit userspace chosen payload flexibility of fw_upload
is attractive.
This design allows the kernel to accept a bitstream instead of loading a
named file from the filesystem, as the module selection and policy
enforcement for TDX Modules are quite complex (see more in patch 8). By
doing so, much of this complexity is shifted out of the kernel. The kernel
need to expose information, such as the TDX Module version, to userspace.
Userspace must understand the TDX Module versioning scheme and update
policy to select the appropriate TDX Module (see "TDX Module Versioning"
below).
In the unlikely event the update fails, for example userspace picks an
incompatible update image, or the image is otherwise corrupted, all TDs
will experience SEAMCALL failures and be killed. The recovery of TD
operation from that event requires a reboot.
Given there is no mechanism to quiesce SEAMCALLs, the TDs themselves must
pause execution over an update. The most straightforward way to meet the
'pause TDs while update executes' constraint is to run the update in
stop_machine() context. All other evaluated solutions export more
complexity to KVM, or exports more fragility to userspace.
== How to test this series ==
First, load kvm-intel.ko and tdx-host.ko if they haven't been loaded:
# modprobe -r kvm_intel
# modprobe kvm_intel tdx=1
# modprobe tdx-host
Then, use the userspace tool below to select the appropriate TDX module and
install it via the interfaces exposed by this series:
# git clone https://github.com/intel/tdx-module-binaries
# cd tdx-module-binaries
# python version_select_and_load.py --update
this version changes the firmware directory name from seamldr_upload to
tdx_module, so, below change should be applied to version_select_and_load.py:
diff --git a/version_select_and_load.py b/version_select_and_load.py
index 2193bd8..6a3b604 100644
--- a/version_select_and_load.py
+++ b/version_select_and_load.py
@@ -38,7 +38,7 @@ except ImportError:
print("Error: cpuid module is not installed. Please install it using 'pip install cpuid'")
sys.exit(1)
-FIRMWARE_PATH = "/sys/class/firmware/seamldr_upload"
+FIRMWARE_PATH = "/sys/class/firmware/tdx_module"
MODULE_PATH = "/sys/devices/faux/tdx_host"
SEAMLDR_PATH = "/sys/devices/faux/tdx_host/seamldr"
allow_debug = False
== Other information relevant to Runtime TDX Module updates ==
=== TDX Module versioning ===
Each TDX Module is assigned a version number x.y.z, where x represents the
"major" version, y the "minor" version, and z the "update" version.
Runtime TDX Module updates are restricted to Z-stream releases.
Note that Z-stream releases do not necessarily guarantee compatibility. A
new release may not be compatible with all previous versions. To address this,
Intel provides a separate file containing compatibility information, which
specifies the minimum module version required for a particular update. This
information is referenced by the tool to determine if two modules are
compatible.
=== TCB Stability ===
Updates change the TCB as viewed by attestation reports. In TDX there is
a distinction between launch-time version and current version where
runtime TDX Module updates cause that latter version number to change,
subject to Z-stream constraints.
The concern that a malicious host may attack confidential VMs by loading
insecure updates was addressed by Alex in [3]. Similarly, the scenario
where some "theoretical paranoid tenant" in the cloud wants to audit
updates and stop trusting the host after updates until audit completion
was also addressed in [4]. Users not in the cloud control the host machine
and can manage updates themselves, so they don't have these concerns.
See more about the implications of current TCB version changes in
attestation as summarized by Dave in [5].
=== TDX Module Distribution Model ===
At a high level, Intel publishes all TDX Modules on the github [2], along
with a mapping_file.json which documents the compatibility information
about each TDX Module and a userspace tool to install the TDX Module. OS
vendors can package these modules and distribute them. Administrators
install the package and use the tool to select the appropriate TDX Module
and install it via the interfaces exposed by this series.
[1]: https://cdrdv2.intel.com/v1/dl/getContent/733584
[2]: https://github.com/intel/tdx-module-binaries
[3]: https://lore.kernel.org/all/665c5ae0-4b7c-4852-8995-255adf7b3a2f@amazon.com/
[4]: https://lore.kernel.org/all/5d1da767-491b-4077-b472-2cc3d73246d6@amazon.com/
[5]: https://lore.kernel.org/all/94d6047e-3b7c-4bc1-819c-85c16ff85abf@intel.com/
Chao Gao (23):
coco/tdx-host: Introduce a "tdx_host" device
coco/tdx-host: Expose TDX Module version
x86/virt/seamldr: Introduce a wrapper for P-SEAMLDR SEAMCALLs
x86/virt/seamldr: Retrieve P-SEAMLDR information
coco/tdx-host: Expose P-SEAMLDR information via sysfs
coco/tdx-host: Implement firmware upload sysfs ABI for TDX Module
updates
x86/virt/seamldr: Block TDX Module updates if any CPU is offline
x86/virt/seamldr: Check update limit before TDX Module updates
x86/virt/seamldr: Allocate and populate a module update request
x86/virt/seamldr: Introduce skeleton for TDX Module updates
x86/virt/seamldr: Abort updates if errors occurred midway
x86/virt/seamldr: Shut down the current TDX module
x86/virt/tdx: Reset software states during TDX Module shutdown
x86/virt/seamldr: Log TDX Module update failures
x86/virt/seamldr: Install a new TDX Module
x86/virt/seamldr: Do TDX per-CPU initialization after updates
x86/virt/tdx: Restore TDX Module state
x86/virt/tdx: Update tdx_sysinfo and check features post-update
x86/virt/tdx: Enable TDX Module runtime updates
x86/virt/tdx: Avoid updates during update-sensitive operations
coco/tdx-host: Document TDX Module update expectations
x86/virt/tdx: Document TDX Module updates
[NOT-FOR-REVIEW] x86/virt/seamldr: Save and restore current VMCS
Kai Huang (1):
x86/virt/tdx: Move low level SEAMCALL helpers out of <asm/tdx.h>
.../ABI/testing/sysfs-devices-faux-tdx-host | 82 ++++
Documentation/arch/x86/tdx.rst | 34 ++
arch/x86/include/asm/seamldr.h | 37 ++
arch/x86/include/asm/special_insns.h | 22 ++
arch/x86/include/asm/tdx.h | 66 +---
arch/x86/include/asm/tdx_global_metadata.h | 5 +
arch/x86/kvm/vmx/tdx_errno.h | 2 -
arch/x86/virt/vmx/tdx/Makefile | 2 +-
arch/x86/virt/vmx/tdx/seamcall_internal.h | 107 ++++++
arch/x86/virt/vmx/tdx/seamldr.c | 360 ++++++++++++++++++
arch/x86/virt/vmx/tdx/tdx.c | 153 +++++---
arch/x86/virt/vmx/tdx/tdx.h | 11 +-
arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 15 +
drivers/virt/coco/Kconfig | 2 +
drivers/virt/coco/Makefile | 1 +
drivers/virt/coco/tdx-host/Kconfig | 12 +
drivers/virt/coco/tdx-host/Makefile | 1 +
drivers/virt/coco/tdx-host/tdx-host.c | 240 ++++++++++++
18 files changed, 1050 insertions(+), 102 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-devices-faux-tdx-host
create mode 100644 arch/x86/include/asm/seamldr.h
create mode 100644 arch/x86/virt/vmx/tdx/seamcall_internal.h
create mode 100644 arch/x86/virt/vmx/tdx/seamldr.c
create mode 100644 drivers/virt/coco/tdx-host/Kconfig
create mode 100644 drivers/virt/coco/tdx-host/Makefile
create mode 100644 drivers/virt/coco/tdx-host/tdx-host.c
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates 2026-02-12 14:35 [PATCH v4 00/24] Runtime TDX Module update support Chao Gao @ 2026-02-12 14:35 ` Chao Gao 2026-03-04 23:49 ` Huang, Kai 2026-03-12 2:42 ` Edgecombe, Rick P 2026-02-12 14:46 ` [PATCH v4 00/24] Runtime TDX Module update support Chao Gao 1 sibling, 2 replies; 5+ messages in thread From: Chao Gao @ 2026-02-12 14:35 UTC (permalink / raw) To: linux-coco, linux-kernel, kvm, x86, linux-doc Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu, sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc, rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, binbin.wu, tony.lindgren, Chao Gao, Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin, Jonathan Corbet Document TDX Module updates as a subsection of "TDX Host Kernel Support" to provide background information and cover key points that developers and users may need to know, for example: - update is done in stop_machine() context - update instructions and results - update policy and tooling Signed-off-by: Chao Gao <chao.gao@intel.com> --- Documentation/arch/x86/tdx.rst | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Documentation/arch/x86/tdx.rst b/Documentation/arch/x86/tdx.rst index 61670e7df2f7..01ae560c7f66 100644 --- a/Documentation/arch/x86/tdx.rst +++ b/Documentation/arch/x86/tdx.rst @@ -99,6 +99,40 @@ initialize:: [..] virt/tdx: module initialization failed ... +TDX Module Runtime Updates +-------------------------- + +The TDX architecture includes a persistent SEAM loader (P-SEAMLDR) that +runs in SEAM mode separately from the TDX Module. The kernel can +communicate with P-SEAMLDR to perform runtime updates of the TDX Module. + +During updates, the TDX Module becomes unresponsive to other TDX +operations. To prevent components using TDX (such as KVM) from experiencing +unexpected errors during updates, updates are performed in stop_machine() +context. + +TDX Module updates have complex compatibility requirements; the new module +must be compatible with the current CPU, P-SEAMLDR, and running TDX Module. +Rather than implementing complex module selection and policy enforcement +logic in the kernel, userspace is responsible for auditing and selecting +appropriate updates. + +Updates use the standard firmware upload interface. See +Documentation/driver-api/firmware/fw_upload.rst for detailed instructions + +Successful updates are logged in dmesg: + [..] virt/tdx: version 1.5.20 -> 1.5.24 + +If updates failed, running TDs may be killed and further TDX operations may +be not possible until reboot. For detailed error information, see +Documentation/ABI/testing/sysfs-devices-faux-tdx-host. + +Given the risk of losing existing TDs, userspace should verify that the update +is compatible with the current system and properly validated before applying it. +A reference userspace tool that implements necessary checks is available at: + + https://github.com/intel/confidential-computing.tdx.tdx-module.binaries + TDX Interaction to Other Kernel Components ------------------------------------------ -- 2.47.3 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates 2026-02-12 14:35 ` [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates Chao Gao @ 2026-03-04 23:49 ` Huang, Kai 2026-03-12 2:42 ` Edgecombe, Rick P 1 sibling, 0 replies; 5+ messages in thread From: Huang, Kai @ 2026-03-04 23:49 UTC (permalink / raw) To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Gao, Chao, x86@kernel.org Cc: corbet@lwn.net, dave.hansen@linux.intel.com, tony.lindgren@linux.intel.com, binbin.wu@linux.intel.com, seanjc@google.com, kas@kernel.org, Chatre, Reinette, Verma, Vishal L, nik.borisov@suse.com, mingo@redhat.com, Weiny, Ira, hpa@zytor.com, Annapurve, Vishal, sagis@google.com, Duan, Zhenzhong, Edgecombe, Rick P, paulmck@kernel.org, tglx@kernel.org, yilun.xu@linux.intel.com, Williams, Dan J, bp@alien8.de On Thu, 2026-02-12 at 06:35 -0800, Chao Gao wrote: > Document TDX Module updates as a subsection of "TDX Host Kernel Support" to > provide background information and cover key points that developers and > users may need to know, for example: > > - update is done in stop_machine() context > - update instructions and results > - update policy and tooling > > Signed-off-by: Chao Gao <chao.gao@intel.com> > --- > Documentation/arch/x86/tdx.rst | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/Documentation/arch/x86/tdx.rst b/Documentation/arch/x86/tdx.rst > index 61670e7df2f7..01ae560c7f66 100644 > --- a/Documentation/arch/x86/tdx.rst > +++ b/Documentation/arch/x86/tdx.rst > @@ -99,6 +99,40 @@ initialize:: > > [..] virt/tdx: module initialization failed ... > > +TDX Module Runtime Updates > +-------------------------- > + > +The TDX architecture includes a persistent SEAM loader (P-SEAMLDR) that > +runs in SEAM mode separately from the TDX Module. The kernel can > +communicate with P-SEAMLDR to perform runtime updates of the TDX Module. > + > +During updates, the TDX Module becomes unresponsive to other TDX > +operations. To prevent components using TDX (such as KVM) from experiencing > +unexpected errors during updates, updates are performed in stop_machine() > +context. During "updates" or "update"? The module only becomes unresponsive during "one module runtime update", correct? > + > +TDX Module updates have complex compatibility requirements; the new module > +must be compatible with the current CPU, P-SEAMLDR, and running TDX Module. > +Rather than implementing complex module selection and policy enforcement > +logic in the kernel, userspace is responsible for auditing and selecting > +appropriate updates. > + > +Updates use the standard firmware upload interface. See > +Documentation/driver-api/firmware/fw_upload.rst for detailed instructions > + > +Successful updates are logged in dmesg: > + [..] virt/tdx: version 1.5.20 -> 1.5.24 > + > +If updates failed, running TDs may be killed and further TDX operations may > +be not possible until reboot. For detailed error information, see > +Documentation/ABI/testing/sysfs-devices-faux-tdx-host. > + > +Given the risk of losing existing TDs, userspace should verify that the update > +is compatible with the current system and properly validated before applying it. > +A reference userspace tool that implements necessary checks is available at: > + > + https://github.com/intel/confidential-computing.tdx.tdx-module.binaries > + > TDX Interaction to Other Kernel Components > ------------------------------------------ > I think I've confused what you mean by "updates" or "update". Perhaps you mean the "steps" during module update as "updates"? But to me you indeed said "update" in the changelog: " - update is done in stop_machine() context - update instructions and results - update policy and tooling " Please make this consistent at least. With this clarified/addressed, feel free to add: Reviewed-by: Kai Huang <kai.huang@intel.com> ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates 2026-02-12 14:35 ` [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates Chao Gao 2026-03-04 23:49 ` Huang, Kai @ 2026-03-12 2:42 ` Edgecombe, Rick P 1 sibling, 0 replies; 5+ messages in thread From: Edgecombe, Rick P @ 2026-03-12 2:42 UTC (permalink / raw) To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Gao, Chao, x86@kernel.org Cc: corbet@lwn.net, Huang, Kai, dave.hansen@linux.intel.com, tony.lindgren@linux.intel.com, binbin.wu@linux.intel.com, seanjc@google.com, Weiny, Ira, Chatre, Reinette, Verma, Vishal L, nik.borisov@suse.com, mingo@redhat.com, kas@kernel.org, Annapurve, Vishal, sagis@google.com, Duan, Zhenzhong, tglx@kernel.org, paulmck@kernel.org, hpa@zytor.com, bp@alien8.de, yilun.xu@linux.intel.com, Williams, Dan J On Thu, 2026-02-12 at 06:35 -0800, Chao Gao wrote: > + > +Given the risk of losing existing TDs, userspace should verify that the update > +is compatible with the current system and properly validated before applying it. Maybe a new line here. > +A reference userspace tool that implements necessary checks is available at: > + > + https://github.com/intel/confidential-computing.tdx.tdx-module.binaries > + It looks good in general. My only question is if we know what kind of persistence this repo will have. These things can move around unfortunately. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 00/24] Runtime TDX Module update support 2026-02-12 14:35 [PATCH v4 00/24] Runtime TDX Module update support Chao Gao 2026-02-12 14:35 ` [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates Chao Gao @ 2026-02-12 14:46 ` Chao Gao 1 sibling, 0 replies; 5+ messages in thread From: Chao Gao @ 2026-02-12 14:46 UTC (permalink / raw) To: linux-coco, linux-kernel, kvm, x86, linux-doc Cc: reinette.chatre, ira.weiny, kai.huang, dan.j.williams, yilun.xu, sagis, vannapurve, paulmck, nik.borisov, zhenzhong.duan, seanjc, rick.p.edgecombe, kas, dave.hansen, vishal.l.verma, binbin.wu, tony.lindgren, Borislav Petkov, H. Peter Anvin, Ingo Molnar, Jonathan Corbet, Paolo Bonzini, Thomas Gleixner On Thu, Feb 12, 2026 at 06:35:03AM -0800, Chao Gao wrote: > >Note that like v3, this v4 is not based on Sean's VMXON series to make this >series more reviewable. There are some conflicts between Sean's VMXON v2 and this TDX module update series: 1. tdx_cpu_enable() is unexported in the VMXON series but used in this series. 2. tdx_module_status is removed in the VMXON series but accessed in this series. 3. Several functions are tagged as __init but called in this series at runtime Below is a sample diff showing how to resolve the conflicts. This series is not ready for merge yet. The diff is posted just to give you a sense of how these two series intersect: diff --cc arch/x86/include/asm/tdx.h index a149740b24e8,50a58160deef..000000000000 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@@ -97,57 -104,22 +104,21 @@@ static inline long tdx_kvm_hypercall(un #endif /* CONFIG_INTEL_TDX_GUEST && CONFIG_KVM_GUEST */ #ifdef CONFIG_INTEL_TDX_HOST - u64 __seamcall(u64 fn, struct tdx_module_args *args); - u64 __seamcall_ret(u64 fn, struct tdx_module_args *args); - u64 __seamcall_saved_ret(u64 fn, struct tdx_module_args *args); void tdx_init(void); + int tdx_cpu_enable(void); -int tdx_enable(void); + const char *tdx_dump_mce_info(struct mce *m); + const struct tdx_sys_info *tdx_get_sysinfo(void); - #include <linux/preempt.h> - #include <asm/archrandom.h> - #include <asm/processor.h> - - typedef u64 (*sc_func_t)(u64 fn, struct tdx_module_args *args); - - static __always_inline u64 __seamcall_dirty_cache(sc_func_t func, u64 fn, - struct tdx_module_args *args) + static inline bool tdx_supports_runtime_update(const struct tdx_sys_info *sysinfo) { - lockdep_assert_preemption_disabled(); - - /* - * SEAMCALLs are made to the TDX module and can generate dirty - * cachelines of TDX private memory. Mark cache state incoherent - * so that the cache can be flushed during kexec. - * - * This needs to be done before actually making the SEAMCALL, - * because kexec-ing CPU could send NMI to stop remote CPUs, - * in which case even disabling IRQ won't help here. - */ - this_cpu_write(cache_state_incoherent, true); - - return func(fn, args); + return sysinfo->features.tdx_features0 & TDX_FEATURES0_TD_PRESERVING; } - static __always_inline u64 sc_retry(sc_func_t func, u64 fn, - struct tdx_module_args *args) + static inline bool tdx_supports_update_compatibility(const struct tdx_sys_info *sysinfo) { - int retry = RDRAND_RETRY_LOOPS; - u64 ret; - - do { - preempt_disable(); - ret = __seamcall_dirty_cache(func, fn, args); - preempt_enable(); - } while (ret == TDX_RND_NO_ENTROPY && --retry); - - return ret; + return sysinfo->features.tdx_features0 & TDX_FEATURES0_UPDATE_COMPAT; } - #define seamcall(_fn, _args) sc_retry(__seamcall, (_fn), (_args)) - #define seamcall_ret(_fn, _args) sc_retry(__seamcall_ret, (_fn), (_args)) - #define seamcall_saved_ret(_fn, _args) sc_retry(__seamcall_saved_ret, (_fn), (_args)) - const char *tdx_dump_mce_info(struct mce *m); - const struct tdx_sys_info *tdx_get_sysinfo(void); - int tdx_guest_keyid_alloc(void); u32 tdx_get_nr_guest_keyids(void); void tdx_guest_keyid_free(unsigned int keyid); diff --cc arch/x86/virt/vmx/tdx/tdx.c index 55d3463e0e93,2cf3a01d0b9c..000000000000 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@@ -40,7 -39,8 +40,9 @@@ #include <asm/cpu_device_id.h> #include <asm/processor.h> #include <asm/mce.h> +#include <asm/virt.h> + + #include "seamcall_internal.h" #include "tdx.h" static u32 tdx_global_keyid __ro_after_init; @@@ -53,57 -53,16 +55,15 @@@ static DEFINE_PER_CPU(bool, tdx_lp_init static struct tdmr_info_list tdx_tdmr_list; -static enum tdx_module_status_t tdx_module_status; -static DEFINE_MUTEX(tdx_module_lock); + static bool sysinit_done; + static int sysinit_ret; + /* All TDX-usable memory regions. Protected by mem_hotplug_lock. */ static LIST_HEAD(tdx_memlist); -static struct tdx_sys_info tdx_sysinfo; +static struct tdx_sys_info tdx_sysinfo __ro_after_init; +static bool tdx_module_initialized __ro_after_init; - typedef void (*sc_err_func_t)(u64 fn, u64 err, struct tdx_module_args *args); - - static inline void seamcall_err(u64 fn, u64 err, struct tdx_module_args *args) - { - pr_err("SEAMCALL (0x%016llx) failed: 0x%016llx\n", fn, err); - } - - static inline void seamcall_err_ret(u64 fn, u64 err, - struct tdx_module_args *args) - { - seamcall_err(fn, err, args); - pr_err("RCX 0x%016llx RDX 0x%016llx R08 0x%016llx\n", - args->rcx, args->rdx, args->r8); - pr_err("R09 0x%016llx R10 0x%016llx R11 0x%016llx\n", - args->r9, args->r10, args->r11); - } - - static __always_inline int sc_retry_prerr(sc_func_t func, - sc_err_func_t err_func, - u64 fn, struct tdx_module_args *args) - { - u64 sret = sc_retry(func, fn, args); - - if (sret == TDX_SUCCESS) - return 0; - - if (sret == TDX_SEAMCALL_VMFAILINVALID) - return -ENODEV; - - if (sret == TDX_SEAMCALL_GP) - return -EOPNOTSUPP; - - if (sret == TDX_SEAMCALL_UD) - return -EACCES; - - err_func(fn, sret, args); - return -EIO; - } - - #define seamcall_prerr(__fn, __args) \ - sc_retry_prerr(__seamcall, seamcall_err, (__fn), (__args)) - - #define seamcall_prerr_ret(__fn, __args) \ - sc_retry_prerr(__seamcall_ret, seamcall_err_ret, (__fn), (__args)) - /* * Do the module global initialization once and return its result. * It can be done on any cpu. It's always called with interrupts @@@ -142,11 -99,17 +100,11 @@@ out } /** - * tdx_cpu_enable - Enable TDX on local cpu - * - * Do one-time TDX module per-cpu initialization SEAMCALL (and TDX module - * global initialization SEAMCALL if not done) on local cpu to make this - * cpu be ready to run any other SEAMCALLs. - * - * Always call this function via IPI function calls. - * - * Return 0 on success, otherwise errors. + * Enable VMXON and then do one-time TDX module per-cpu initialization SEAMCALL + * (and TDX module global initialization SEAMCALL if not done) on local cpu to + * make this cpu be ready to run any other SEAMCALLs. */ - static int tdx_cpu_enable(void) + int tdx_cpu_enable(void) { struct tdx_module_args args = {}; int ret; @@@ -1236,51 -1114,168 +1194,150 @@@ err_free_tdxmem goto out_put_tdxmem; } -static int __tdx_enable(void) +static __init int tdx_enable(void) { + enum cpuhp_state state; int ret; - ret = init_tdx_module(); - if (ret) { - pr_err("module initialization failed (%d)\n", ret); - tdx_module_status = TDX_MODULE_ERROR; - return ret; + if (!cpu_feature_enabled(X86_FEATURE_TDX_HOST_PLATFORM)) { + pr_err("TDX not supported by the host platform\n"); + return -ENODEV; } - pr_info("module initialized\n"); - tdx_module_status = TDX_MODULE_INITIALIZED; - - return 0; -} + if (!cpu_feature_enabled(X86_FEATURE_XSAVE)) { + pr_err("XSAVE is required for TDX\n"); + return -EINVAL; + } -/** - * tdx_enable - Enable TDX module to make it ready to run TDX guests - * - * This function assumes the caller has: 1) held read lock of CPU hotplug - * lock to prevent any new cpu from becoming online; 2) done both VMXON - * and tdx_cpu_enable() on all online cpus. - * - * This function requires there's at least one online cpu for each CPU - * package to succeed. - * - * This function can be called in parallel by multiple callers. - * - * Return 0 if TDX is enabled successfully, otherwise error. - */ -int tdx_enable(void) -{ - int ret; + if (!cpu_feature_enabled(X86_FEATURE_MOVDIR64B)) { + pr_err("MOVDIR64B is required for TDX\n"); + return -EINVAL; + } - if (!boot_cpu_has(X86_FEATURE_TDX_HOST_PLATFORM)) + if (!cpu_feature_enabled(X86_FEATURE_SELFSNOOP)) { + pr_err("Self-snoop is required for TDX\n"); return -ENODEV; + } - lockdep_assert_cpus_held(); - - mutex_lock(&tdx_module_lock); + state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "virt/tdx:online", + tdx_online_cpu, tdx_offline_cpu); + if (state < 0) + return state; - switch (tdx_module_status) { - case TDX_MODULE_UNINITIALIZED: - ret = __tdx_enable(); - break; - case TDX_MODULE_INITIALIZED: - /* Already initialized, great, tell the caller. */ - ret = 0; - break; - default: - /* Failed to initialize in the previous attempts */ - ret = -EINVAL; - break; + ret = init_tdx_module(); + if (ret) { + pr_err("TDX-Module initialization failed (%d)\n", ret); + cpuhp_remove_state(state); + return ret; } - mutex_unlock(&tdx_module_lock); + register_syscore(&tdx_syscore); - return ret; + tdx_module_initialized = true; + pr_info("TDX-Module initialized\n"); + return 0; } -EXPORT_SYMBOL_FOR_KVM(tdx_enable); +subsys_initcall(tdx_enable); + #define TDX_SYS_SHUTDOWN_AVOID_COMPAT_SENSITIVE BIT(16) + + int tdx_module_shutdown(void) + { + struct tdx_module_args args = {}; + u64 ret; + int cpu; + + /* + * Shut down the TDX Module and prepare handoff data for the next + * TDX Module. This SEAMCALL requires a handoff version. Use the + * module's handoff version, as it is the highest version the + * module can produce and is more likely to be supported by new + * modules as new modules likely have higher handoff version. + */ + args.rcx = tdx_sysinfo.handoff.module_hv; + + if (tdx_supports_update_compatibility(&tdx_sysinfo)) + args.rcx |= TDX_SYS_SHUTDOWN_AVOID_COMPAT_SENSITIVE; + + ret = seamcall(TDH_SYS_SHUTDOWN, &args); + + /* + * Return -EBUSY to signal that there is one or more ongoing flows + * which may not be compatible with an updated TDX module, so that + * userspace can retry on this error. + */ + if ((ret & TDX_SEAMCALL_STATUS_MASK) == TDX_UPDATE_COMPAT_SENSITIVE) + return -EBUSY; + else if (ret) + return -EIO; + - tdx_module_status = TDX_MODULE_UNINITIALIZED; ++ tdx_module_initialized = false; + sysinit_done = false; + sysinit_ret = 0; + + for_each_online_cpu(cpu) + per_cpu(tdx_lp_initialized, cpu) = false; + return 0; + } + + int tdx_module_run_update(void) + { + struct tdx_module_args args = {}; + int ret; + + ret = seamcall_prerr(TDH_SYS_UPDATE, &args); + if (ret) { + pr_err("TDX-Module update failed (%d)\n", ret); - tdx_module_status = TDX_MODULE_ERROR; + return ret; + } + - tdx_module_status = TDX_MODULE_INITIALIZED; ++ tdx_module_initialized = true; + return 0; + } + + /* + * Update tdx_sysinfo and check if any TDX module features changed after + * updates + */ + int tdx_module_post_update(struct tdx_sys_info *info) + { + struct tdx_sys_info_version *old, *new; + int ret; + + /* Shouldn't fail as the update has succeeded */ + ret = get_tdx_sys_info(info); + if (WARN_ONCE(ret, "version retrieval failed after update, replace TDX Module\n")) + return ret; + + old = &tdx_sysinfo.version; + new = &info->version; + pr_info("version %u.%u.%02u -> %u.%u.%02u\n", old->major_version, + old->minor_version, + old->update_version, + new->major_version, + new->minor_version, + new->update_version); + + /* + * Blindly refreshing the entire tdx_sysinfo could disrupt running + * software, as it may subtly rely on the previous state unless + * proven otherwise. + * + * Only refresh version information (including handoff version) + * that does not affect functionality, and ignore all other + * changes. + */ + tdx_sysinfo.version = info->version; + tdx_sysinfo.handoff = info->handoff; + + if (!memcmp(&tdx_sysinfo, info, sizeof(*info))) + return 0; + + pr_info("TDX module features have changed after updates, but might not take effect.\n"); + pr_info("Please consider updating your BIOS to install the TDX Module.\n"); + return 0; + } + static bool is_pamt_page(unsigned long phys) { struct tdmr_info_list *tdmr_list = &tdx_tdmr_list; @@@ -1530,12 -1525,17 +1587,12 @@@ void __init tdx_init(void const struct tdx_sys_info *tdx_get_sysinfo(void) { - const struct tdx_sys_info *p = NULL; - - /* Make sure all fields in @tdx_sysinfo have been populated */ - mutex_lock(&tdx_module_lock); - if (tdx_module_status == TDX_MODULE_INITIALIZED) - p = (const struct tdx_sys_info *)&tdx_sysinfo; - mutex_unlock(&tdx_module_lock); + if (!tdx_module_initialized) + return NULL; - return p; + return (const struct tdx_sys_info *)&tdx_sysinfo; } - EXPORT_SYMBOL_FOR_KVM(tdx_get_sysinfo); + EXPORT_SYMBOL_FOR_MODULES(tdx_get_sysinfo, "kvm-intel,tdx-host"); u32 tdx_get_nr_guest_keyids(void) { diff --cc arch/x86/virt/vmx/tdx/tdx_global_metadata.c index c7db393a9cfb,6aee10c36489..000000000000 --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-03-12 2:43 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-02-12 14:35 [PATCH v4 00/24] Runtime TDX Module update support Chao Gao 2026-02-12 14:35 ` [PATCH v4 23/24] x86/virt/tdx: Document TDX Module updates Chao Gao 2026-03-04 23:49 ` Huang, Kai 2026-03-12 2:42 ` Edgecombe, Rick P 2026-02-12 14:46 ` [PATCH v4 00/24] Runtime TDX Module update support Chao Gao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox