Linux Confidential Computing Development
 help / color / mirror / Atom feed
* [PATCH v2] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized
       [not found] <20261029080731.890996-1-challvy.tee@gmail.com>
@ 2026-10-29  9:47 ` Challvy Tee
  2026-10-29 12:10   ` Kiryl Shutsemau
  0 siblings, 1 reply; 2+ messages in thread
From: Challvy Tee @ 2026-10-29  9:47 UTC (permalink / raw)
  To: x86, linux-coco
  Cc: linux-kernel, regressions, dave.hansen, kas, rick.p.edgecombe,
	vishal.l.verma, kai.huang, Challvy Tee, stable

Commit 5b25f249be32 ("x86/tdx: Disable the TDX module during kexec and
kdump") made native_machine_crash_shutdown() call tdx_sys_disable(), but
tdx_sys_disable() has no runtime gate: its only guard is compile time
(CONFIG_INTEL_TDX_HOST), which is enabled in most kernel configs.  On a
system where the TDX module was never initialized, kdump now issues a
TDH.SYS.DISABLE SEAMCALL that it did not issue before, and the crash
path never reaches machine_kexec().  The capture kernel is never entered
and no vmcore is written, so kdump is completely non-functional.

Having the TDX module uninitialized is an ordinary state rather than an
error.  tdx_enable() returns -ENODEV early when
X86_FEATURE_TDX_HOST_PLATFORM is absent, and it also bails out if
init_tdx_module() fails.  Any guest whose host does not expose TDX is in
this state and logs:

  virt/tdx: TDX not supported by the host platform

The syscore path is implicitly protected: register_syscore() only runs
after init_tdx_module() succeeds, so tdx_shutdown() cannot be reached on
an uninitialized system.  That is why plain kexec still works and only
kdump regressed.

The crash path calls tdx_sys_disable() directly and bypasses that
protection.

Reproduced with 'echo c > /proc/sysrq-trigger' in VM guests on Intel
Sapphire Rapids, Emerald Rapids and Granite Rapids platforms, in every
case on a kernel that already contains the change described above: the
capture kernel is never entered and no vmcore is produced.  With this
patch applied kdump completes normally on all of them.

Three negative controls, all of which produce a vmcore as expected: the
same guests on kernels without that change, guests on platforms without
SEAM support, and plain kexec on every platform tested.

On a host where the module did initialize the new gate is a no-op and
TDH.SYS.DISABLE is still issued, so the poison clearing that the above
commit was added for is unaffected.  We do not have a TDX host to test
on, so this part is reasoned from the code rather than measured.

Gate the SEAMCALL on tdx_module_state.initialized, the same predicate
tdx_get_sysinfo() already uses in this file.  Putting the check inside
tdx_sys_disable() rather than at the crash.c call site also covers the
syscore caller and any future caller.

Fixes: 5b25f249be32 ("x86/tdx: Disable the TDX module during kexec and kdump")
Cc: stable@vger.kernel.org
Signed-off-by: Challvy Tee <challvy.tee@gmail.com>
---
v1 -> v2:
 - Use the real commit id 5b25f249be32 in the Fixes: tag and in the
   opening paragraph; v1 went out with a placeholder instead.
 - Drop the claim that nothing reaches the console.  panic() prints the
   message and backtrace before __crash_kexec(), so they do appear;
   describe the failure as the crash path never reaching machine_kexec()
   instead.
 - Drop the paragraph that explained why guests on platforms without
   SEAM support are unaffected.  It asserted a mechanism we have not
   verified, and the negative controls now carry the same information.
 - State explicitly that a host where the module did initialize is
   unaffected, so the poison clearing the fixed commit was added for
   still happens, and say plainly that we have no TDX host to test on.
 - Restrict the syscore claim to kexec: tdx_suspend() does not call
   tdx_sys_disable().
 - Resend with the full get_maintainer.pl recipient list.  v1 only
   reached stable@ and missed LKML and the x86 maintainers entirely.
   v1: https://lore.kernel.org/all/20261029080731.890996-1-challvy.tee@gmail.com/
 - No code change.
 arch/x86/virt/vmx/tdx/tdx.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 96ced0494b68..a7eae7492c1e 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -2321,6 +2321,9 @@ void tdx_sys_disable(void)
 	struct tdx_module_args args = {};
 	u64 ret;
 
+	if (!tdx_module_state.initialized)
+		return;
+
 	/*
 	 * Don't loop forever.
 	 *
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized
  2026-10-29  9:47 ` [PATCH v2] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized Challvy Tee
@ 2026-10-29 12:10   ` Kiryl Shutsemau
  0 siblings, 0 replies; 2+ messages in thread
From: Kiryl Shutsemau @ 2026-10-29 12:10 UTC (permalink / raw)
  To: Challvy Tee
  Cc: x86, linux-coco, linux-kernel, regressions, dave.hansen,
	rick.p.edgecombe, vishal.l.verma, kai.huang, stable

On Thu, Oct 29, 2026 at 05:47:05PM +0800, Challvy Tee wrote:
> Commit 5b25f249be32 ("x86/tdx: Disable the TDX module during kexec and
> kdump") made native_machine_crash_shutdown() call tdx_sys_disable(), but
> tdx_sys_disable() has no runtime gate: its only guard is compile time
> (CONFIG_INTEL_TDX_HOST), which is enabled in most kernel configs.  On a
> system where the TDX module was never initialized, kdump now issues a
> TDH.SYS.DISABLE SEAMCALL that it did not issue before, and the crash
> path never reaches machine_kexec().  The capture kernel is never entered
> and no vmcore is written, so kdump is completely non-functional.
> 
> Having the TDX module uninitialized is an ordinary state rather than an
> error.  tdx_enable() returns -ENODEV early when
> X86_FEATURE_TDX_HOST_PLATFORM is absent, and it also bails out if
> init_tdx_module() fails.  Any guest whose host does not expose TDX is in
> this state and logs:
> 
>   virt/tdx: TDX not supported by the host platform
> 
> The syscore path is implicitly protected: register_syscore() only runs
> after init_tdx_module() succeeds, so tdx_shutdown() cannot be reached on
> an uninitialized system.  That is why plain kexec still works and only
> kdump regressed.
> 
> The crash path calls tdx_sys_disable() directly and bypasses that
> protection.
> 
> Reproduced with 'echo c > /proc/sysrq-trigger' in VM guests on Intel
> Sapphire Rapids, Emerald Rapids and Granite Rapids platforms, in every
> case on a kernel that already contains the change described above: the
> capture kernel is never entered and no vmcore is produced.  With this
> patch applied kdump completes normally on all of them.
> 
> Three negative controls, all of which produce a vmcore as expected: the
> same guests on kernels without that change, guests on platforms without
> SEAM support, and plain kexec on every platform tested.
> 
> On a host where the module did initialize the new gate is a no-op and
> TDH.SYS.DISABLE is still issued, so the poison clearing that the above
> commit was added for is unaffected.  We do not have a TDX host to test
> on, so this part is reasoned from the code rather than measured.
> 
> Gate the SEAMCALL on tdx_module_state.initialized, the same predicate
> tdx_get_sysinfo() already uses in this file.  Putting the check inside
> tdx_sys_disable() rather than at the crash.c call site also covers the
> syscore caller and any future caller.
> 
> Fixes: 5b25f249be32 ("x86/tdx: Disable the TDX module during kexec and kdump")
> Cc: stable@vger.kernel.org
> Signed-off-by: Challvy Tee <challvy.tee@gmail.com>

The changelog is long for a three-line check, and it doesn't say why
the crash path stops. It takes time to understand what you try to fix.

A SEAMCALL that hits #UD is caught by the fixup in tdxcall.S and returns
TDX_SEAMCALL_UD; tdx_sys_disable() then leaves the loop without printing
anything. That is your no-SEAM control, and kdump works there.

On SPR and later, SEAMCALL in VMX non-root causes a VM exit instead, and
what happens next is up to the hypervisor. KVM injects #UD only since
9d7dfb95da2c ("KVM: VMX: Inject #UD if guest tries to execute SEAMCALL
or TDCALL"); before that it is an unexpected exit reason and the VMM
gets KVM_EXIT_INTERNAL_ERROR. What hypervisor are your guests running
on? Does the host log "unexpected exit reason 0x4c"?

If that is it, kdump is broken only in guests on SEAM-capable hosts
whose hypervisor doesn't handle the exit.

The changelog should say so in a couple of paragraphs.

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-29 12:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20261029080731.890996-1-challvy.tee@gmail.com>
2026-10-29  9:47 ` [PATCH v2] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized Challvy Tee
2026-10-29 12:10   ` Kiryl Shutsemau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox