Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [PATCH v3] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized
       [not found] <auM3KKutfutAqgWG@thinkstation>
@ 2026-10-30 15:48 ` Challvy Tee
  2026-10-30 16:13   ` Dave Hansen
  0 siblings, 1 reply; 4+ messages in thread
From: Challvy Tee @ 2026-10-30 15:48 UTC (permalink / raw)
  To: x86, linux-coco
  Cc: linux-kernel, kvm, regressions, stable, kas, dave.hansen,
	rick.p.edgecombe, vishal.l.verma, kai.huang, seanjc

Commit 5b25f249be32 ("x86/tdx: Disable the TDX module during kexec and
kdump") made native_machine_crash_shutdown() call tdx_sys_disable(),
whose only gate is compile time (CONFIG_INTEL_TDX_HOST).  A kernel that
never initialized the TDX module therefore still issues
TDH.SYS.DISABLE.

In VMX non-root operation on a SEAM-capable host, SEAMCALL causes a VM
exit instead of a native #UD.  KVM injects #UD only since
commit 9d7dfb95da2c ("KVM: VMX: Inject #UD if guest tries to execute
SEAMCALL or TDCALL"), first released in v6.18.  On an older host the
VMM gets KVM_EXIT_INTERNAL_ERROR and the vCPU never resumes, so
machine_kexec() is never reached and no vmcore is written.  Kdump is
thus broken only in guests on SEAM-capable hosts whose hypervisor does
not handle the exit; plain kexec is unaffected because tdx_shutdown()
only runs as a syscore op, registered after init_tdx_module() succeeds.

Gate the SEAMCALL on tdx_module_state.initialized, the predicate
tdx_get_sysinfo() already uses in this file: a kernel that never
initialized the module has no module to disable, and where it did the
gate is a no-op.  Doing it here rather than at the crash.c call site
also covers the syscore caller and any future one.

It also decouples kdump from the host KVM version -- a guest cannot
require its host to inject the #UD.

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>
---
v2 -> v3:
 - Rework the changelog around the VM exit mechanism from the review
   and scope the impact to guests on SEAM-capable hosts whose
   hypervisor does not handle the exit.
 - Shorten it and move the reproduction data below the fold.
 - Cc the author of the KVM commit now cited.  No code change.
   v2: https://lore.kernel.org/all/20261029094705.896693-1-challvy.tee@gmail.com/

Hypervisor -- KVM on all five (CPUID leaf 0x40000000), across three
clouds: Alibaba Cloud ECS, AWS EC2 and Tencent Cloud CVM.

Host log -- yes, from the Alibaba ECS host of the Emerald Rapids guest:

  KVM internal error. Suberror: 4
  extra data[0]: 4c
  extra data[1]: 2f
  RAX=0000000000000045 RDI=0000000000000045 RIP=ffffffff855422fe
  R12=8000020300000000 R13=8000000300000000 R14=8000020200000000
  Code=... 4c 8b 5e 28 <66> 0f 01 cf 72 05 ...
  check runstate transition: 'running' -> 'internal-error'

Suberror 4 is KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON; the two data
words are the exit reason (0x4c = EXIT_REASON_SEAMCALL) and
last_vmentry_cpu, i.e. kvm_prepare_unexpected_reason_exit().

RAX and RDI hold 0x45 = TDH_SYS_DISABLE and RIP is at the '66 0f 01 cf'
SEAMCALL opcode in __seamcall.  RAX still holds the input leaf rather
than a status code: the SEAMCALL never returned.

Reproduced with 'echo c > /proc/sysrq-trigger'.  All five have
CONFIG_INTEL_TDX_HOST=y, kexec_crash_loaded=1, a kernel changelog
naming both backported commits, and "TDX not supported by the host
platform" in dmesg:

  Microarch          x86_vfm  Cloud          Kernel             echo c
  Sapphire Rapids    0x68F    AWS EC2        6.12.0-278.el10    no vmcore
  Emerald Rapids     0x6CF    Alibaba ECS    6.12.0-278.el10    no vmcore
  Granite Rapids     0x6AD    Alibaba ECS    6.12.0-278.el10    no vmcore
  Granite Rapids     0x6AD    AWS EC2        6.12.0-278.el10    no vmcore
  Granite Rapids     0x6AD    Tencent CVM    6.12.0-278.el10    no vmcore

Controls, each producing a vmcore: the same platform on a kernel
without 5b25f249be32 (tdx_sys_disable absent from kallsyms), platforms
without SEAM support (Skylake, Cascade Lake, Ice Lake, AMD), and plain
kexec.

With the gate applied kdump produces a vmcore on the two Alibaba ECS
guests; the others have not been retested.  No TDX host was available,
so the no-op case is reasoned from the code rather than measured.

 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] 4+ messages in thread

* Re: [PATCH v3] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized
  2026-10-30 15:48 ` [PATCH v3] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized Challvy Tee
@ 2026-10-30 16:13   ` Dave Hansen
  2026-10-30 16:26     ` Kiryl Shutsemau
  0 siblings, 1 reply; 4+ messages in thread
From: Dave Hansen @ 2026-10-30 16:13 UTC (permalink / raw)
  To: Challvy Tee, x86, linux-coco
  Cc: linux-kernel, kvm, regressions, stable, kas, dave.hansen,
	rick.p.edgecombe, vishal.l.verma, kai.huang, seanjc

On 10/30/26 08:48, Challvy Tee wrote:
> --- 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;

NAK from me on this.

If SEAMCALL is fatal then we need stronger barriers on the generic paths
to SEAMCALLs themselves, not one-off patches of the sites.

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

* Re: [PATCH v3] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized
  2026-10-30 16:13   ` Dave Hansen
@ 2026-10-30 16:26     ` Kiryl Shutsemau
  2026-10-30 16:38       ` Dave Hansen
  0 siblings, 1 reply; 4+ messages in thread
From: Kiryl Shutsemau @ 2026-10-30 16:26 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Challvy Tee, x86, linux-coco, linux-kernel, kvm, regressions,
	stable, dave.hansen, rick.p.edgecombe, vishal.l.verma, kai.huang,
	seanjc

On Fri, Oct 30, 2026 at 09:13:12AM -0700, Dave Hansen wrote:
> On 10/30/26 08:48, Challvy Tee wrote:
> > --- 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;
> 
> NAK from me on this.
> 
> If SEAMCALL is fatal then we need stronger barriers on the generic paths
> to SEAMCALLs themselves, not one-off patches of the sites.

I don't think the generic path is the right place for it. For every
other caller, reaching a SEAMCALL on a non-TDX system means something
went wrong higher up, and we want to see it. A check there that quietly
returns an error hides that. Making it WARN would catch it, but then the
crash path would still need its own check before the call.

So gate the call on X86_FEATURE_TDX_HOST_PLATFORM, the same way
paddr_is_tdx_private() does.

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

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

* Re: [PATCH v3] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized
  2026-10-30 16:26     ` Kiryl Shutsemau
@ 2026-10-30 16:38       ` Dave Hansen
  0 siblings, 0 replies; 4+ messages in thread
From: Dave Hansen @ 2026-10-30 16:38 UTC (permalink / raw)
  To: Kiryl Shutsemau
  Cc: Challvy Tee, x86, linux-coco, linux-kernel, kvm, regressions,
	stable, dave.hansen, rick.p.edgecombe, vishal.l.verma, kai.huang,
	seanjc

On 10/30/26 09:26, Kiryl Shutsemau wrote:
>>
>> If SEAMCALL is fatal then we need stronger barriers on the generic paths
>> to SEAMCALLs themselves, not one-off patches of the sites.
> I don't think the generic path is the right place for it. For every
> other caller, reaching a SEAMCALL on a non-TDX system means something
> went wrong higher up, and we want to see it. A check there that quietly
> returns an error hides that. Making it WARN would catch it, but then the
> crash path would still need its own check before the call.
> 
> So gate the call on X86_FEATURE_TDX_HOST_PLATFORM, the same way
> paddr_is_tdx_private() does.

Sounds fine to me.

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

end of thread, other threads:[~2026-10-30 16:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <auM3KKutfutAqgWG@thinkstation>
2026-10-30 15:48 ` [PATCH v3] x86/virt/tdx: Skip TDH.SYS.DISABLE if the TDX module is not initialized Challvy Tee
2026-10-30 16:13   ` Dave Hansen
2026-10-30 16:26     ` Kiryl Shutsemau
2026-10-30 16:38       ` Dave Hansen

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