From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F206C1531E8; Wed, 20 May 2026 13:40:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284404; cv=none; b=oqzCKpCWWyjv0PeUXNkvAzN3JWVQ7qeP3Dc/TAdER15cMZ6u/fuba1gY1JrhJyy08DVQ47iOqd3WoZ+JY4gHmiPm7kXYFPhujiNTQcZXD2PcVrHqTU3w+gARzR0m+h1IkJ0/1mXtGDk5SEsGma483KJX4Wpbe9JPGKCJj4nEono= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284404; c=relaxed/simple; bh=Dnc6vYjOgJ7kPnjh+chu/5a8ACZuGGWSZJFZC4cfU6M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GG8IfVKstAT68dHjTjw4gfu1S60bd8jqevfGBXgPLCGSPyCqBliHuq/PaeOxFjpiS+2esQdQVbRHrNGuNZaEZNzE8EuxEFaWhPfPrCb6hAsmXcTIgWBXV3U2lWSo2umEA51CHfyctR2tOen3RXF3tGxgH25sxkmWqvkheMqRs0w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=GH5XFL/+; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="GH5XFL/+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284402; x=1810820402; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Dnc6vYjOgJ7kPnjh+chu/5a8ACZuGGWSZJFZC4cfU6M=; b=GH5XFL/+gDUJ5DbQ/2/hJ+TxmzSIQb9e32AUlp8GXaoJWTpJtM78o9Cw 3keZaWLvuoeP0xJqGdnob8SVb2nlb95DPS6CLMYu6IrRaxcT1ESH1SEL/ TV7E3VblHhL4AK2/ysN59AvX/F117kfex66S2dIct03ybdLG+zQOBvLuC ROa/Aedp+8QGIRllZIjdZOWhnMRXeAD+S7JOcjtX3hPUwlPXnVq/PcPQ/ 0ouFzulzIwj6V0tAIWlQxVZYyj+5PP5AQ3JSo1MU2tNlvwhVfReyemlxX 52QwNuwF8Jj5NkESxv03R/6ZyuqIbYlY8pSQ6C835GCW4cpbI5ySbAVPC A==; X-CSE-ConnectionGUID: 7EvSNPNXRs+AwIWcGpVWsQ== X-CSE-MsgGUID: AK61UmP3S/iqoqEDmWMAdA== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146387" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146387" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:00 -0700 X-CSE-ConnectionGUID: kgJHbNTvQFCArELGFUUbYg== X-CSE-MsgGUID: 3Vag2oDBSAKCkuj3p+Xj8Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923599" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:39:59 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 01/25] x86/virt/tdx: Clarify try_init_module_global() result caching Date: Wed, 20 May 2026 06:38:04 -0700 Message-ID: <20260520133909.409394-2-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TDX module global initialization is executed only once. The first call caches both the result and the "done" state, and later callers reuse the saved result. A lock protects that cached state. The current code is hard to read because sysinit_done is accessed under the lock, while sysinit_ret is not. To improve readability, move sysinit_ret accesses within the lock. Group sysinit_ret/sysinit_done updates right after initialization so Caching the result is separate from the initialization itself. Signed-off-by: Chao Gao Reviewed-by: Xiaoyao Li --- arch/x86/virt/vmx/tdx/tdx.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index c0c6281b08a5..ad56f142dd0b 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -115,28 +115,34 @@ static int try_init_module_global(void) static DEFINE_RAW_SPINLOCK(sysinit_lock); static bool sysinit_done; static int sysinit_ret; + int ret; =20 raw_spin_lock(&sysinit_lock); =20 - if (sysinit_done) + /* Return the "cached" return code. */ + if (sysinit_done) { + ret =3D sysinit_ret; goto out; + } =20 /* RCX is module attributes and all bits are reserved */ args.rcx =3D 0; - sysinit_ret =3D seamcall_prerr(TDH_SYS_INIT, &args); + ret =3D seamcall_prerr(TDH_SYS_INIT, &args); =20 /* * The first SEAMCALL also detects the TDX module, thus * it can fail due to the TDX module is not loaded. * Dump message to let the user know. */ - if (sysinit_ret =3D=3D -ENODEV) + if (ret =3D=3D -ENODEV) pr_err("module not loaded\n"); =20 + /* Save the return code for later callers. */ sysinit_done =3D true; + sysinit_ret =3D ret; out: raw_spin_unlock(&sysinit_lock); - return sysinit_ret; + return ret; } =20 /** --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC2192E2F1F; Wed, 20 May 2026 13:40:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284408; cv=none; b=cKIJ63ttqSnLGwaIzzqAnV/+WmfX7V25dzNq9JfsIq6cRqx/C+P9EWzGJJ5dC1B7IejXkBFXTenD07pt/nsZD7CswIMHSipTHbnWtra17IbzB6Y9Xt/MRS1/cZr+wZZMDzxJRBit6r2z2LEY1fS1Ldka3eEwRz+c0MXs4+xH2Ug= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284408; c=relaxed/simple; bh=8rfjTJTMMNoR4Sspo8JUOf6q9kOwUDez03bzPGnIrnk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ApqCTRG9REclED/3YxI6oYi28YBv8vckjWQzlsz3zxDPsIuRdABqrObrPXWTa7Llc2nFjQD9YeF3gE34o0G3YACLmQK/4wK1LCM0Ea4xQJsRbK8psEWr7oOHnFJ+9XbOIbOnYzqiIAI0X/bVpyyoM7SJ/+bWKwDzM2gf3/rTm2k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=N1/qMy2x; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="N1/qMy2x" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284404; x=1810820404; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8rfjTJTMMNoR4Sspo8JUOf6q9kOwUDez03bzPGnIrnk=; b=N1/qMy2xcI7IrmkCJQy/QGRDph0vPNo4PkzYZW6SyVx9Pb8KHemYp7fG Ziq9LA7+YGC6IPnnwjNZBtmRVzGwnzbjThG6ZkcH8goRxGAMnQX0QuHcS Qqy+PtwG5oUZgJHX/NgSRZ5GsWtLBJCFosk2G7mvVItxP3z4hk7i8+rNz LxBaP8vjgmZ7xIwmIWPtTq+I4g/JUZYMUB7M/EEr13OYD2v5XIuJeUqcM pPbcZvXdjcfdIC4XnTYzXp7W3uIXNiX+vZD8noXs9K/UKxoEWBTWWUO76 s0+MhOWsdJoR3tl1bnUUo+c47BXkdE3YuxQMD42y6by3NEiBpRpgA3q6+ g==; X-CSE-ConnectionGUID: kUYE5tiQQG6Urw18mEY2jw== X-CSE-MsgGUID: 7ubk0ABORNC+NtcJTJeSoA== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146397" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146397" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:01 -0700 X-CSE-ConnectionGUID: lPpUJ2FUSoW6dEo4n3TOHQ== X-CSE-MsgGUID: 7Amo8i5SSfWs5y6dzfuB+Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923613" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:00 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 02/25] x86/virt/tdx: Move TDX global initialization states to file scope Date: Wed, 20 May 2026 06:38:05 -0700 Message-ID: <20260520133909.409394-3-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TDX module global initialization is executed only once. The first call caches both the result and the "done" state, and later callers reuse the saved result. A lock protects that cached states. Those states and the lock are currently kept as function-local statics because they are used only by try_init_module_global(). TDX module updates need to reset the cached states so TDX global initialization can be run again after an update. That will add another access site in the same file. Move the cached states to file scope so it is accessible outside try_init_module_global(), and move the lock along with the states it protects. No functional change intended. Signed-off-by: Chao Gao Reviewed-by: Xiaoyao Li --- arch/x86/virt/vmx/tdx/tdx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index ad56f142dd0b..40444a3c5cdd 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -105,6 +105,10 @@ static __always_inline int sc_retry_prerr(sc_func_t fu= nc, #define seamcall_prerr_ret(__fn, __args) \ sc_retry_prerr(__seamcall_ret, seamcall_err_ret, (__fn), (__args)) =20 +static DEFINE_RAW_SPINLOCK(sysinit_lock); +static bool sysinit_done; +static int sysinit_ret; + /* * Do the module global initialization once and return its result. * It can be done on any cpu, and from task or IRQ context. @@ -112,9 +116,6 @@ static __always_inline int sc_retry_prerr(sc_func_t fun= c, static int try_init_module_global(void) { struct tdx_module_args args =3D {}; - static DEFINE_RAW_SPINLOCK(sysinit_lock); - static bool sysinit_done; - static int sysinit_ret; int ret; =20 raw_spin_lock(&sysinit_lock); --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 488373AA1B2; Wed, 20 May 2026 13:40:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284408; cv=none; b=oVxTeIFdI7vzq//f2bRHzUg3O9Iafgg48lSOeCDPS8MLHCcv4AZFP5zFrkCnMOo/+2VBeV+e4j9OR4+YGFNdE1KREFdadM4VpOnXsdFbiF6+y9QG7k+JDG3bnsrIQ+F0trgafcZ+tGE7gcsQtu8Ahut9prHO1Hhe7wBwCg10V60= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284408; c=relaxed/simple; bh=pYwWR633SCu4170yEG3u38P71vF4aiFiBV8uRgld4Bk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WW3BEsjYE8w9v26eSSW82eQGD7/x4is0wsReefVvfw/tzgjDWVwzLGWuU+uLx+rvZSs43NhgZw3SDoa3Zwx2SfJhiAdi5tEYVNan+ueQLHi57or2qDPls8ExMm/tg3JbpEmjQjdz2uvf1dns5yco6i33XwIBl5vTahZ5tkroRzs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=HhK7NxaE; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="HhK7NxaE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284405; x=1810820405; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=pYwWR633SCu4170yEG3u38P71vF4aiFiBV8uRgld4Bk=; b=HhK7NxaEO6kFu145o9vajYDaUIf5ivKJiCqPFALSAuQJ7d7d4ThBK0GJ rCARWESi/pSp4f6BYtfY6Q6TA4HbhkrVx5NCxbOQVCTgIHajzgN6NmDGb 0GT5J1GbHrqjX6Jf57xjfJFyQipOj1+27ZUrPQEARW9MfqIuoSh/9bH34 5qYEVxCJ//EwgrJRwJiFss5rHJzoA9Zv+q7zUE2QD5xjRdIvVDcLd1hrn dqN61+APrrqOE94dZriLFAPCQuI1uAcO33gGxu9f8WKghkuamROATQfFn hrVw/zoOdAo7Dk4v0qZLlhNSUXNou9isGWyj01tYzRXt+MlDOcaNI66Us Q==; X-CSE-ConnectionGUID: UE7u/h6eTWWul5DI0n8ZiQ== X-CSE-MsgGUID: 8RPFRUkiTGqx+xWZHfXxGg== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146409" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146409" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:03 -0700 X-CSE-ConnectionGUID: N0cyFpTcQbSqoKy6pv3TTg== X-CSE-MsgGUID: GsjXY3yJSP6voBnVDe6X6w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923641" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:01 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 03/25] x86/virt/tdx: Consolidate TDX global initialization states Date: Wed, 20 May 2026 06:38:06 -0700 Message-ID: <20260520133909.409394-4-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The kernel uses several global flags to guard one-time TDX initialization flows and prevent them from being repeated. When the TDX module is updated, all of those states must be reset so that the module can be initialized again. Today those states are kept as separate global variables, which makes the reset path awkward and easy to miss when a new state is added. Group the states into a single structure so they can be reset together, for example with memset(), and so a newly added state won't be missed. Drop the __ro_after_init annotation from tdx_module_initialized because the other two states do not have it. And with TDX module update support, all the states need to be writable at runtime. Signed-off-by: Chao Gao Reviewed-by: Xiaoyao Li --- arch/x86/virt/vmx/tdx/tdx.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 40444a3c5cdd..71d39a79ef3f 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -44,6 +44,13 @@ #include #include "tdx.h" =20 +struct tdx_module_state { + bool initialized; + bool sysinit_done; + int sysinit_ret; +}; + +static struct tdx_module_state tdx_module_state; static u32 tdx_global_keyid __ro_after_init; static u32 tdx_guest_keyid_start __ro_after_init; static u32 tdx_nr_guest_keyids __ro_after_init; @@ -58,7 +65,6 @@ static struct tdmr_info_list tdx_tdmr_list; static LIST_HEAD(tdx_memlist); =20 static struct tdx_sys_info tdx_sysinfo __ro_after_init; -static bool tdx_module_initialized __ro_after_init; =20 typedef void (*sc_err_func_t)(u64 fn, u64 err, struct tdx_module_args *arg= s); =20 @@ -106,8 +112,6 @@ static __always_inline int sc_retry_prerr(sc_func_t fun= c, sc_retry_prerr(__seamcall_ret, seamcall_err_ret, (__fn), (__args)) =20 static DEFINE_RAW_SPINLOCK(sysinit_lock); -static bool sysinit_done; -static int sysinit_ret; =20 /* * Do the module global initialization once and return its result. @@ -121,8 +125,8 @@ static int try_init_module_global(void) raw_spin_lock(&sysinit_lock); =20 /* Return the "cached" return code. */ - if (sysinit_done) { - ret =3D sysinit_ret; + if (tdx_module_state.sysinit_done) { + ret =3D tdx_module_state.sysinit_ret; goto out; } =20 @@ -139,8 +143,8 @@ static int try_init_module_global(void) pr_err("module not loaded\n"); =20 /* Save the return code for later callers. */ - sysinit_done =3D true; - sysinit_ret =3D ret; + tdx_module_state.sysinit_done =3D true; + tdx_module_state.sysinit_ret =3D ret; out: raw_spin_unlock(&sysinit_lock); return ret; @@ -1306,7 +1310,7 @@ static __init int tdx_enable(void) =20 register_syscore(&tdx_syscore); =20 - tdx_module_initialized =3D true; + tdx_module_state.initialized =3D true; pr_info("TDX-Module initialized\n"); return 0; } @@ -1561,7 +1565,7 @@ void __init tdx_init(void) =20 const struct tdx_sys_info *tdx_get_sysinfo(void) { - if (!tdx_module_initialized) + if (!tdx_module_state.initialized) return NULL; =20 return (const struct tdx_sys_info *)&tdx_sysinfo; --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B3413A6B6E; Wed, 20 May 2026 13:40:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284409; cv=none; b=Bg5b20jOLQ4ggD5yg7QjTZ9sX6617xpZspQBUmBAjJR7QRIqqgtQ+YG/yOI5x31PCOf0nww/2Bx0Um3ubNmqamoXc6biubKTpiH/rxaMOSRUO5Q2idhAYAbCZIsLW2L7deV2Akohxf5QKhN5281f0bJIETtsYmS+Kr4FFfcRmgo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284409; c=relaxed/simple; bh=vsVXOzX+eZdIz/SpvJEyplhhhAPnPHgd18pUAlvF5Rk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oSFtJyBpC3PjNx8KkvS9wleBUtZvONn8kI83BG48B/8zTVEQRRbmkNMiVhm35h9glJWztCl1Hn9O1S0rC3u1zted0qD9XZqnB1TJyg880SbovGRTOMTMR5yx0ZwzQOGDFcOORQZApQzVynnpzzBcYHTbRH/7HdtsVUXbiiXA1/E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=OJi2Xsif; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="OJi2Xsif" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284406; x=1810820406; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=vsVXOzX+eZdIz/SpvJEyplhhhAPnPHgd18pUAlvF5Rk=; b=OJi2XsifYKEx5I/inc5HA9ptFnIZKzhokV+2tPAbq/YMj3YF1FhvFCqW qBUyllFnv0KqRCzvNgCNNblPXUk93Ls4soJj+KCRcPNjpX4/gCfke7sQo gp27uPBAocYW/1zinbNMKl2hLk/lU8CK/l4532rclqdYSlxvkIZaYzys8 FHeO6DFNHFY6mzS+Q+s2p+WNmUlJIaVImV9FYCbJKS7J3fD7J366dvSS0 pUFtuTprB3LykLc5fO8B3Qgxte5xQZCSOGUAtxUzWlqt56uhcy9CmuDbK q3Jhg4O0eWg75nlohA8Di192xsAcJoZuo1A4tpY38UFS0tBDnTR181bIZ w==; X-CSE-ConnectionGUID: ZCejHnOcSA+O6n1U9crd8Q== X-CSE-MsgGUID: TS/iozRhRh2umPqbqiID/w== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146419" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146419" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:05 -0700 X-CSE-ConnectionGUID: 6acRzcItSce0dn3NDOrwIg== X-CSE-MsgGUID: z72y8QSlT2yRZTdichrdTA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923680" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:02 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 04/25] x86/virt/tdx: Move TDX_FEATURES0 bits to asm/tdx.h Date: Wed, 20 May 2026 06:38:07 -0700 Message-ID: <20260520133909.409394-5-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Future changes will add support for new TDX features exposed as TDX_FEATURES0 bits. The presence of these features will need to be checked outside of arch/x86/virt. So the feature query helpers, and the TDX_FEATURES0 defines they reference, will need to live in the widely accessible asm/tdx.h header. Move the existing TDX_FEATURES0 to asm/tdx.h so that they can all be kept together. Opportunistically switch to BIT_ULL() since TDX_FEATURES0 is 64-bit. No functional change intended. Signed-off-by: Chao Gao Link: https://lore.kernel.org/kvm/20260427152854.101171-17-chao.gao@intel.c= om/ # [1] Link: https://lore.kernel.org/kvm/20251121005125.417831-16-rick.p.edgecombe= @intel.com/ # [2] Reviewed-by: Xiaoyao Li --- arch/x86/include/asm/tdx.h | 3 +++ arch/x86/virt/vmx/tdx/tdx.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 15eac89b0afb..e2430dd0e4d5 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -32,6 +32,9 @@ #define TDX_SUCCESS 0ULL #define TDX_RND_NO_ENTROPY 0x8000020300000000ULL =20 +/* Bit definitions of TDX_FEATURES0 metadata field */ +#define TDX_FEATURES0_NO_RBP_MOD BIT_ULL(18) + #ifndef __ASSEMBLER__ =20 #include diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index e2cf2dd48755..76c5fb1e1ffe 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -85,9 +85,6 @@ struct tdmr_info { DECLARE_FLEX_ARRAY(struct tdmr_reserved_area, reserved_areas); } __packed __aligned(TDMR_INFO_ALIGNMENT); =20 -/* Bit definitions of TDX_FEATURES0 metadata field */ -#define TDX_FEATURES0_NO_RBP_MOD BIT(18) - /* * Do not put any hardware-defined TDX structure representations below * this comment! --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 126D73DC4CD; Wed, 20 May 2026 13:40:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284412; cv=none; b=t9neDqX8E0F6jquBsBjeIHJtwKskOnvVe1tSV5kCOZfglWpGEtPcmQC1lhQqN52Ea5nFWujP10i83FoHzVpRkp65thXPPbg0cGV89FKZOtGk2WoOYnQJCI+TZARdMXZ5ILZCsoiiEMS7ItYikReLCQyzMdE/wOafjolvOa5XQzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284412; c=relaxed/simple; bh=A3yJHdoCDPK1tBuaRjsUHFUHq6wyZnUlvrnhjVUqUeI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZSDlqp6n81R7KaYBi5alulLKULJqwa/JPQw3cH6Wbyd++FWrXnYFRhSyQ3/oB7kysS7FqHz1Vea1tIdHUUQDbZqwW4wArwg54yPNXCAw/Dp3Uvc6AeKgRMfebNVH2C6FjCBf8ASR9OgihX+Dy0aVUjWVxc/eycG5ZtpZ76jsntM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=GcdEmZKO; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="GcdEmZKO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284410; x=1810820410; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=A3yJHdoCDPK1tBuaRjsUHFUHq6wyZnUlvrnhjVUqUeI=; b=GcdEmZKOqUdMhJH1PCnzX4t+7QdP7eW0TsgWwyl3vRiUgarFsJPAQbYx 0huVdupMIJ2FxzvGfK7cnldua1mMMW691rGIYE7DrQ7l42ti9xu6avR2w hFT7ujOfF/cTPLpog5NigrWr1UQgGvO6BiXH4TS4kMeOW63JbYE4v9acv oP+Sv8VPr3mucMvcUEM4nvTkMrPo35rfxD9QXXPvhBDV2KhK1sVqP37qJ IFoJTc79AgRMl8rTxsUGVA9M69YXpdPbKSYbFhQxy45s5nhXNlNx6et/v D1UMIf+i3QwsshGxTclyUWDJ6hnS/wdZ7MVqxsYYvmTy50Ts+5xogSXKc g==; X-CSE-ConnectionGUID: 6tTRRd6rRzWAxKrB4CGiSA== X-CSE-MsgGUID: nx4M/TPRRP2y76bpB6urjQ== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146430" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146430" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:09 -0700 X-CSE-ConnectionGUID: uu6N6Z4URACRSydUXP7cOg== X-CSE-MsgGUID: VERWiynOQOODjK4fWwe/NQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923728" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:04 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Zhenzhong Duan , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 05/25] x86/virt/tdx: Move low level SEAMCALL helpers out of Date: Wed, 20 May 2026 06:38:08 -0700 Message-ID: <20260520133909.409394-6-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kai Huang TDX host core code implements three seamcall*() helpers to make SEAMCALLs to the TDX module. Currently, they are implemented in and are exposed to other kernel code which includes . However, other than the TDX host core, seamcall*() are not expected to be used by other kernel code directly. For instance, for all SEAMCALLs that are used by KVM, the TDX host core exports a wrapper function for each of them. Move seamcall*() and related code out of and make them only visible to TDX host core. Since TDX host core tdx.c is already very heavy, don't put low level seamcall*() code there but to a new dedicated "seamcall_internal.h". Also, currently tdx.c has seamcall_prerr*() helpers which additionally print error message when calling seamcall*() fails. Move them to "seamcall_internal.h" as well. In such way all low level SEAMCALL helpers are in a dedicated place, which is much more readable. Copy the copyright notice from the original files and consolidate the date ranges to: Copyright (C) 2021-2023 Intel Corporation Signed-off-by: Kai Huang Signed-off-by: Chao Gao Reviewed-by: Zhenzhong Duan Reviewed-by: Binbin Wu Reviewed-by: Tony Lindgren Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Xiaoyao Li Reviewed-by: Vishal Annapurve Acked-by: Dave Hansen --- arch/x86/include/asm/tdx.h | 47 ---------- arch/x86/virt/vmx/tdx/seamcall_internal.h | 109 ++++++++++++++++++++++ arch/x86/virt/vmx/tdx/tdx.c | 47 +--------- 3 files changed, 111 insertions(+), 92 deletions(-) create mode 100644 arch/x86/virt/vmx/tdx/seamcall_internal.h diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index e2430dd0e4d5..8b739ac01479 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -100,54 +100,7 @@ static inline long tdx_kvm_hypercall(unsigned int nr, = unsigned long p1, #endif /* CONFIG_INTEL_TDX_GUEST && CONFIG_KVM_GUEST */ =20 #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); - -#include -#include -#include - -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) -{ - 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); -} - -static __always_inline u64 sc_retry(sc_func_t func, u64 fn, - struct tdx_module_args *args) -{ - int retry =3D RDRAND_RETRY_LOOPS; - u64 ret; - - do { - preempt_disable(); - ret =3D __seamcall_dirty_cache(func, fn, args); - preempt_enable(); - } while (ret =3D=3D TDX_RND_NO_ENTROPY && --retry); - - return ret; -} - -#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); =20 diff --git a/arch/x86/virt/vmx/tdx/seamcall_internal.h b/arch/x86/virt/vmx/= tdx/seamcall_internal.h new file mode 100644 index 000000000000..be5f446467df --- /dev/null +++ b/arch/x86/virt/vmx/tdx/seamcall_internal.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * SEAMCALL utilities for TDX host-side operations. + * + * Provides convenient wrappers around SEAMCALL assembly with retry logic, + * error reporting and cache coherency tracking. + * + * Copyright (C) 2021-2023 Intel Corporation + */ + +#ifndef _X86_VIRT_SEAMCALL_INTERNAL_H +#define _X86_VIRT_SEAMCALL_INTERNAL_H + +#include +#include +#include +#include +#include + +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); + +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) +{ + 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); +} + +static __always_inline u64 sc_retry(sc_func_t func, u64 fn, + struct tdx_module_args *args) +{ + int retry =3D RDRAND_RETRY_LOOPS; + u64 ret; + + do { + preempt_disable(); + ret =3D __seamcall_dirty_cache(func, fn, args); + preempt_enable(); + } while (ret =3D=3D TDX_RND_NO_ENTROPY && --retry); + + return ret; +} + +#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)) + +typedef void (*sc_err_func_t)(u64 fn, u64 err, struct tdx_module_args *arg= s); + +static inline void seamcall_err(u64 fn, u64 err, struct tdx_module_args *a= rgs) +{ + 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 =3D sc_retry(func, fn, args); + + if (sret =3D=3D TDX_SUCCESS) + return 0; + + if (sret =3D=3D TDX_SEAMCALL_VMFAILINVALID) + return -ENODEV; + + if (sret =3D=3D TDX_SEAMCALL_GP) + return -EOPNOTSUPP; + + if (sret =3D=3D 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)) + +#endif /* _X86_VIRT_SEAMCALL_INTERNAL_H */ diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 71d39a79ef3f..b329791db9c2 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -42,6 +42,8 @@ #include #include #include + +#include "seamcall_internal.h" #include "tdx.h" =20 struct tdx_module_state { @@ -66,51 +68,6 @@ static LIST_HEAD(tdx_memlist); =20 static struct tdx_sys_info tdx_sysinfo __ro_after_init; =20 -typedef void (*sc_err_func_t)(u64 fn, u64 err, struct tdx_module_args *arg= s); - -static inline void seamcall_err(u64 fn, u64 err, struct tdx_module_args *a= rgs) -{ - 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 =3D sc_retry(func, fn, args); - - if (sret =3D=3D TDX_SUCCESS) - return 0; - - if (sret =3D=3D TDX_SEAMCALL_VMFAILINVALID) - return -ENODEV; - - if (sret =3D=3D TDX_SEAMCALL_GP) - return -EOPNOTSUPP; - - if (sret =3D=3D 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)) - static DEFINE_RAW_SPINLOCK(sysinit_lock); =20 /* --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE7912D97BB; Wed, 20 May 2026 13:40:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284416; cv=none; b=RMbSw+7X6A6i6LwOk6iVvc1FVH3QMNVVug15MGnDFC6dCsrETbvJg4eyYR1ZsDkIKJht2r13D/X27lsOIZgcj+QLsh1RG5gB+toIQqaBAaljKplUNTZuS3epYp/trupcbPnImoL7Xnt3xWiBNWptCXTNdEFPg40Bcrt3iwIF4AE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284416; c=relaxed/simple; bh=OB5KK7/DzK4PibNM8rdSPzLUWiGXEh1JtVXCtjv2v8o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pBrtDAUb1aLEbg7ZA4hL00bt81daNCpSQOzuj2gIo0rU1lT2zP6hN3Nn3qbvHqMB6NZfyQZcE2qXhYeXXZDYxqKUDqUZco8BBGw8J4W7NoGkAXno48UNGMYVuM/NVo24u472b3cEh99VjWKdVh9aucM9p6C5xH0vv6w398+6vr0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Nn4J1MT6; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Nn4J1MT6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284412; x=1810820412; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OB5KK7/DzK4PibNM8rdSPzLUWiGXEh1JtVXCtjv2v8o=; b=Nn4J1MT6MqJsNycFPayS6SqjxS6//OPx7EEyA9qjLOxAKdp3ZeY4E0Bc 3AXzA3JUwh5xHq6xhl92OZnWINLfuY0kcaL4E7gIhu4rLN+o0bpkfwryQ GlMOl9TLota7Hk4q7Zb5CHGxY+V1zQM1lSoCO91Ff6ED/JMrS2c4SzBaa dxjdeCRAdxon7z3K/VWqeVZerzyD8ZbH353x/RYHMAsbNuUi0ZebGGP1z Wz9N+/TRmil5KwoiFEJumIq7CttENe9rdH16pmDjlwjWmLzeviSDTa42Z 6NsS+q1GjQI3vsjx7ocV22B75mtGXeiH2fy6uZy90eOCG1Q2MBmpNULaM g==; X-CSE-ConnectionGUID: VdZVqWGFRNCiFWU20atqRg== X-CSE-MsgGUID: kMGM9kQ0TAmBPWZyS/+Vgw== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146440" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146440" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:10 -0700 X-CSE-ConnectionGUID: W5mijFsHRGKXZCU+ilAHDQ== X-CSE-MsgGUID: WPonONw7TBiUFfQOGGT58w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923756" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:06 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Jonathan Cameron , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 06/25] coco/tdx-host: Introduce a "tdx_host" device Date: Wed, 20 May 2026 06:38:09 -0700 Message-ID: <20260520133909.409394-7-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TDX depends on a platform firmware module that is invoked via instructions similar to vmenter (i.e. enter into a new privileged "root-mode" context to manage private memory and private device mechanisms). It is a software construct that depends on the CPU vmxon state to enable invocation of TDX module ABIs. Unlike other Trusted Execution Environment (TEE) platform implementations that employ a firmware module running on a PCI device with an MMIO mailbox for communication, TDX has no hardware device to point to as the TEE Secure Manager (TSM). Create a virtual device not only to align with other implementations but also to make it easier to - expose metadata (e.g., TDX module version, seamldr version etc) to the userspace as device attributes - implement firmware uploader APIs which are tied to a device. This is needed to support TDX module runtime updates - enable TDX Connect which will share a common infrastructure with other platform implementations. In the TDX Connect context, every architecture has a TSM, represented by a PCIe or virtual device. The new "tdx_host" device will serve the TSM role. A faux device is used for TDX because the TDX module is singular within the system and lacks associated platform resources. Using a faux device eliminates the need to create a stub bus. The call to tdx_get_sysinfo() ensures that the TDX module is ready to provide services. Note that AMD has a PCI device for the PSP for SEV and ARM CCA will likely have a faux device [1]. Thanks to Dan and Yilun for all the help on this one. Signed-off-by: Chao Gao Reviewed-by: Jonathan Cameron Reviewed-by: Tony Lindgren Reviewed-by: Xu Yilun Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Xiaoyao Li Link: https://lore.kernel.org/all/2025073035-bulginess-rematch-b92e@gregkh/= # [1] --- v10: - Drop Kconfig prompt [Dave] --- arch/x86/virt/vmx/tdx/tdx.c | 2 +- drivers/virt/coco/Kconfig | 2 ++ drivers/virt/coco/Makefile | 1 + drivers/virt/coco/tdx-host/Kconfig | 4 +++ drivers/virt/coco/tdx-host/Makefile | 1 + drivers/virt/coco/tdx-host/tdx-host.c | 43 +++++++++++++++++++++++++++ 6 files changed, 52 insertions(+), 1 deletion(-) 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 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index b329791db9c2..5fb0441a9ac6 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1527,7 +1527,7 @@ const struct tdx_sys_info *tdx_get_sysinfo(void) =20 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"); =20 u32 tdx_get_nr_guest_keyids(void) { diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index df1cfaf26c65..f7691f64fbe3 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -17,5 +17,7 @@ source "drivers/virt/coco/arm-cca-guest/Kconfig" source "drivers/virt/coco/guest/Kconfig" endif =20 +source "drivers/virt/coco/tdx-host/Kconfig" + config TSM bool diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index cb52021912b3..b323b0ae4f82 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_EFI_SECRET) +=3D efi_secret/ obj-$(CONFIG_ARM_PKVM_GUEST) +=3D pkvm-guest/ obj-$(CONFIG_SEV_GUEST) +=3D sev-guest/ obj-$(CONFIG_INTEL_TDX_GUEST) +=3D tdx-guest/ +obj-$(CONFIG_INTEL_TDX_HOST) +=3D tdx-host/ obj-$(CONFIG_ARM_CCA_GUEST) +=3D arm-cca-guest/ obj-$(CONFIG_TSM) +=3D tsm-core.o obj-$(CONFIG_TSM_GUEST) +=3D guest/ diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-hos= t/Kconfig new file mode 100644 index 000000000000..cfe81b9c0364 --- /dev/null +++ b/drivers/virt/coco/tdx-host/Kconfig @@ -0,0 +1,4 @@ +config TDX_HOST_SERVICES + tristate + depends on INTEL_TDX_HOST + default m diff --git a/drivers/virt/coco/tdx-host/Makefile b/drivers/virt/coco/tdx-ho= st/Makefile new file mode 100644 index 000000000000..e61e749a8dff --- /dev/null +++ b/drivers/virt/coco/tdx-host/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TDX_HOST_SERVICES) +=3D tdx-host.o diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c new file mode 100644 index 000000000000..c77885392b09 --- /dev/null +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TDX host user interface driver + * + * Copyright (C) 2025 Intel Corporation + */ + +#include +#include +#include + +#include +#include + +static const struct x86_cpu_id tdx_host_ids[] =3D { + X86_MATCH_FEATURE(X86_FEATURE_TDX_HOST_PLATFORM, NULL), + {} +}; +MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids); + +static struct faux_device *fdev; + +static int __init tdx_host_init(void) +{ + if (!x86_match_cpu(tdx_host_ids) || !tdx_get_sysinfo()) + return -ENODEV; + + fdev =3D faux_device_create(KBUILD_MODNAME, NULL, NULL); + if (!fdev) + return -ENODEV; + + return 0; +} +module_init(tdx_host_init); + +static void __exit tdx_host_exit(void) +{ + faux_device_destroy(fdev); +} +module_exit(tdx_host_exit); + +MODULE_DESCRIPTION("TDX Host Services"); +MODULE_LICENSE("GPL"); --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0106C3E314D; Wed, 20 May 2026 13:40:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284416; cv=none; b=CS4tW9pX47pwOZ87fXP9U8Xl2wQYwxVbWru3ZEHeQ4mHFZ/Jfx3EPvKXIRhSVYz1w0xvtj/CDgPesMdNEGpjzNVFdJ+KDU4mFYg4wO3rgKFQ0hPL1vG8TAQxwQGjfLuQIiBXPKbAhlKSqmrhzHd0hON8hKPt0HXg03XiIz12rJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284416; c=relaxed/simple; bh=dA16JSqyzi8Y3F9p4zAe6XahvJgF+2JG7ZGRrhvbrHE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z1IObv6AAe4y56O7d1mI/+6DfcS/ENdTPsFYjh9dBdBKSjfhOa9H12yMOQ0fziKugt6fZTldshbu+jE2zQidscHxEnvoh7FumJZA0W7OXtZqdb/oliMqy7+9fVxixEzdEHUHrUPMn59TwNh/IKMYQa0A8EUTQ6lWiBLcvVIqW3I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=kS4ZtGjN; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="kS4ZtGjN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284414; x=1810820414; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dA16JSqyzi8Y3F9p4zAe6XahvJgF+2JG7ZGRrhvbrHE=; b=kS4ZtGjNvj9bjilGtEYsdMLARbjlBec8TrkNobaUO0AcoGVk4e5Bwfji rkNhCesGxfWAjGjJipooaI35FDVTIIROZoB+sK71EQ+yDV4ck/eLoT5Ds 2GOoyM9Opmul1NzUpOff66J+Yso/+0PXv34B8NcKOG1gJX/agyyH1vynZ Cc3XYu3F8DerqsTmdynPbgBBbIE2qD4L87e6klHKBESaw3m5mSuYFaLs3 H1cbCYG846pauVRAksSulE3xpps8BLwriAbe8+TUC+5Qi74conoqXPCSL 1bRjY40GluSUqH1IGr4+SyA3x0ns7QlyM4uVnW9JE62WzxR2GzRyCRKDb w==; X-CSE-ConnectionGUID: 4O3nxEuqTcKWmuafFY+1eA== X-CSE-MsgGUID: 3UwKeuuAT6Kj+1RrWAlRZA== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146451" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146451" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:11 -0700 X-CSE-ConnectionGUID: /XedE3xVQIyHaBC5xRvxgQ== X-CSE-MsgGUID: opAeuO8DSNyF9CMI0mnf8w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923775" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:08 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 07/25] coco/tdx-host: Expose TDX module version Date: Wed, 20 May 2026 06:38:10 -0700 Message-ID: <20260520133909.409394-8-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For TDX module updates, userspace needs to select compatible update versions based on the current module version. This design delegates module selection complexity to userspace because compatibility must satisfy constraints from both the CPU and the running TDX module version. For example, the 1.5.x series runs on Sapphire Rapids but not Granite Rapids, which needs 2.0.x. Updates are also constrained by version distance, so a 1.5.6 module might permit updates to 1.5.7 but not to 1.5.20. Expose the TDX module version to userspace via sysfs to aid module selection. Since the TDX faux device will drive module updates, expose the version as its attribute. Define TDX_VERSION_FMT macro for the TDX version format since it will be used multiple times. Also convert an existing print statement to use it. =3D=3D Background =3D=3D The "faux device + device attribute" approach compares to other update mechanisms as follows: 1. AMD SEV leverages an existing PCI device for the PSP to expose metadata. TDX uses a faux device as it doesn't have PCI device in its architecture. 2. Microcode uses per-CPU virtual devices to report microcode revisions because CPUs can have different revisions. But, there is only a single TDX module, so exposing the TDX module version through a global TDX faux device is appropriate 3. ARM's CCA implementation isn't in-tree yet, but will likely follow a similar faux device approach, though it's unclear whether they need to expose firmware version information Signed-off-by: Chao Gao Reviewed-by: Binbin Wu Reviewed-by: Tony Lindgren Reviewed-by: Xu Yilun Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Xiaoyao Li Reviewed-by: Dave Hansen Link: https://lore.kernel.org/all/2025073035-bulginess-rematch-b92e@gregkh/= # [1] --- v10: - Improve clarity of the changelog and ABI documentation [Dave] --- .../ABI/testing/sysfs-devices-faux-tdx-host | 5 ++++ arch/x86/include/asm/tdx.h | 6 +++++ arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 2 +- drivers/virt/coco/tdx-host/tdx-host.c | 26 ++++++++++++++++++- 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-devices-faux-tdx-host diff --git a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host b/Docume= ntation/ABI/testing/sysfs-devices-faux-tdx-host new file mode 100644 index 000000000000..47d73cb89f1e --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host @@ -0,0 +1,5 @@ +What: /sys/devices/faux/tdx_host/version +Contact: linux-coco@lists.linux.dev +Description: (RO) Report the version of the loaded TDX module. + Formatted as "major.minor.update". Used by TDX module + update tooling. Example: "1.2.03". diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 8b739ac01479..b7f4396b5cc5 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -41,6 +41,12 @@ #include #include =20 +/* + * TDX module and P-SEAMLDR version convention: "major.minor.update" + * (e.g., "1.5.08") with zero-padded two-digit update field. + */ +#define TDX_VERSION_FMT "%u.%u.%02u" + /* * Used by the #VE exception handler to gather the #VE exception * info from the TDX module. This is a software only structure diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vm= x/tdx/tdx_global_metadata.c index c7db393a9cfb..d54d4227990c 100644 --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c @@ -106,7 +106,7 @@ static __init int get_tdx_sys_info(struct tdx_sys_info = *sysinfo) =20 ret =3D ret ?: get_tdx_sys_info_version(&sysinfo->version); =20 - pr_info("Module version: %u.%u.%02u\n", + pr_info("Module version: " TDX_VERSION_FMT "\n", sysinfo->version.major_version, sysinfo->version.minor_version, sysinfo->version.update_version); diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index c77885392b09..ef117a836b3a 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -8,6 +8,7 @@ #include #include #include +#include =20 #include #include @@ -18,6 +19,29 @@ static const struct x86_cpu_id tdx_host_ids[] =3D { }; MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids); =20 +static ssize_t version_show(struct device *dev, struct device_attribute *a= ttr, + char *buf) +{ + const struct tdx_sys_info *tdx_sysinfo =3D tdx_get_sysinfo(); + const struct tdx_sys_info_version *ver; + + if (!tdx_sysinfo) + return -ENXIO; + + ver =3D &tdx_sysinfo->version; + + return sysfs_emit(buf, TDX_VERSION_FMT "\n", ver->major_version, + ver->minor_version, + ver->update_version); +} +static DEVICE_ATTR_RO(version); + +static struct attribute *tdx_host_attrs[] =3D { + &dev_attr_version.attr, + NULL, +}; +ATTRIBUTE_GROUPS(tdx_host); + static struct faux_device *fdev; =20 static int __init tdx_host_init(void) @@ -25,7 +49,7 @@ static int __init tdx_host_init(void) if (!x86_match_cpu(tdx_host_ids) || !tdx_get_sysinfo()) return -ENODEV; =20 - fdev =3D faux_device_create(KBUILD_MODNAME, NULL, NULL); + fdev =3D faux_device_create_with_groups(KBUILD_MODNAME, NULL, NULL, tdx_h= ost_groups); if (!fdev) return -ENODEV; =20 --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E14943E3140; Wed, 20 May 2026 13:40:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284416; cv=none; b=Q3sR9FSBoHvebsJGJe8eyX7/H3JFyXu94WTVB6K7qCmUnN1nbEZn40rRNKwJ5ujfAX37pLVP1LFrLMiOlrmG7nAC1wXlaLF4vGvmxr3zSRI/8/Ri/Ed7M/DzB5+cZsJWE2hb6TqT5fCG40SEgKUkwvz6vTj7s12Vf6bEEa293Z8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284416; c=relaxed/simple; bh=CSyfguuVNxcphI8M8hXCKwfgO28jhSOmDsVMJc+ujrQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IAQymdoRWnskX+t9lZErp4esrjpRLNfvj2U0akQJIEjVzxsyjDhs68XivKGH/ZKmOiVB6ntUQShakDWdXBtyuuk6HsEGEcpjh/WVNOujPjlSxYA1k2D5Gk/Dka2KZRth8NXXQMEc0hs4m+b5JAVqPcMby28Cl7JKStO7mhg5Fjw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=UaZBbLRm; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UaZBbLRm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284414; x=1810820414; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=CSyfguuVNxcphI8M8hXCKwfgO28jhSOmDsVMJc+ujrQ=; b=UaZBbLRmRtYzOvxM6+6dzn6q8qb3pc/dWbTDMk9LG8buG8F0HmheD/a2 xl3U2FSwRthyCJs6IbidSqTZuHV6viHDj88DBL4vA0SQBuwfwe4QKERGP jQNJQTUhzQfj+Ls03fVeY9r6AWXOel1iWQFbbAF3LklR28JMp8idFPnV0 bJ2PbcDoLNYCA0z/MAPFYQ+YqEg2gsRlygPwe5I29TPgnB7JgtApIC+TS AzE4VLJT/v8RXEEhgqq13aSslKIFez+lbt2DlCdlVPXF1eIUFIkBZgyD5 BStwWa02FlnsTl3fes63Nml5yQmfEkNZ4b+SPJHD9Erm6U3ZnUa6i9i9d w==; X-CSE-ConnectionGUID: PQCyQVtEQwqdjizn8Pjobw== X-CSE-MsgGUID: ZniwiGIUQI+VFmEq3iHRug== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146459" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146459" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:11 -0700 X-CSE-ConnectionGUID: k+TxXo9eR0qm21GvNNIDtg== X-CSE-MsgGUID: k3bEo73ySUaqu9hA4lv5iA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923796" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:10 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt Subject: [PATCH v10 08/25] x86/virt/seamldr: Introduce a wrapper for P-SEAMLDR SEAMCALLs Date: Wed, 20 May 2026 06:38:11 -0700 Message-ID: <20260520133909.409394-9-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The TDX architecture uses the "SEAMCALL" instruction to communicate with SEAM mode software. Right now, the only SEAM mode software that the kernel communicates with is the TDX module. But, there is actually another component that runs in SEAM mode but it is separate from the TDX module: the persistent SEAM loader or "P-SEAMLDR". Right now, the only component that communicates with it is the BIOS which loads the TDX module itself at boot. But, to support updating the TDX module, the kernel now needs to be able to talk to it. P-SEAMLDR SEAMCALLs differ from TDX module SEAMCALLs in areas such as concurrency requirements. Add a P-SEAMLDR wrapper to handle these differences and prepare for implementing concrete functions. Use seamcall_prerr() (not '_ret') because current P-SEAMLDR calls do not use any output registers other than RAX. Note: Despite the similar name, the NP-SEAMLDR ("Non-Persistent") differs sharply from the P-SEAMLDR. It is an authenticated code module (ACM) invoked exclusively by the BIOS at boot rather than a component running in SEAM mode. The kernel cannot call it at runtime. It exposes no SEAMCALL interface. Signed-off-by: Chao Gao Reviewed-by: Binbin Wu Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Xiaoyao Li Reviewed-by: Rick Edgecombe Reviewed-by: Dave Hansen Link: https://cdrdv2.intel.com/v1/dl/getContent/733582 # [1] --- v10: - make "main act" solution statement in a prominent place [Dave] --- arch/x86/virt/vmx/tdx/Makefile | 2 +- arch/x86/virt/vmx/tdx/seamldr.c | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 arch/x86/virt/vmx/tdx/seamldr.c diff --git a/arch/x86/virt/vmx/tdx/Makefile b/arch/x86/virt/vmx/tdx/Makefile index 90da47eb85ee..d1dbc5cc5697 100644 --- a/arch/x86/virt/vmx/tdx/Makefile +++ b/arch/x86/virt/vmx/tdx/Makefile @@ -1,2 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y +=3D seamcall.o tdx.o +obj-y +=3D seamcall.o seamldr.o tdx.o diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c new file mode 100644 index 000000000000..65616dd2f4d2 --- /dev/null +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * P-SEAMLDR support for TDX module management features like runtime updat= es + * + * Copyright (C) 2025 Intel Corporation + */ +#define pr_fmt(fmt) "seamldr: " fmt + +#include + +#include "seamcall_internal.h" + +/* + * Serialize P-SEAMLDR calls since the hardware only allows a single CPU to + * interact with P-SEAMLDR simultaneously. Use raw version as the calls can + * be made with interrupts disabled, where plain spinlocks are prohibited = in + * PREEMPT_RT kernels as they become sleeping locks. + */ +static DEFINE_RAW_SPINLOCK(seamldr_lock); + +static __maybe_unused int seamldr_call(u64 fn, struct tdx_module_args *arg= s) +{ + guard(raw_spinlock)(&seamldr_lock); + return seamcall_prerr(fn, args); +} --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFEAD39B94C; Wed, 20 May 2026 13:40:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284420; cv=none; b=UAbhYIJVoz7n0IGu4/s2vxzQrsdn442ttqEtf/H9U5aIavIsCVgHmvwfLVVJh/PtTmF8okAvVj3EnEwvLHzPFEQLxMTBxIx1PadmV243O+DQBzrLLY66dctbx9c5n9ZwhnJbi3ut4OQHxFT0xE9Gic/6A3sW6MtQkaxOIcUsxlo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284420; c=relaxed/simple; bh=Otjxhkr5ExaAgS9xigLSzxVdyYwj4abmozFtPQYLOd0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jB6EUpL9ZgyD8kE8ipSdR//JEZWdDSK+AM5yIDpl45hJZRb90jDB0uOCjH0/nHeqLjTnURvFTX0grOoKRNkb8HAfo60s6iu+rtQ23SYilw2UhZqMLQ7Z1zVZRizrgVw4zAFRJTqavIfkjyVjA9kEHY7JPRNEL50QxeUkSK9x8Qg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=gdJaxJmc; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="gdJaxJmc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284418; x=1810820418; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Otjxhkr5ExaAgS9xigLSzxVdyYwj4abmozFtPQYLOd0=; b=gdJaxJmcPEhm2dIMbzOSLPmB6W4c07sfZTCrmheaMT6PhxRETvBwKHdk R9JNuh43cszpPM7iNHPvWc4dSQbcfJdV9BotLFf8D0+2FBvCJaBYJCGee NHS5V37VKz29BCOB25Jg0BvNHoP0UzcohRPfAZdXa+6G1Sieb/GQD2uV2 cyhmuWHrTbHZViCkxrIZHLDdH/c1fjrg3Jxp6l7P6CVCu2hkYRPvgCmgM y9w1UnNPfNnzNG85KAb7FVaKTF5rZSrqJyYn2ihqYkxIGU1qUN1+TXI1q 6xGiWiPYPhqDpjoCOWE6fAgYGWC2q2/QWaGn16CTyPPPaC8Z5HjkCGYuY w==; X-CSE-ConnectionGUID: dCQiXu0ESlGH5ONbIRu7Tw== X-CSE-MsgGUID: R+5jtgkVRqSjuj7XnVuYtg== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146471" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146471" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:12 -0700 X-CSE-ConnectionGUID: NXf43sx1RnW0ofeSR4hOOw== X-CSE-MsgGUID: URyZ0Z7bQ0WlxGaRpOzamQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923811" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:11 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 09/25] x86/virt/seamldr: Add a helper to retrieve P-SEAMLDR information Date: Wed, 20 May 2026 06:38:12 -0700 Message-ID: <20260520133909.409394-10-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable P-SEAMLDR reports its state via SEAMLDR.INFO, including its version and the number of remaining runtime updates. This information is useful for userspace. For example, the admin can use the P-SEAMLDR version to determine whether a candidate TDX module is compatible with the running loader, and can use the remaining update count to determine whether another runtime update is still possible. Add a helper to retrieve P-SEAMLDR information in preparation for exposing P-SEAMLDR version and other necessary information to userspace. Export the new kAPI for use by the "tdx_host" device. Note that there are two distinct P-SEAMLDR APIs with similar names: "SEAMLDR.INFO" is metadata about the loader. It's metadata for the update process. "SEAMLDR.SEAMINFO" is metadata about SEAM mode. It is for the module init process, not for the update process. Use SEAMLDR.INFO here. For details, see "Intel=C2=AE Trust Domain Extensions - SEAM Loader (SEAMLD= R) Interface Specification". Signed-off-by: Chao Gao Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Xiaoyao Li Reviewed-by: Rick Edgecombe Reviewed-by: Dave Hansen --- v10: - Shorten the comment above the SEAMLDR_INFO structure [Dave] - Use tdx_host consistently when referring to the device [Dave] - Shorten the changelog description about SEAMLDR.{INFO,SEAMINFO} [Dave] --- arch/x86/include/asm/seamldr.h | 35 +++++++++++++++++++++++++++++++++ arch/x86/virt/vmx/tdx/seamldr.c | 20 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 arch/x86/include/asm/seamldr.h diff --git a/arch/x86/include/asm/seamldr.h b/arch/x86/include/asm/seamldr.h new file mode 100644 index 000000000000..a74151b75599 --- /dev/null +++ b/arch/x86/include/asm/seamldr.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_SEAMLDR_H +#define _ASM_X86_SEAMLDR_H + +#include + +/* + * This is the "SEAMLDR_INFO" data structure defined in the + * "SEAM Loader (SEAMLDR) Interface Specification". + * + * Must be aligned to a 256-byte boundary. + */ +struct seamldr_info { + u32 version; + u32 attributes; + u32 vendor_id; + u32 build_date; + u16 build_num; + u16 minor_version; + u16 major_version; + u16 update_version; + u32 acm_x2apicid; + u32 num_remaining_updates; + u8 seam_info[128]; + u8 seam_ready; + u8 seam_debug; + u8 p_seam_ready; + u8 reserved[93]; +} __packed __aligned(256); + +static_assert(sizeof(struct seamldr_info) =3D=3D 256); + +int seamldr_get_info(struct seamldr_info *seamldr_info); + +#endif /* _ASM_X86_SEAMLDR_H */ diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index 65616dd2f4d2..7269a239bc22 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -8,8 +8,13 @@ =20 #include =20 +#include + #include "seamcall_internal.h" =20 +/* P-SEAMLDR SEAMCALL leaf function */ +#define P_SEAMLDR_INFO 0x8000000000000000 + /* * Serialize P-SEAMLDR calls since the hardware only allows a single CPU to * interact with P-SEAMLDR simultaneously. Use raw version as the calls can @@ -18,8 +23,21 @@ */ static DEFINE_RAW_SPINLOCK(seamldr_lock); =20 -static __maybe_unused int seamldr_call(u64 fn, struct tdx_module_args *arg= s) +static int seamldr_call(u64 fn, struct tdx_module_args *args) { guard(raw_spinlock)(&seamldr_lock); return seamcall_prerr(fn, args); } + +int seamldr_get_info(struct seamldr_info *seamldr_info) +{ + struct tdx_module_args args =3D {}; + + /* + * Use slow_virt_to_phys() since @seamldr_info may be allocated on + * the stack. + */ + args.rcx =3D slow_virt_to_phys(seamldr_info); + return seamldr_call(P_SEAMLDR_INFO, &args); +} +EXPORT_SYMBOL_FOR_MODULES(seamldr_get_info, "tdx-host"); --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4D512D877B; Wed, 20 May 2026 13:40:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284420; cv=none; b=J6jYZeVrzHbDwCszDfCAoWglhdrj7L2B74RpMNd5HtiFjXWPSPJMU4ovuLTYivRH4bNRawGJoUDYaTiZ9Cx6Wy/tOjD5+14LE5nu081o+MaAm9Bsshl4KJjyqGe/bKBIlPiM/ciXR8vWgDBmC0TGRPuwpU0mI9/Hcg//Xkkc10Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284420; c=relaxed/simple; bh=VF7FSnYcGZCTJLXLTw+t3jMigL1zziwUMIDb97mj+ZU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tbuITJB9IxB8x57RBNxm79coD9Dx8+a726uJ1qrSa9eB62I36Tzscezj9yUVnkIbLI3U+YKXs1l3/1i27gKPK2RfQ0Woezuz23rrZGnEJWXJwnDFf6hJP6EczzJCi+3lq5cCnM600w6ikg0mpEv2JFDsH3QiMykWYzlqr+7ZxKw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LQnZ2bbi; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LQnZ2bbi" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284417; x=1810820417; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=VF7FSnYcGZCTJLXLTw+t3jMigL1zziwUMIDb97mj+ZU=; b=LQnZ2bbiSYZR9tRV/T57+t/8pFdbBziPxw5j9FrXBbyZH8pWxdAvDJ4B s834JaclkOLrstiW+k1S6nySVyuAcXm7XPppkehIw4tYYcs0mUGLJAPQk b0n1uXfPUvB20O/i0+qiXcXpRChrAiHSammh5tK5Q/V6XoLHEqUdyfoNv VJHl2AM2dDH4hD/HjZyaU8kT3ltCVxOxoaZgFJrmriTLVeITti+2yJvul Qpzqz5uAMuNY+dAjinr2xeu2oa0ao8atzbAKf21dNZ3CD8a2JOai1mLsl k1iWnwtylV9DbhUGgIZQQp/t9u+Exx5FGocDEHZWoosEUGkeVboPX3bx9 Q==; X-CSE-ConnectionGUID: ke+oyjPxR7a7M73VpaJwGA== X-CSE-MsgGUID: NLx6ct8ETw+rXAdqr9739Q== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146481" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146481" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:14 -0700 X-CSE-ConnectionGUID: Mp4xl6IwRs23kQ8y4NoxsA== X-CSE-MsgGUID: CcMBLJYsSTqjuS41AQVd9w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923826" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:12 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 10/25] coco/tdx-host: Expose P-SEAMLDR information via sysfs Date: Wed, 20 May 2026 06:38:13 -0700 Message-ID: <20260520133909.409394-11-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable TDX module updates require userspace to select the appropriate module to load. Expose necessary information to facilitate this decision. Two values are needed: - P-SEAMLDR version: for compatibility checks between TDX module and P-SEAMLDR - num_remaining_updates: indicates how many updates can be performed Expose them as tdx-host device attributes. Make seamldr attributes visible only when the update feature is supported, as that's their sole purpose. Note that the underlying P-SEAMLDR attributes are available regardless of update support; this only restricts their visibility in Linux. Signed-off-by: Chao Gao Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Dave Hansen --- v10: - Describe the P-SEAMLDR version by referring to the TDX module version instead of copying the text [Dave] - add a comment for DEVICE_ATTR_ADMIN_RO() [Dave] - Avoid the tertiary operator [Dave] --- .../ABI/testing/sysfs-devices-faux-tdx-host | 21 ++++++ arch/x86/include/asm/tdx.h | 6 ++ drivers/virt/coco/tdx-host/tdx-host.c | 72 ++++++++++++++++++- 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host b/Docume= ntation/ABI/testing/sysfs-devices-faux-tdx-host index 47d73cb89f1e..69b4cfc99d87 100644 --- a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host +++ b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host @@ -3,3 +3,24 @@ Contact: linux-coco@lists.linux.dev Description: (RO) Report the version of the loaded TDX module. Formatted as "major.minor.update". Used by TDX module update tooling. Example: "1.2.03". + +What: /sys/devices/faux/tdx_host/seamldr_version +Contact: linux-coco@lists.linux.dev +Description: (RO) Report the version of the loaded P-SEAMLDR. + Formatted as a TDX module version. Used by TDX module + update tooling. + +What: /sys/devices/faux/tdx_host/num_remaining_updates +Contact: linux-coco@lists.linux.dev +Description: (RO) Report the number of remaining updates. TDX maintains a + log about each TDX module that has been loaded. This log has + a finite size, which limits the number of TDX module updates + that can be performed. + + After each successful update, the number reduces by one. Once it + reaches zero, further updates will fail until next reboot. The + number is always zero if the P-SEAMLDR doesn't support updates. + + See Intel=C2=AE Trust Domain Extensions - SEAM Loader (SEAMLDR) + Interface Specification, Chapter "SEAMLDR_INFO" and Chapter + "SEAMLDR.INSTALL" for more information. diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index b7f4396b5cc5..27376db7ddac 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -110,6 +110,12 @@ void tdx_init(void); const char *tdx_dump_mce_info(struct mce *m); const struct tdx_sys_info *tdx_get_sysinfo(void); =20 +static inline bool tdx_supports_runtime_update(const struct tdx_sys_info *= sysinfo) +{ + /* To be enabled when kernel is ready. */ + return false; +} + int tdx_guest_keyid_alloc(void); u32 tdx_get_nr_guest_keyids(void); void tdx_guest_keyid_free(unsigned int keyid); diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index ef117a836b3a..2997311f72fa 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -11,6 +11,7 @@ #include =20 #include +#include #include =20 static const struct x86_cpu_id tdx_host_ids[] =3D { @@ -40,7 +41,76 @@ static struct attribute *tdx_host_attrs[] =3D { &dev_attr_version.attr, NULL, }; -ATTRIBUTE_GROUPS(tdx_host); + +static const struct attribute_group tdx_host_group =3D { + .attrs =3D tdx_host_attrs, +}; + +static ssize_t seamldr_version_show(struct device *dev, struct device_attr= ibute *attr, + char *buf) +{ + struct seamldr_info info; + int ret; + + ret =3D seamldr_get_info(&info); + if (ret) + return ret; + + return sysfs_emit(buf, TDX_VERSION_FMT "\n", info.major_version, + info.minor_version, + info.update_version); +} + +static ssize_t num_remaining_updates_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct seamldr_info info; + int ret; + + ret =3D seamldr_get_info(&info); + if (ret) + return ret; + + return sysfs_emit(buf, "%u\n", info.num_remaining_updates); +} + +/* + * These attributes are intended for managing TDX module updates. Reading + * them issues a slow, serialized P-SEAMLDR query, so keep them admin-only. + */ +static DEVICE_ATTR_ADMIN_RO(seamldr_version); +static DEVICE_ATTR_ADMIN_RO(num_remaining_updates); + +static struct attribute *seamldr_attrs[] =3D { + &dev_attr_seamldr_version.attr, + &dev_attr_num_remaining_updates.attr, + NULL, +}; + +static umode_t seamldr_group_visible(struct kobject *kobj, struct attribut= e *attr, int idx) +{ + const struct tdx_sys_info *sysinfo =3D tdx_get_sysinfo(); + + if (!sysinfo) + return 0; + + if (!tdx_supports_runtime_update(sysinfo)) + return 0; + + return attr->mode; +} + +static const struct attribute_group seamldr_group =3D { + .attrs =3D seamldr_attrs, + .is_visible =3D seamldr_group_visible, +}; + +static const struct attribute_group *tdx_host_groups[] =3D { + &tdx_host_group, + &seamldr_group, + NULL, +}; =20 static struct faux_device *fdev; =20 --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C17243E5EF9; Wed, 20 May 2026 13:40:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284421; cv=none; b=BoX9RXhWgG+cLa6WFx993vENHe6vbNDskGHC3VteAkpqC66fZUSgdbwASYpUIsuhy6oZhVemIerqEYqLSQkRgYFwya69Rng6ro4l7VUcMb2lxcJYfUfCu9q6vuX37Kg7cA8fi2Y5Sb+qba3kXMaPj1LMigbVek5GMRtrpkWv/GI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284421; c=relaxed/simple; bh=AlehDs/IqpKIcQ5FsfjPn2/Cs/DHt7hYJskpq+M548c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P0LfPoPFCmLzn1pKlS4Tvl9gSiTblw5phIl1knOtPazeGGkD3oGlvegawYss49KjCn6+5CaQS7pwLjcx8j5OJsvIUJN0icsL1yd6/f41vwQ4YViYOW8k5zcUA//+xupniRRt8nq5jBLezUWpfmVfg36UGUl5fYSr9rjucmv6feY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LgmSTf5X; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LgmSTf5X" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284418; x=1810820418; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AlehDs/IqpKIcQ5FsfjPn2/Cs/DHt7hYJskpq+M548c=; b=LgmSTf5XOPmligJcR9FmNwfszeGYlC1DB9jb0A+Vx/Kj34yyI17YDhoz rB1ODbmsHJBLJKbrAITbWrNHIl5e08MkKbqmwWKPxcECVtfWN4rBEcgoP MOfDVgRXf9hqL3aCMXoydsw2aoi6UHJ9nMUAQltVK8z4rkm3+VKBSnGp9 UlNkPq/Or/umtn2pdx3lt6P1rIN3VnO1rBFOtTapojoiMA58Ao09PHjwm Xaku79H7MMzOkonlZBUhypoB1Tq7ZPhWOpnbZF/gvswVIWBQQ3fd7o5DJ bLBmHoH3faZHlKDc9XJXqDkXJiMEN+7RD6ULEWZ0njDVD413U+4E/RfQz Q==; X-CSE-ConnectionGUID: 7RmRDnx9TpWXY3i1GRmwng== X-CSE-MsgGUID: Lm99F4OdSuiI2G60/vnLSw== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146493" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146493" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:15 -0700 X-CSE-ConnectionGUID: JwgCiX6ZSsWPYH4PXaafsQ== X-CSE-MsgGUID: DMYUw12pT3m4kEo8EfC7YA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923846" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:14 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 11/25] coco/tdx-host: Don't expose P-SEAMLDR information on CPUs with erratum Date: Wed, 20 May 2026 06:38:14 -0700 Message-ID: <20260520133909.409394-12-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable TDX-capable CPUs clobber the current VMCS on return from P-SEAMLDR, as documented in Intel=C2=AE Trust Domain CPU Architectural Extensions: SEAMRET from the P-SEAMLDR clears the current VMCS structure pointed to by the current-VMCS pointer. A VMM that invokes the P-SEAMLDR using SEAMCALL must reload the current-VMCS, if required, using the VMPTRLD instruction. Clearing the current VMCS behind KVM's back will break KVM. Future CPUs will fix this by preserving the current VMCS across P-SEAMLDR calls. A future specification update will describe the SEAMRET VMCS-clearing behavior as an erratum and to state that it does not occur when IA32_VMX_BASIC[60] is set. Add a CPU bug bit for this erratum and refuse to expose P-SEAMLDR information on affected CPUs, because even reading the P-SEAMLDR sysfs knobs would enter and exit P-SEAMLDR. Use a CPU bug bit to stay consistent with X86_BUG_TDX_PW_MCE. As a bonus, the bug bit is visible to userspace, which allows userspace to determine why these sysfs files are not exposed, and it can also be checked by other kernel components in the future if needed. =3D=3D Alternatives =3D=3D Two workarounds were considered but both were rejected: 1. Save/restore the current VMCS around P-SEAMLDR calls. This produces ugly assembly code [1] and doesn't play well with #MCE or #NMI if they need to use the current VMCS. 2. Move KVM's VMCS tracking logic to the TDX core code, which would break the boundary between KVM and the TDX core code [2]. Signed-off-by: Chao Gao Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Rick Edgecombe Reviewed-by: Dave Hansen Link: https://lore.kernel.org/kvm/fedb3192-e68c-423c-93b2-a4dc2f964148@inte= l.com/ # [1] Link: https://lore.kernel.org/kvm/aYIXFmT-676oN6j0@google.com/ # [2] --- This is split into a separate patch rather than folded into the previous on= e, because the erratum handling warrants a longer changelog and discussion of the alternatives. v10: - Make it clear that clearing VMCS is the current architecture behavior. but will be fixed by a later doc update. --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/vmx.h | 1 + arch/x86/virt/vmx/tdx/tdx.c | 11 +++++++++++ drivers/virt/coco/tdx-host/tdx-host.c | 8 ++++++++ 4 files changed, 21 insertions(+) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpuf= eatures.h index 1d506e5d6f46..7b572bc24265 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -573,4 +573,5 @@ #define X86_BUG_ITS_NATIVE_ONLY X86_BUG( 1*32+ 8) /* "its_native_only" CP= U is affected by ITS, VMX is not affected */ #define X86_BUG_TSA X86_BUG( 1*32+ 9) /* "tsa" CPU is affected by Transi= ent Scheduler Attacks */ #define X86_BUG_VMSCAPE X86_BUG( 1*32+10) /* "vmscape" CPU is affected b= y VMSCAPE attacks from guests */ +#define X86_BUG_SEAMRET_INVD_VMCS X86_BUG( 1*32+11) /* "seamret_invd_vmcs"= SEAMRET from P-SEAMLDR clears the current VMCS */ #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 37080382df54..49d8551d285d 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -147,6 +147,7 @@ struct vmcs { #define VMX_BASIC_INOUT BIT_ULL(54) #define VMX_BASIC_TRUE_CTLS BIT_ULL(55) #define VMX_BASIC_NO_HW_ERROR_CODE_CC BIT_ULL(56) +#define VMX_BASIC_NO_SEAMRET_INVD_VMCS BIT_ULL(60) =20 static inline u32 vmx_basic_vmcs_revision_id(u64 vmx_basic) { diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 5fb0441a9ac6..53cf99c41dbb 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -42,6 +42,7 @@ #include #include #include +#include =20 #include "seamcall_internal.h" #include "tdx.h" @@ -1450,6 +1451,8 @@ static struct notifier_block tdx_memory_nb =3D { =20 static void __init check_tdx_erratum(void) { + u64 basic_msr; + /* * These CPUs have an erratum. A partial write from non-TD * software (e.g. via MOVNTI variants or UC/WC mapping) to TDX @@ -1461,6 +1464,14 @@ static void __init check_tdx_erratum(void) case INTEL_EMERALDRAPIDS_X: setup_force_cpu_bug(X86_BUG_TDX_PW_MCE); } + + /* + * Some TDX-capable CPUs have an erratum where the current VMCS is + * cleared after calling into P-SEAMLDR. + */ + rdmsrq(MSR_IA32_VMX_BASIC, basic_msr); + if (!(basic_msr & VMX_BASIC_NO_SEAMRET_INVD_VMCS)) + setup_force_cpu_bug(X86_BUG_SEAMRET_INVD_VMCS); } =20 void __init tdx_init(void) diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index 2997311f72fa..2cd7be7bb404 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -98,6 +98,14 @@ static umode_t seamldr_group_visible(struct kobject *kob= j, struct attribute *att if (!tdx_supports_runtime_update(sysinfo)) return 0; =20 + /* + * Calling P-SEAMLDR on CPUs with the seamret_invd_vmcs bug clears + * the current VMCS, which breaks KVM. Verify the erratum is not + * present before exposing P-SEAMLDR features. + */ + if (boot_cpu_has_bug(X86_BUG_SEAMRET_INVD_VMCS)) + return 0; + return attr->mode; } =20 --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27AEE2D94B5; Wed, 20 May 2026 13:40:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284424; cv=none; b=WYYxkFDOYpC8CG1KiwWjgrpumUU8yprJvPGbWzrUG5Z1YilxfDD/HBwlkv3/wP8G4UtXyw5nTXPJyk7jg2RPSxGzqr6gpAdOqGW2b2E6P4GZrNBH/K/Gce0hA4/O4HBwz2RHbF7hvgY74UmJvFgnAZ6+GNxcNDfCbcObuxsJH7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284424; c=relaxed/simple; bh=xFq7z+yD2KnqYhp+RfH6uPtT6cIpAo/nQxQdNfO6F/k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GUpY/rJRV4uRMPWDJPrOcq0pJH1JMDToaEsYYUpGegSdIZZlaa8WUHKfh2i8f3+zifKPeLOHkF1PTHHeF6fVe+ZxWhHM4uT5BP76BcuqAzbTIm1iZTLrnKT8zmSuDCI2YHJVK6DPpT6DCs40qfPLOC80X32C8x59+FWxc5wm4ec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=eGbtvzW4; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="eGbtvzW4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284422; x=1810820422; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xFq7z+yD2KnqYhp+RfH6uPtT6cIpAo/nQxQdNfO6F/k=; b=eGbtvzW4OK2AjITcY4yHXHX/QVkM6gi7j4IzQlT09Qdmu4v8DAo6kdbT upZIn+ymIMByg9XsjS+AZBpoI0lSjxdYFLhIib/1FpYKOin+dB+p7LzJ7 tQQyFRqtfPWcqpr/CHsJMIPlrxFEqPr0R1Foy6HxILvBrec/KJgTpwWL1 0df/GDfTK8FK/EDs6XbmKHZtxztMlCxkNJneMNJl0SQ/cHyj55HYmp5jj sl/78JWwny68YFBfn/ZIZsevOp7sfhUHTmyXbsKCSqfhD+Fgx9kzOPMZn bbJWUv7eReooJuSxQVAOEGv/ryQ4Tjz8IbVUPKSOQHQ4WNgDIzekte1Ft w==; X-CSE-ConnectionGUID: moYAMCbsTmuBgjrUZ2gXuw== X-CSE-MsgGUID: vvUDv8ylQ+a6H9EH0fFXZg== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146502" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146502" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:17 -0700 X-CSE-ConnectionGUID: EkeuaMvTRnO8AAgKEktmhA== X-CSE-MsgGUID: 9sCDtDfARBulxk0X8X6kGA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923863" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:16 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 12/25] coco/tdx-host: Implement firmware upload sysfs ABI for TDX module updates Date: Wed, 20 May 2026 06:38:15 -0700 Message-ID: <20260520133909.409394-13-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" tl;dr: Select fw_upload for doing TDX module updates. The process of selecting among available update images is complicated and nuanced. Punt the selection process out to userspace. One existing userspace implementation today is the script in the Intel TDX Module Binaries repository. Long Version: The kernel supports two primary firmware update mechanisms: 1. request_firmware() - used by microcode, SEV firmware, hundreds of other drivers 2. 'struct fw_upload' - used by CXL, FPGA updates, dozens of others The key difference between is that request_firmware() loads a named file from the filesystem where the filename is kernel-controlled, while fw_upload accepts firmware data directly from userspace. TDX module firmware update selection policy is too complex for the kernel. Leave it to userspace and use fw_upload. Why fw_upload instead of request_firmware()? =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Selecting a TDX module update image is not a simple "load the latest" decision. Userspace needs to choose an image that is compatible with both the platform and the currently running module. Some constraints are hard requirements: a. Module version series are platform-specific. For example, the 1.5.x series runs on Sapphire Rapids but not Granite Rapids, which needs 2.0.x. b. Updates are also constrained by version distance. A 1.5.6 module might permit updates to 1.5.7 but not to 1.5.50. There may also be userspace policy choices: c. Decide the update direction: upgrade or downgrade d. Choose whether to optimize for fewer updates or smaller version steps, for example, 1.2.3=3D>1.2.5 versus 1.2.3=3D>1.2.4=3D>1.2.5. Given that complexity, leave module selection to userspace and use fw_upload. Signed-off-by: Chao Gao Reviewed-by: Tony Lindgren Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Link: https://lore.kernel.org/kvm/01fc8946-eb84-46fa-9458-f345dd3f6033@inte= l.com/ --- Future patches add more cases to the switch in tdx_fw_write(). With only two cases, the switch looks a bit awkward right now. v10: - Polish the changelog [Dave] - Point to one existing userspace implementation [Dave] - Separate hard compatibility requirements from userspace policy choices - Use true/false rather than 0/1 for bool return values. - s/size/data_len --- arch/x86/include/asm/seamldr.h | 1 + arch/x86/virt/vmx/tdx/seamldr.c | 14 ++++ drivers/virt/coco/tdx-host/Kconfig | 2 + drivers/virt/coco/tdx-host/tdx-host.c | 92 +++++++++++++++++++++++++-- 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/seamldr.h b/arch/x86/include/asm/seamldr.h index a74151b75599..43084e2daa2d 100644 --- a/arch/x86/include/asm/seamldr.h +++ b/arch/x86/include/asm/seamldr.h @@ -31,5 +31,6 @@ struct seamldr_info { static_assert(sizeof(struct seamldr_info) =3D=3D 256); =20 int seamldr_get_info(struct seamldr_info *seamldr_info); +int seamldr_install_module(const u8 *data, u32 data_len); =20 #endif /* _ASM_X86_SEAMLDR_H */ diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index 7269a239bc22..d3880b0f93aa 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -41,3 +41,17 @@ int seamldr_get_info(struct seamldr_info *seamldr_info) return seamldr_call(P_SEAMLDR_INFO, &args); } EXPORT_SYMBOL_FOR_MODULES(seamldr_get_info, "tdx-host"); + +/** + * seamldr_install_module - Install a new TDX module. + * @data: Pointer to the TDX module image. + * @data_len: Size of the TDX module image. + * + * Returns 0 on success, negative error code on failure. + */ +int seamldr_install_module(const u8 *data, u32 data_len) +{ + /* TODO: Update TDX module here */ + return 0; +} +EXPORT_SYMBOL_FOR_MODULES(seamldr_install_module, "tdx-host"); diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-hos= t/Kconfig index cfe81b9c0364..57d0c01a4357 100644 --- a/drivers/virt/coco/tdx-host/Kconfig +++ b/drivers/virt/coco/tdx-host/Kconfig @@ -1,4 +1,6 @@ config TDX_HOST_SERVICES tristate depends on INTEL_TDX_HOST + select FW_LOADER + select FW_UPLOAD default m diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index 2cd7be7bb404..b32ab595047f 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -6,6 +6,7 @@ */ =20 #include +#include #include #include #include @@ -88,15 +89,15 @@ static struct attribute *seamldr_attrs[] =3D { NULL, }; =20 -static umode_t seamldr_group_visible(struct kobject *kobj, struct attribut= e *attr, int idx) +static bool supports_runtime_update(void) { const struct tdx_sys_info *sysinfo =3D tdx_get_sysinfo(); =20 if (!sysinfo) - return 0; + return false; =20 if (!tdx_supports_runtime_update(sysinfo)) - return 0; + return false; =20 /* * Calling P-SEAMLDR on CPUs with the seamret_invd_vmcs bug clears @@ -104,6 +105,14 @@ static umode_t seamldr_group_visible(struct kobject *k= obj, struct attribute *att * present before exposing P-SEAMLDR features. */ if (boot_cpu_has_bug(X86_BUG_SEAMRET_INVD_VMCS)) + return false; + + return true; +} + +static umode_t seamldr_group_visible(struct kobject *kobj, struct attribut= e *attr, int idx) +{ + if (!supports_runtime_update()) return 0; =20 return attr->mode; @@ -120,6 +129,81 @@ static const struct attribute_group *tdx_host_groups[]= =3D { NULL, }; =20 +static enum fw_upload_err tdx_fw_prepare(struct fw_upload *fwl, + const u8 *data, u32 data_len) +{ + return FW_UPLOAD_ERR_NONE; +} + +static enum fw_upload_err tdx_fw_write(struct fw_upload *fwl, const u8 *da= ta, + u32 offset, u32 data_len, u32 *written) +{ + int ret; + + ret =3D seamldr_install_module(data, data_len); + switch (ret) { + case 0: + *written =3D data_len; + return FW_UPLOAD_ERR_NONE; + default: + return FW_UPLOAD_ERR_FW_INVALID; + } +} + +static enum fw_upload_err tdx_fw_poll_complete(struct fw_upload *fwl) +{ + /* + * The upload completed during tdx_fw_write(). + * Never poll for completion. + */ + return FW_UPLOAD_ERR_NONE; +} + + +static void tdx_fw_cancel(struct fw_upload *fwl) +{ + /* + * TDX module updates are not cancellable. + * Provide a no-op callback to satisfy fw_upload_ops. + */ +} + +static const struct fw_upload_ops tdx_fw_ops =3D { + .prepare =3D tdx_fw_prepare, + .write =3D tdx_fw_write, + .poll_complete =3D tdx_fw_poll_complete, + .cancel =3D tdx_fw_cancel, +}; + +static void seamldr_deinit(void *tdx_fwl) +{ + firmware_upload_unregister(tdx_fwl); +} + +static int seamldr_init(struct device *dev) +{ + struct fw_upload *tdx_fwl; + + if (!supports_runtime_update()) + return 0; + + tdx_fwl =3D firmware_upload_register(THIS_MODULE, dev, "tdx_module", + &tdx_fw_ops, NULL); + if (IS_ERR(tdx_fwl)) + return PTR_ERR(tdx_fwl); + + return devm_add_action_or_reset(dev, seamldr_deinit, tdx_fwl); +} + +static int tdx_host_probe(struct faux_device *fdev) +{ + return seamldr_init(&fdev->dev); +} + +static const struct faux_device_ops tdx_host_ops =3D { + .probe =3D tdx_host_probe, +}; + static struct faux_device *fdev; =20 static int __init tdx_host_init(void) @@ -127,7 +211,7 @@ static int __init tdx_host_init(void) if (!x86_match_cpu(tdx_host_ids) || !tdx_get_sysinfo()) return -ENODEV; =20 - fdev =3D faux_device_create_with_groups(KBUILD_MODNAME, NULL, NULL, tdx_h= ost_groups); + fdev =3D faux_device_create_with_groups(KBUILD_MODNAME, NULL, &tdx_host_o= ps, tdx_host_groups); if (!fdev) return -ENODEV; =20 --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2907F3E5ED7; Wed, 20 May 2026 13:40:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284424; cv=none; b=IY5FQcUT24soeos+/l+WOMECYUYGOMQEevsS5JCiZxH3fpYGO9dY1ezk2Pq+P+mFhcZNSdqGweK1PPYZb80qfc707EL6jnpgwYRdpRGR0Sj2uKhsGNiC3B9H6Zc5RZqaobf/iR0QZt4CxulcjpL8thGj4qZRA2jmw9IwOlVMKTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284424; c=relaxed/simple; bh=2uRkB7s6oabhaBTOUeY7fNLUBuDLjjsV/PBO02yCpxQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XmUQ6JsD9hCqDDYYa2O2IPHYy0XO56XvOvi4z1InsqdEZf20wEnjDah7DCx/royFpzh2OvgAjO11CT67KJVRDL+MGgm0dmHbcBJwaN+rUKZ2chrlRBqtncTOEnBAxOAtxC9oGuzQ2jjcTlCrtcgFiKe4EGXHuU4eQWu24aza6QQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=GFD8vxBX; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="GFD8vxBX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284422; x=1810820422; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2uRkB7s6oabhaBTOUeY7fNLUBuDLjjsV/PBO02yCpxQ=; b=GFD8vxBXabHQnqkemPGzYjUSillZf0xWL/XMCADJ/rYJWJp5JIVoFjZI ub1b8MRn6ye+G9ZiG59KJ/adKQ6Gu5fVTaekWC3TWG3o6C1HkolB2QARp 3S2R52gS15kgHWuDWoWkJGgjb/sTgEqrEzpXX6HCb6YzFkGLqaLYOI073 o6CY+/NH9YUVYGoWwA8LjwbBtIkgkoH3nFG/9hemr22r2nFZ5OgSKSIqX 9eEI2vIUrOrSkalNCoZgXF27HaGUc6BTX/9F2m66dn4uNk6PYB9j60yPD KMp/vWVy1JO22xhnR1dfz2kTlgZFHl5OJ9y/uJG0ydQQ6LGSiZRWKUB2n Q==; X-CSE-ConnectionGUID: PmW/byrWSH6P+1mvl6/mDw== X-CSE-MsgGUID: YxraRti8TMiEw1U7ww8weQ== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146514" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146514" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:18 -0700 X-CSE-ConnectionGUID: K6R2RWyXSASJL9BuzPd1cg== X-CSE-MsgGUID: BdGEX0EESlWAunUzgeQMHA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923873" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:17 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 13/25] x86/virt/seamldr: Allocate and populate a module update request Date: Wed, 20 May 2026 06:38:16 -0700 Message-ID: <20260520133909.409394-14-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" There are two important ABIs here: 'struct tdx_image' - The on-disk and in-memory format for a TDX module update image. 'struct seamldr_params' - The in-memory ABI passed to the TDX module loader. Points to a single 'struct tdx_image' broken up into 4k pages. Userspace supplies the update image in struct tdx_image format. The image consists of a header followed by a sigstruct and the module binary. P-SEAMLDR, however, consumes struct seamldr_params rather than the image directly. Parse the struct tdx_image provided by userspace and populate a matching struct seamldr_params. The 'tdx_image' ABI is versioned. Two public versions exist today: 0x100 and 0x200. This kernel only accepts 0x200. The older 0x100 format is being deprecated and is intentionally not supported here. Future versions of the module might be able to use the same ABIs (user/kernel and kernel/SEAMLDR) but they will not be able to use this kernel code. Reject module images without that specific version. This ensures that the kernel is able to understand the passed-in format. Validate the struct tdx_image header before using it, because the header is consumed solely by the kernel to locate the sigstruct and module within the image. Do not validate the payload itself. The sigstruct and module pages are passed through to P-SEAMLDR, which validates them as part of the update flow. sigstruct_pages_pa_list currently has only one entry, but it will grow to four pages in the future. Keep it as an array for symmetry with module_pages_pa_list and for extensibility. Signed-off-by: Chao Gao --- v10: - Add comments for init_seamldr_params() and its call site [Dave] - Use data_len/image_len rather than size [Dave] - Do bounds check rather than implicitly truncat the update image [Dave] - Explain why the header version is checked in changelog [Dave] - make init_seamldr_params() accept a tdx_image pointer [Dave] - vertical alignment for code has a pattern [Dave] --- arch/x86/virt/vmx/tdx/seamldr.c | 145 +++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index d3880b0f93aa..11bd28e8370c 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -6,6 +6,8 @@ */ #define pr_fmt(fmt) "seamldr: " fmt =20 +#include +#include #include =20 #include @@ -15,6 +17,35 @@ /* P-SEAMLDR SEAMCALL leaf function */ #define P_SEAMLDR_INFO 0x8000000000000000 =20 +#define SEAMLDR_MAX_NR_MODULE_PAGES 496 +#define SEAMLDR_MAX_NR_SIG_PAGES 1 + +/* + * The seamldr_params "scenario" field specifies the operation mode: + * 0: Install TDX module from scratch (not used by kernel) + * 1: Update existing TDX module to a compatible version + */ +#define SEAMLDR_SCENARIO_UPDATE 1 + +/* + * This is the "SEAMLDR_PARAMS" data structure defined in the + * "SEAM Loader (SEAMLDR) Interface Specification". + * + * It is the in-memory ABI that the kernel passes to the P-SEAMLDR + * to update the TDX module. It breaks the TDX module image up in + * page-size pieces. + */ +struct seamldr_params { + u32 version; + u32 scenario; + u64 sigstruct_pages_pa_list[SEAMLDR_MAX_NR_SIG_PAGES]; + u8 reserved[104]; + u64 module_nr_pages; + u64 module_pages_pa_list[SEAMLDR_MAX_NR_MODULE_PAGES]; +} __packed; + +static_assert(sizeof(struct seamldr_params) =3D=3D 4096); + /* * Serialize P-SEAMLDR calls since the hardware only allows a single CPU to * interact with P-SEAMLDR simultaneously. Use raw version as the calls can @@ -42,6 +73,98 @@ int seamldr_get_info(struct seamldr_info *seamldr_info) } EXPORT_SYMBOL_FOR_MODULES(seamldr_get_info, "tdx-host"); =20 +#define TDX_IMAGE_VERSION_2 0x200 + +struct tdx_image_header { + u16 version; + u16 checksum; + u8 signature[8]; + u32 sigstruct_nr_pages; + u32 module_nr_pages; + u8 reserved[4076]; +} __packed; + +#define TDX_IMAGE_HEADER_SIZE sizeof(struct tdx_image_header) +static_assert(TDX_IMAGE_HEADER_SIZE =3D=3D 4096); + +/* + * Intel TDX module update ABI structure. aka. "TDX module blob". + * + * @payload contains sigstruct pages followed by module pages. + */ +struct tdx_image { + struct tdx_image_header header; + u8 payload[]; +}; + +static void populate_pa_list(u64 *pa_list, const u8 *vmalloc_addr, u32 vma= lloc_len_pages) +{ + int i; + + for (i =3D 0; i < vmalloc_len_pages; i++) { + unsigned long offset =3D i * PAGE_SIZE; + unsigned long pfn =3D vmalloc_to_pfn(&vmalloc_addr[offset]); + + pa_list[i] =3D pfn << PAGE_SHIFT; + } +} + +static void populate_seamldr_params(struct seamldr_params *params, + const u8 *sig, u32 sig_nr_pages, + const u8 *mod, u32 mod_nr_pages) +{ + params->version =3D 0; + params->scenario =3D SEAMLDR_SCENARIO_UPDATE; + params->module_nr_pages =3D mod_nr_pages; + + populate_pa_list(params->sigstruct_pages_pa_list, sig, sig_nr_pages); + populate_pa_list(params->module_pages_pa_list, mod, mod_nr_pages); +} + +/* + * @image points to a vmalloc()'d 'struct tdx_image'. Transform + * it into @params which is the P-SEAMLDR ABI format. + */ +static int init_seamldr_params(struct seamldr_params *params, + const struct tdx_image *image, + u32 image_len) +{ + const struct tdx_image_header *header =3D &image->header; + + u32 sigstruct_len =3D header->sigstruct_nr_pages * PAGE_SIZE; + u32 module_len =3D header->module_nr_pages * PAGE_SIZE; + + u8 *header_start =3D (u8 *)header; + u8 *header_end =3D header_start + TDX_IMAGE_HEADER_SIZE; + + u8 *sigstruct_start =3D header_end; + u8 *sigstruct_end =3D sigstruct_start + sigstruct_len; + + u8 *module_start =3D sigstruct_end; + + /* Check the calculated payload size against the image size. */ + if (TDX_IMAGE_HEADER_SIZE + sigstruct_len + module_len !=3D image_len) + return -EINVAL; + + /* Reject unsupported tdx_image ABI versions. */ + if (header->version !=3D TDX_IMAGE_VERSION_2) + return -EINVAL; + + if (header->sigstruct_nr_pages > SEAMLDR_MAX_NR_SIG_PAGES || + header->module_nr_pages > SEAMLDR_MAX_NR_MODULE_PAGES) + return -EINVAL; + + if (memcmp(header->signature, "TDX-BLOB", sizeof(header->signature))) + return -EINVAL; + + if (memchr_inv(header->reserved, 0, sizeof(header->reserved))) + return -EINVAL; + + populate_seamldr_params(params, sigstruct_start, header->sigstruct_nr_pag= es, + module_start, header->module_nr_pages); + return 0; +} + /** * seamldr_install_module - Install a new TDX module. * @data: Pointer to the TDX module image. @@ -51,7 +174,27 @@ EXPORT_SYMBOL_FOR_MODULES(seamldr_get_info, "tdx-host"); */ int seamldr_install_module(const u8 *data, u32 data_len) { + struct seamldr_params *params; + const struct tdx_image *image; + int ret; + + if (data_len < TDX_IMAGE_HEADER_SIZE) + return -EINVAL; + + image =3D (const struct tdx_image *)data; + + params =3D kzalloc_obj(*params); + if (!params) + return -ENOMEM; + + /* Populate 'params' from 'image'. */ + ret =3D init_seamldr_params(params, image, data_len); + if (ret) + goto out; + /* TODO: Update TDX module here */ - return 0; +out: + kfree(params); + return ret; } EXPORT_SYMBOL_FOR_MODULES(seamldr_install_module, "tdx-host"); --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E95673E835E; Wed, 20 May 2026 13:40:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284428; cv=none; b=JdGERMBQ1i476M974HW4bphKb4jjQVM9hVEMVTORrzc10vwpwnJuBKLEuRgBvnhUbGfp1LOM5T5kkYcne3mR991M4GC0Z8b8o/jExxMlumSA7LDSci6ARVsVtGL5PqFzUcryt7jNEGg/8zcXnZtzz4UuoHMPkkTWEOeUIjVxzg8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284428; c=relaxed/simple; bh=tVsArRA2sGbQoUu1urPqUjzAv7PIClDuiJsEtM6+h+c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NzhgxFTpPOxBrQaEt0TmhKcrt+yBAfocMWX/rw34EEeNVNIhtOTNOP/aJ/z6XOb66UBZfgJYYudO6UBUh885cW+xcTDVnggTp2OZp1+TkxXuXLClbcUedk9BtcnV239TpTXk6EnbF7wb48w3C9Z+LD3IVFIF5lngucNLlJmp1GI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=K7HtHUVr; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="K7HtHUVr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284423; x=1810820423; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=tVsArRA2sGbQoUu1urPqUjzAv7PIClDuiJsEtM6+h+c=; b=K7HtHUVr+7opDW/0g9u5N8rXRDqxILcmKoZvmhmxk/ns/MO2JvRwnnUv vaoxIghliiFmquTAU7Y6s7FECBIraIOxWcPlHgfYyp5YFOSiYJ7Pn4oju BKye9H1Jb4LzLqgXLSl3KfmuBqeu9L1ZntA5Q1ODtPF39IGe8EDrf4CvL pTRwoY6lmYCdoubFmGqZhNxOOc9TB8V0LM8o5gzHx44KidbR6vc0uSKQc cJkO9WPFlXyTmt5Z6g19il2E30QzWgrip9jwtXBpS1QqXeZsIEiM1VhD7 PEx01zVePPWghHgaE8Xj1mP8JUGfuWmXbatAwFf92grs15whPAtSZM6vV Q==; X-CSE-ConnectionGUID: GJFxBufhS3eUVuztVK5t4Q== X-CSE-MsgGUID: FfTicD4dQ1Keq90pbvf+xQ== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146528" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146528" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:19 -0700 X-CSE-ConnectionGUID: Amq7jAaPSyivrXtCeLJyrg== X-CSE-MsgGUID: vvXZYRJzSty9LCyiEs0c4w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923890" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:18 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 14/25] x86/virt/seamldr: Introduce skeleton for TDX module updates Date: Wed, 20 May 2026 06:38:17 -0700 Message-ID: <20260520133909.409394-15-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable TDX module updates require careful synchronization with other TDX operations. The requirements are (#1/#2 reflect current behavior that must be preserved): 1. SEAMCALLs need to be callable from both process and IRQ contexts. 2. SEAMCALLs need to be able to run concurrently across CPUs 3. During updates, only update-related SEAMCALLs are permitted; all other SEAMCALLs shouldn't be called. 4. During updates, all online CPUs must participate in the update work. No single lock primitive satisfies all requirements. For instance, rwlock_t handles #1/#2 but fails #4: CPUs spinning with IRQs disabled cannot be directed to perform update work. Use stop_machine() as it is the only well-understood mechanism that can meet all requirements. And TDX module updates consist of several steps (See Intel=C2=AE Trust Doma= in Extensions (Intel=C2=AE TDX) Module Base Architecture Specification, Chapter "TD-Preserving TDX module Update"). Ordering requirements between steps mandate lockstep synchronization across all CPUs. multi_cpu_stop() provides a good example of executing a multi-step task in lockstep across CPUs, but it does not synchronize the individual steps inside the callback itself. Implement a similar state machine as the skeleton for TDX module updates. Each state represents one step in the update flow, and the state advances only after all CPUs acknowledge completion of the current step. This acknowledgment mechanism provides the required lockstep execution. The update flow is intentionally simpler than multi_cpu_stop() in two ways: a) use a spinlock to protect the control data instead of atomic_t and explicit memory barriers. b) omit touch_nmi_watchdog() and rcu_momentary_eqs(), which exist there for debugging and are not strictly needed for this update flow Potential alternative to stop_machine() =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D An alternative approach is to lock all KVM entry points and kick all vCPUs. Here, KVM entry points refer to KVM VM/vCPU ioctl entry points, implemented in KVM common code (virt/kvm). Adding a locking mechanism there would affect all architectures KVM supports. And to lock only TDX vCPUs, new logic would be needed to identify TDX vCPUs, which the KVM common code currently lacks. This would add significant complexity and maintenance overhead to KVM for this TDX-specific use case, so don't take this approach. Signed-off-by: Chao Gao Reviewed-by: Xu Yilun Reviewed-by: Tony Lindgren Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Rick Edgecombe --- arch/x86/virt/vmx/tdx/seamldr.c | 87 ++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index 11bd28e8370c..db6c52f65995 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -7,8 +7,10 @@ #define pr_fmt(fmt) "seamldr: " fmt =20 #include +#include #include #include +#include =20 #include =20 @@ -165,6 +167,84 @@ static int init_seamldr_params(struct seamldr_params *= params, return 0; } =20 +/* + * During a TDX module update, all CPUs start from MODULE_UPDATE_START and + * progress to MODULE_UPDATE_DONE. Each state is associated with certain + * work. For some states, just one CPU needs to perform the work, while + * other CPUs just wait during those states. + */ +enum module_update_state { + MODULE_UPDATE_START, + MODULE_UPDATE_DONE, +}; + +static struct update_ctrl { + enum module_update_state state; + int num_ack; + /* + * Protect update_ctrl. Raw spinlock as it will be acquired from + * interrupt-disabled contexts. + */ + raw_spinlock_t lock; +} update_ctrl; + +/* Called with ctrl->lock held or during initialization. */ +static void __set_target_state(struct update_ctrl *ctrl, + enum module_update_state newstate) +{ + /* Reset ack counter. */ + ctrl->num_ack =3D 0; + ctrl->state =3D newstate; +} + +/* Last one to ack a state moves to the next state. */ +static void ack_state(struct update_ctrl *ctrl) +{ + raw_spin_lock(&ctrl->lock); + + ctrl->num_ack++; + if (ctrl->num_ack =3D=3D num_online_cpus()) + __set_target_state(ctrl, ctrl->state + 1); + + raw_spin_unlock(&ctrl->lock); +} + +static void init_state(struct update_ctrl *ctrl) +{ + raw_spin_lock_init(&ctrl->lock); + __set_target_state(ctrl, MODULE_UPDATE_START + 1); +} + +/* + * See multi_cpu_stop() from where this multi-cpu state-machine was + * adopted. + */ +static int do_seamldr_install_module(void *seamldr_params) +{ + enum module_update_state newstate, curstate =3D MODULE_UPDATE_START; + int ret =3D 0; + + do { + newstate =3D READ_ONCE(update_ctrl.state); + + if (curstate =3D=3D newstate) { + cpu_relax(); + continue; + } + + curstate =3D newstate; + switch (curstate) { + /* TODO: add the update steps. */ + default: + break; + } + + ack_state(&update_ctrl); + } while (curstate !=3D MODULE_UPDATE_DONE); + + return ret; +} + /** * seamldr_install_module - Install a new TDX module. * @data: Pointer to the TDX module image. @@ -192,7 +272,12 @@ int seamldr_install_module(const u8 *data, u32 data_le= n) if (ret) goto out; =20 - /* TODO: Update TDX module here */ + /* Ensure a stable set of online CPUs for the update process. */ + cpus_read_lock(); + init_state(&update_ctrl); + ret =3D stop_machine_cpuslocked(do_seamldr_install_module, params, cpu_on= line_mask); + cpus_read_unlock(); + out: kfree(params); return ret; --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0210E3D3480; Wed, 20 May 2026 13:40:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284428; cv=none; b=pNrhFOHM+JdOyCqqAPraKM2ncZ0Dx3vhU24ikZ73woAyP2Y120TiwTQTmD7mtZK8Wz7VMsVZqPeR8coSCzHMgAztksGr86x9sX3KJpGgGuPGW24yJiDuDZC08O9obtK+i0UnWqnci31ocgbLQ37HlClDH2N493kpinUnkneiYk8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284428; c=relaxed/simple; bh=lh0QUflOJ+0B1qD0EDBKQhCL1yyuhVcDXTIhG/1ITuM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nHV2hALJZErsoGYRN9yiRWfR9aYTKh85RJUrqpsvs+GbfYQ3xg3/A0SU5SLZ8phwkZKKq1Z+C5eD3LDbW3zqtGX32GwjoNu1+ammR9TO3UkA2xu1L1U6qfjJCEk4dHE4o0ZQ12BLYwcoO5KOH3qB90GUcelgUiYR0RSCpFINKj0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=nnKXEYaA; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="nnKXEYaA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284426; x=1810820426; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lh0QUflOJ+0B1qD0EDBKQhCL1yyuhVcDXTIhG/1ITuM=; b=nnKXEYaAUqv7c24HodEP9jsCEK7UMqwemYDyWsz8acIrsSjXem1ow0Kl L9IfhsgBMRBvGmjmg5dAjR3aLmcsAcJxE602SR2iCPbhlEjgEbnglwuSP ht15E02n1YekwDvekSNgZ2kE8dW2H3znndQojmkPGkGU6hWKLU5q2w9gO RydbJsNE64PI7kaZ8A3nzADWvM+xZAGsF3grZSVf2q023gexkrhZj5Brk KP6ObZVrfeYy8NZFOM/L8TShTriO0NPz+7dYBbdkGztjFNqSWTNakvYx5 Rn0Hc93oEkFQMim5eQfyqMiu1X74Rt3UCCgXBk014D7ryj+JutncEAr8m Q==; X-CSE-ConnectionGUID: 3JhaJi2nS8KrpboL0Dd+Zw== X-CSE-MsgGUID: kQZbrCvCSe21pUwFnzPJFQ== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146537" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146537" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:20 -0700 X-CSE-ConnectionGUID: s7yx0l03SxegTCq1Fe7pww== X-CSE-MsgGUID: zC//OBAtRhK903Og1bdiSA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923899" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:19 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 15/25] x86/virt/seamldr: Abort updates after a failed step Date: Wed, 20 May 2026 06:38:18 -0700 Message-ID: <20260520133909.409394-16-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A TDX module update is a multi-step process, and any step can fail. The current update flow continues to later steps after an error. Continuing after a failure can cause the TDX module to enter an unrecoverable state. But certain failures during the initial module shutdown step should simply return an error to userspace, so the update can be retried cleanly. To preserve that recoverability, one option would be to abort the update only for those failures, since they occur before any TDX module state is changed. But special-casing specific failures in specific steps would complicate the do-while() update loop for no benefit. Simply abort update on any failure, at any step. Track failures for each step, stop the update loop once a failure is observed, and do not advance the state machine to the next step. Signed-off-by: Chao Gao Reviewed-by: Xu Yilun Reviewed-by: Tony Lindgren Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Link: https://lore.kernel.org/linux-coco/aQFmOZCdw64z14cJ@google.com/ # [1] --- v9: - Avoid nested if/else by deferring failure accounting to ack_state(). - Reduce indentation of the main flow. - Convert the failed flag into a counter. This avoids a conditional update of the flag; the counter can simply accumulate failures. --- arch/x86/virt/vmx/tdx/seamldr.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index db6c52f65995..002cdae3b1ff 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -181,6 +181,7 @@ enum module_update_state { static struct update_ctrl { enum module_update_state state; int num_ack; + int num_failed; /* * Protect update_ctrl. Raw spinlock as it will be acquired from * interrupt-disabled contexts. @@ -198,12 +199,13 @@ static void __set_target_state(struct update_ctrl *ct= rl, } =20 /* Last one to ack a state moves to the next state. */ -static void ack_state(struct update_ctrl *ctrl) +static void ack_state(struct update_ctrl *ctrl, int result) { raw_spin_lock(&ctrl->lock); =20 + ctrl->num_failed +=3D !!result; ctrl->num_ack++; - if (ctrl->num_ack =3D=3D num_online_cpus()) + if (ctrl->num_ack =3D=3D num_online_cpus() && !ctrl->num_failed) __set_target_state(ctrl, ctrl->state + 1); =20 raw_spin_unlock(&ctrl->lock); @@ -213,6 +215,7 @@ static void init_state(struct update_ctrl *ctrl) { raw_spin_lock_init(&ctrl->lock); __set_target_state(ctrl, MODULE_UPDATE_START + 1); + ctrl->num_failed =3D 0; } =20 /* @@ -239,8 +242,8 @@ static int do_seamldr_install_module(void *seamldr_para= ms) break; } =20 - ack_state(&update_ctrl); - } while (curstate !=3D MODULE_UPDATE_DONE); + ack_state(&update_ctrl, ret); + } while (curstate !=3D MODULE_UPDATE_DONE && !READ_ONCE(update_ctrl.num_f= ailed)); =20 return ret; } --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 088413DD518; Wed, 20 May 2026 13:40:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284430; cv=none; b=NeN9MhFlA3SK8QNt1/yUdzSMnJcS/uVnlF6XaQaR2oCKHvxZoxhxC3MgdUW329rH+1mRzFJr2bZcYK4tIE+mobmsMPZPGDrLIFUub5hqZAlGUouRIRNQ5uVMHqFCiwX9gl69EWJ+eF4I4LmF30ocMiLWBgkNpqOobwHPD+cyLjU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284430; c=relaxed/simple; bh=rL4SsUZOmcccWMsTgDnBY03K7sLgLIBYfmhJw2Db6OI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DQHiX9M+Bqp2ovJ0F/pgN3QUpZeAfo593Yn0JWqA2rX9vN9IYWyE/w41anGuovE29sd2jmlBdBLPa8PNIALX6VB/8impPFXbPyt1PbfSCnhAYzejmnAAJd7Ya84yiFsrvkpid29qjRFtL9yiqaOVOxtWlRlbWKWFDLzviZLIiXs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=LoKA4pfY; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="LoKA4pfY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284426; x=1810820426; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rL4SsUZOmcccWMsTgDnBY03K7sLgLIBYfmhJw2Db6OI=; b=LoKA4pfYR8T5bWnmjxvQCqyX2qASi/06hLqruoxT3Vi2NQKvKBzracKD pcukqjt+kqGsQUAUSsBmpRmE9xaBLooEo4r8oCxIamu09wHVfrg26QBv+ XcO927QYdl+Cb5LfdB9R5i4pH5iyODm/xoudJY7dB37qK3/Tve6JMFqOU ZoOu4IXdV9rFe6JvVgaAAr8ie3XlbeBIDdXk6WSKGqZROw1wqvzt08OC1 CTsF+xegp6mPdBcL2/4AnuiZU5s5XH79swSMWEaiMrSGxXkuUxu+HsSrh +U/662FPe6f+gmXbpF/XgpQxHeGbd6UZ5g2/PXAd3PX1N/N0Ji13UTR5E A==; X-CSE-ConnectionGUID: 8ZyHsss6SbWQb64OVSpJPA== X-CSE-MsgGUID: 1bT8GTGfSyaBg2n/17nAaA== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146545" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146545" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:22 -0700 X-CSE-ConnectionGUID: SM3T7PGtSWejdrWTId3p9w== X-CSE-MsgGUID: HP4Urmy1TA6QhkaRiVwrrw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923917" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:20 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 16/25] x86/virt/seamldr: Shut down the current TDX module Date: Wed, 20 May 2026 06:38:19 -0700 Message-ID: <20260520133909.409394-17-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The first step of TDX module updates is shutting down the current TDX module. This step also packs state information that needs to be preserved across updates, called "handoff data". This handoff data is consumed by the updated module and stored internally in the SEAM range and hidden from the kernel. Since handoff data layout may change between modules, the handoff data is versioned. Each module has a native handoff version and provides backward support for several older versions. The complete handoff versioning protocol is complex as it supports both module upgrades and downgrades. See details in Intel=C2=AE Trust Domain Extensions (Intel=C2=AE TDX) Module Base Architecture Specification, Chapter "Handoff Versioning". Ideally, the kernel needs to retrieve the handoff versions supported by the current module and the new module and select a version supported by both. But since this implementation only supports module upgrades, simply request handoff data from the current module using its highest supported version. That is sufficient for this upgrade-only implementation. Retrieve the module's handoff version from TDX global metadata and add an update step to shut down the module. Module shutdown only needs to run on one CPU. Don't cache the handoff information in tdx_sysinfo. It is used only for module shutdown, and is present only when the TDX module supports updates. Caching it in get_tdx_sys_info() would require extra update-support guards and refreshing the cached value across module updates. Signed-off-by: Chao Gao Reviewed-by: Tony Lindgren Reviewed-by: Xu Yilun Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) --- v10: - Polish the changelog [Rick] - Rename "primary" to "is_lead_cpu" and polish the comment above it [Rick] --- arch/x86/include/asm/tdx_global_metadata.h | 4 ++++ arch/x86/virt/vmx/tdx/seamldr.c | 15 ++++++++++++++- arch/x86/virt/vmx/tdx/tdx.c | 19 ++++++++++++++++++- arch/x86/virt/vmx/tdx/tdx.h | 3 +++ arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 13 +++++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/= asm/tdx_global_metadata.h index 40689c8dc67e..41150d546589 100644 --- a/arch/x86/include/asm/tdx_global_metadata.h +++ b/arch/x86/include/asm/tdx_global_metadata.h @@ -40,6 +40,10 @@ struct tdx_sys_info_td_conf { u64 cpuid_config_values[128][2]; }; =20 +struct tdx_sys_info_handoff { + u16 module_hv; +}; + struct tdx_sys_info { struct tdx_sys_info_version version; struct tdx_sys_info_features features; diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index 002cdae3b1ff..217b3c962aff 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -15,6 +15,7 @@ #include =20 #include "seamcall_internal.h" +#include "tdx.h" =20 /* P-SEAMLDR SEAMCALL leaf function */ #define P_SEAMLDR_INFO 0x8000000000000000 @@ -175,6 +176,7 @@ static int init_seamldr_params(struct seamldr_params *p= arams, */ enum module_update_state { MODULE_UPDATE_START, + MODULE_UPDATE_SHUTDOWN, MODULE_UPDATE_DONE, }; =20 @@ -225,8 +227,16 @@ static void init_state(struct update_ctrl *ctrl) static int do_seamldr_install_module(void *seamldr_params) { enum module_update_state newstate, curstate =3D MODULE_UPDATE_START; + int cpu =3D smp_processor_id(); + bool is_lead_cpu; int ret =3D 0; =20 + /* + * Some steps must be run on exactly one CPU. Pick a "lead" CPU to + * execute those steps. Use CPU 0 because it is always online. + */ + is_lead_cpu =3D cpu =3D=3D 0; + do { newstate =3D READ_ONCE(update_ctrl.state); =20 @@ -237,7 +247,10 @@ static int do_seamldr_install_module(void *seamldr_par= ams) =20 curstate =3D newstate; switch (curstate) { - /* TODO: add the update steps. */ + case MODULE_UPDATE_SHUTDOWN: + if (is_lead_cpu) + ret =3D tdx_module_shutdown(); + break; default: break; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 53cf99c41dbb..84d5df70a250 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -328,7 +328,7 @@ static __init int build_tdx_memlist(struct list_head *t= mb_list) return ret; } =20 -static __init int read_sys_metadata_field(u64 field_id, u64 *data) +static int read_sys_metadata_field(u64 field_id, u64 *data) { struct tdx_module_args args =3D {}; int ret; @@ -1274,6 +1274,23 @@ static __init int tdx_enable(void) } subsys_initcall(tdx_enable); =20 +int tdx_module_shutdown(void) +{ + struct tdx_sys_info_handoff handoff =3D {}; + struct tdx_module_args args =3D {}; + int ret; + + ret =3D get_tdx_sys_info_handoff(&handoff); + WARN_ON_ONCE(ret); + + /* + * Use the module's handoff version as it is the highest the + * module can produce and most likely supported by newer modules. + */ + args.rcx =3D handoff.module_hv; + return seamcall_prerr(TDH_SYS_SHUTDOWN, &args); +} + static bool is_pamt_page(unsigned long phys) { struct tdmr_info_list *tdmr_list =3D &tdx_tdmr_list; diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 76c5fb1e1ffe..f0c20dea0388 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -46,6 +46,7 @@ #define TDH_PHYMEM_PAGE_WBINVD 41 #define TDH_VP_WR 43 #define TDH_SYS_CONFIG 45 +#define TDH_SYS_SHUTDOWN 52 #define TDH_SYS_DISABLE 69 =20 /* @@ -108,4 +109,6 @@ struct tdmr_info_list { int max_tdmrs; /* How many 'tdmr_info's are allocated */ }; =20 +int tdx_module_shutdown(void); + #endif diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vm= x/tdx/tdx_global_metadata.c index d54d4227990c..e793dec688ab 100644 --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c @@ -100,6 +100,19 @@ static __init int get_tdx_sys_info_td_conf(struct tdx_= sys_info_td_conf *sysinfo_ return ret; } =20 +static int get_tdx_sys_info_handoff(struct tdx_sys_info_handoff *sysinfo_h= andoff) +{ + int ret; + u64 val; + + ret =3D read_sys_metadata_field(0x8900000100000000, &val); + if (ret) + return ret; + + sysinfo_handoff->module_hv =3D val; + return 0; +} + static __init int get_tdx_sys_info(struct tdx_sys_info *sysinfo) { int ret =3D 0; --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C0253EA97B; Wed, 20 May 2026 13:40:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284433; cv=none; b=Vre+m3qVhxAssIPvr9ylO+9SQDc91zB0eOeZ/HovxPYA40HX3BgYaXkay0DSsP0pEmHRWRp+7i+2/UCfsIN0U0GumoVvFhsiruFBc+BhLCtqtNLNdM3kPAXD6+hENFst0QV2TSvAIZBXzxEazMszCES7YHBCJC1Az7qtO9MsbAQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284433; c=relaxed/simple; bh=XRVwVR2NLOG1LjcAaIrvI4Up3jDwgvxuJgeTqpfmaTI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aX45OJfUI1r+KYlbC6KkazV8REzaKd0/8z7kcU8Ujdl2rJ4gRsdWEl6n6sm5P3xZn7lebLQsc+5q8PCvye658/8U5e37oXjeWmGOY2sP7EQ7mhBBHlqlbcUL0PAwZBf5MGILIcKl9QMNZT69VP6g2u/9X3v56+pohE0b15O89GQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=g4sFg26k; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="g4sFg26k" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284429; x=1810820429; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XRVwVR2NLOG1LjcAaIrvI4Up3jDwgvxuJgeTqpfmaTI=; b=g4sFg26kCq3WZwNILxFEJE0yM/bbAVHXeXb37TRdfKgvyTGuClrpZf4X xINVUtErgB9N2lSYiU8vSaoPfGTjTpuisT8FLO/IVN9cfkyLMe7WhnQWt o6NQM5KgC/ble3gvUq0ppZ7cH58CoHfTAR5KuL2xHsUDQde0gX0fyYYpo dX5ELtsQUotyP9Xhm0f51jegWtCTh+VsmGeBD63QtAjMPmIYpsqATnVPQ ls1gh0Qq3N6rIRV2yTFR8l7wzpEddN+QowFsl8klspEmrenfHmm0rzlQe kcx/gQFUN6L2ZIW8gCiIsTHhUNqC/nazfvdjXg2cEDhkReiqpPCuDT/7R g==; X-CSE-ConnectionGUID: RAZmKTSGR4uqa9Z9NScSIQ== X-CSE-MsgGUID: XH56KSheT6qKHPawhKpkdA== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146554" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146554" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:23 -0700 X-CSE-ConnectionGUID: eDLnSouLTWuVa8WJR5V/Ag== X-CSE-MsgGUID: oSWCP1WLRKeqrmVxnouTCg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923931" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:21 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 17/25] x86/virt/tdx: Reset software states during TDX module shutdown Date: Wed, 20 May 2026 06:38:20 -0700 Message-ID: <20260520133909.409394-18-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The TDX module requires a one-time global initialization (TDH.SYS.INIT) and per-CPU initialization (TDH.SYS.LP.INIT) before use. These initializations are guarded by software flags to prevent repetition. After TDX module updates, the new TDX module requires the same global and per-CPU initializations, but the existing software flags prevent re-initialization. Reset all software flags guarding the initialization flows to allow the global and per-CPU initializations to be triggered again after updates. Signed-off-by: Chao Gao Reviewed-by: Tony Lindgren Reviewed-by: Kai Huang Reviewed-by: Rick Edgecombe --- v9: - use a global structure for TDX global state and use memset to zero the whole structure [Dave] --- arch/x86/virt/vmx/tdx/tdx.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 84d5df70a250..01d0087180a0 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1278,7 +1278,7 @@ int tdx_module_shutdown(void) { struct tdx_sys_info_handoff handoff =3D {}; struct tdx_module_args args =3D {}; - int ret; + int ret, cpu; =20 ret =3D get_tdx_sys_info_handoff(&handoff); WARN_ON_ONCE(ret); @@ -1288,7 +1288,21 @@ int tdx_module_shutdown(void) * module can produce and most likely supported by newer modules. */ args.rcx =3D handoff.module_hv; - return seamcall_prerr(TDH_SYS_SHUTDOWN, &args); + ret =3D seamcall_prerr(TDH_SYS_SHUTDOWN, &args); + if (ret) + return ret; + + /* + * Clear global and per-CPU initialization flags so the new module + * can be fully re-initialized after a successful update. + * + * No locks needed as no concurrent accesses can occur here. + */ + memset(&tdx_module_state, 0, sizeof(tdx_module_state)); + for_each_possible_cpu(cpu) + per_cpu(tdx_lp_initialized, cpu) =3D false; + + return 0; } =20 static bool is_pamt_page(unsigned long phys) --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3BA4F3E92BA; Wed, 20 May 2026 13:40:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284433; cv=none; b=QTCfoqFDYWyXWMN4ef7GOXUI0UezWurNSVjZO3SbYNxzabvHhU4cBh5SdtR9T1AfOoH9nU44x5PXAiO+AJ/EL2bh0IJShkkk6JLwx8z8pkVOWgNRaDEwlfoZAd/D9lcKmoEMv2m9yOQhSk9mthvYoiy5hvHoYxymWJK/bUs9fVE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284433; c=relaxed/simple; bh=x+zSpLlvXkFLQ91oeRt+Qpao7+rP7ECB/QZPTdOkZ1Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=db+LPxj79jhU7U7emSj45Fpmv913QOnmx5GcD9bQZp4I6IbHQMI5MeU4krC3MAZNblBHY/UyBG9JXKv/6eMgzk/QXcgWxfSJesgOKl3GPNVlMUl4Jnd1qV7SEbZQNTs8wCu8MgZagJpFvb3eFq6NePZabg2y+BG5xhneReObrZI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Zw11qEyO; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Zw11qEyO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284430; x=1810820430; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=x+zSpLlvXkFLQ91oeRt+Qpao7+rP7ECB/QZPTdOkZ1Q=; b=Zw11qEyOn1Ip139LqBiLr/wM/1fO58gK1ulZHLP6gL+jJeSfXUpogQXP Nj3QlqCCSoxubFwY/G4cDPHhVrA8+J0KCcWfqHHaxKr49d+2EQxQQeC7D 4Yt2QKjuQqvKE5VGoPTi2F9q02E8bparI47WHYvBaHYL+vM9IpUGJvzlr ZCvwUCGUSPwqfiTe+nji+TR9bMORkQnTY5qbQKWFWkf9AP1nP63hi3kC9 fajSV57aRj8AzgelMP0Wfkgrk3wxKFQdTw8Z2Plnqg92QfuBjg6+2GlOp AoV7NnSAyAwyTxkiv9LqdcBJBjqmYDmKPAJnqxEkeZSB/RAp7Nzs26Qn1 A==; X-CSE-ConnectionGUID: JDiNtZ/4QqOFp/bytrPQeA== X-CSE-MsgGUID: nIJg5/fDSwi6eQBVv34EFg== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146564" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146564" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:24 -0700 X-CSE-ConnectionGUID: SqIAl3EBQDivEsUzz8rNjg== X-CSE-MsgGUID: d94DxpP+QAKF1sVvcQ1Kfw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923939" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:23 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 18/25] x86/virt/seamldr: Install a new TDX module Date: Wed, 20 May 2026 06:38:21 -0700 Message-ID: <20260520133909.409394-19-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Following the shutdown of the existing TDX module, the update process continues with installing the new module. P-SEAMLDR provides the SEAMLDR.INSTALL SEAMCALL to perform this installation, which must be executed on all CPUs. Implement SEAMLDR.INSTALL and execute it on every CPU. Signed-off-by: Chao Gao Reviewed-by: Tony Lindgren Reviewed-by: Kai Huang Reviewed-by: Xu Yilun Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Rick Edgecombe --- v9: - Add a comment above seamldr_install() --- arch/x86/virt/vmx/tdx/seamldr.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index 217b3c962aff..afd8179e5c98 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -19,6 +19,7 @@ =20 /* P-SEAMLDR SEAMCALL leaf function */ #define P_SEAMLDR_INFO 0x8000000000000000 +#define P_SEAMLDR_INSTALL 0x8000000000000001 =20 #define SEAMLDR_MAX_NR_MODULE_PAGES 496 #define SEAMLDR_MAX_NR_SIG_PAGES 1 @@ -76,6 +77,15 @@ int seamldr_get_info(struct seamldr_info *seamldr_info) } EXPORT_SYMBOL_FOR_MODULES(seamldr_get_info, "tdx-host"); =20 +/* Call into P-SEAMLDR to install a TDX module update */ +static int seamldr_install(const struct seamldr_params *params) +{ + struct tdx_module_args args =3D {}; + + args.rcx =3D __pa(params); + return seamldr_call(P_SEAMLDR_INSTALL, &args); +} + #define TDX_IMAGE_VERSION_2 0x200 =20 struct tdx_image_header { @@ -177,6 +187,7 @@ static int init_seamldr_params(struct seamldr_params *p= arams, enum module_update_state { MODULE_UPDATE_START, MODULE_UPDATE_SHUTDOWN, + MODULE_UPDATE_CPU_INSTALL, MODULE_UPDATE_DONE, }; =20 @@ -251,6 +262,9 @@ static int do_seamldr_install_module(void *seamldr_para= ms) if (is_lead_cpu) ret =3D tdx_module_shutdown(); break; + case MODULE_UPDATE_CPU_INSTALL: + ret =3D seamldr_install(seamldr_params); + break; default: break; } --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E308E3E95B3; Wed, 20 May 2026 13:40:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284433; cv=none; b=BsXc24ZW4aYxbuB3Fa5F2ARSOIjSWKWDYyizQrSYiCujQ/DaRVV9gKaT169e8fKFywAwoFiGQXd0BYg+4CBdb8QNAnv3FgcC6Spnq5AQfws98IbdVBZVODWQtTuW0PNBRAkpa+JkZ/5sMXnaGF+8hpyCwo3emvm+pn9OU0fCWAY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284433; c=relaxed/simple; bh=hSwqZtE6R79puNZ3iGIjxtW6FnHjj4i3G49DAaZ7Vmc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C9kDaBgURCfczZccxa2R1GodGPqHNfWGDvpkm54VhA6qjG18chQCKbjb0J7NBBwCaXQ+ANjuwzu9fEMTg3dxp2VoNwxvw0/XuZp3LcLIFm3+Y9NUNK/iuxVh6UiMJV2kuPugmMbq+nGMXeVZnSfCXkUsnkW7T5dolqY/jD0Zv+M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=mAYwmicl; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="mAYwmicl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284432; x=1810820432; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hSwqZtE6R79puNZ3iGIjxtW6FnHjj4i3G49DAaZ7Vmc=; b=mAYwmiclGUkVxr80eC9/yumrXm5qfkgs6mWjNliYC8eZdKJDNiej9gtl mJj1S/BxtfzBEUCsCEmlDbaCHx4qTkXMvOWmFynSXiSJJDktlWkDXeKAB xjBlonzzeZbH0KkL5YRdBwRT7NcRybFC46EdpM87JbR8jNMk0u6xeHRN9 9upnEdI5+RHWiMgvE4+MverNhLl9OhRUPg7BaM1abKHA9xU+hm4K8/gCB JUD/Kf7029WuAMkeKNMDuMQKeNnMXtQzTWyxLniyzLKJQt46KHg4of1zZ XhOIWuXOx7oVBBNEJlFmWRA0qQ30vy+QB0ZM5r2B8NlGLF5uK5tdeTYBw Q==; X-CSE-ConnectionGUID: rILT+avfTrChiDx7SPu5xg== X-CSE-MsgGUID: 4u+VRQRtRau5Fbp3fzlcCw== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146581" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146581" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:25 -0700 X-CSE-ConnectionGUID: JkHN4SE5RR2j/GWSJNdyNg== X-CSE-MsgGUID: Fe8wMNq/T5i/XxNNfdT7zQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923956" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:24 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 19/25] x86/virt/seamldr: Do TDX global and per-CPU init after module installation Date: Wed, 20 May 2026 06:38:22 -0700 Message-ID: <20260520133909.409394-20-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" After installing a new TDX module, the kernel must re-initialize TDX before resuming TDX operations. This post-update initialization differs from the initial boot-time initialization. It only needs TDX global initialization, TDX per-CPU initialization, and restoration of TDX state from the handoff data. tdx_cpu_enable() covers the global and per-CPU initialization. Export it and invoke it on all CPUs. Signed-off-by: Chao Gao Reviewed-by: Xu Yilun Reviewed-by: Tony Lindgren Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Rick Edgecombe --- arch/x86/include/asm/tdx.h | 1 + arch/x86/virt/vmx/tdx/seamldr.c | 4 ++++ arch/x86/virt/vmx/tdx/tdx.c | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 27376db7ddac..5d750fe53669 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -107,6 +107,7 @@ static inline long tdx_kvm_hypercall(unsigned int nr, u= nsigned long p1, =20 #ifdef CONFIG_INTEL_TDX_HOST void tdx_init(void); +int tdx_cpu_enable(void); const char *tdx_dump_mce_info(struct mce *m); const struct tdx_sys_info *tdx_get_sysinfo(void); =20 diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index afd8179e5c98..a026de7f7bcd 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -188,6 +188,7 @@ enum module_update_state { MODULE_UPDATE_START, MODULE_UPDATE_SHUTDOWN, MODULE_UPDATE_CPU_INSTALL, + MODULE_UPDATE_CPU_INIT, MODULE_UPDATE_DONE, }; =20 @@ -265,6 +266,9 @@ static int do_seamldr_install_module(void *seamldr_para= ms) case MODULE_UPDATE_CPU_INSTALL: ret =3D seamldr_install(seamldr_params); break; + case MODULE_UPDATE_CPU_INIT: + ret =3D tdx_cpu_enable(); + break; default: break; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 01d0087180a0..5292dd8d1e36 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -113,7 +113,7 @@ static int try_init_module_global(void) * (and TDX module global initialization SEAMCALL if not done) on local cp= u 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 =3D {}; int ret; --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 58E723ED3D8; Wed, 20 May 2026 13:40:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284435; cv=none; b=romZwZG+d+2lHk5b7e4/SoQUvVSVvs0Np7/RR7uUhf8AJPLadVLYE1XypuHvScLEc8PpO4uCZbfpXEJu8NOxUsVwVYlASQdAr4ZA+LuKCRX7HOhxWkr+OeCXVnLc2otg697Y9i++6MrC0uQzvdcYtoPwYOUQputSQBicOGbOQAw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284435; c=relaxed/simple; bh=XV9VTJ3o2IDh1IiNVSnV+YGyHt511oVNICOLhvRSQco=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VBnc11EcfnuUoNg/fZFvq7f6WEzXKcRyFbBl7vvbxLBHsxdKjp8TjLoZd/T50+fbJ4yW5tF3RnRyYqyKIlXVBOpacnQpcuGuZjUXumJn9bwsJ4QjZheJjoSraGwCn4GgVxszVGYm2ExEXmPdD/nE5ZBni5Rg18TrTXKZ8ARlh+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=bSBD+VqN; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bSBD+VqN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284434; x=1810820434; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XV9VTJ3o2IDh1IiNVSnV+YGyHt511oVNICOLhvRSQco=; b=bSBD+VqN58CHVV6MlgkVAnHmmB7InjN/eJ847qiwXk0xtkaM/EwaGXbb F8oujB+fkxxr61PdTtM6MeADfNTDXl0FXhhQdm4BLCBoXV3k9Yl+C6szx G0HSY71PL0PLPbK56Llgwbs/Eml1vxYFH5dY7HSTQsoTtn2JmA3qATZiM 8h9qlebUKO6bNh9ZZCdFkFSaAxe3RhFGMptwT1DMwn2zRHTzdndMR362m RURDq/ecuy4qWeCICS2rcSnHhVjiWtIFi5F+EreriMOw3oXS8vKSbBapS 3ejJmBG70HqVs334LmsfYBbpmqA0xVCDUVImCcKii8JwZSM0jsWRhMhzs g==; X-CSE-ConnectionGUID: biiqyHnhRmWPH5sOlDySlg== X-CSE-MsgGUID: Hm4GP/7wTECm2G/2yLShIA== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146594" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146594" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:28 -0700 X-CSE-ConnectionGUID: 9asMpD3bQziHFu/87M9Qgw== X-CSE-MsgGUID: KerPXY/RTqOqIrkBicue9w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235923985" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:25 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 20/25] x86/virt/tdx: Restore TDX module state Date: Wed, 20 May 2026 06:38:23 -0700 Message-ID: <20260520133909.409394-21-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable TDX module state was packed as handoff data during module shutdown. After per-CPU initialization, the new module can restore TDX module state from handoff data to preserve running TDs. Once the restoration is done, the TDX module update is complete, which means the new module is ready to handle requests from the host and guests. Implement the new TDH.SYS.UPDATE SEAMCALL to restore TDX module state and invoke it on one CPU since it only needs to be called once. For error handling, Intel=C2=AE Trust Domain Extensions (Intel=C2=AE TDX) Module Base Architecture Specification, Chapter "Restore TDX Module State after a TD-Preserving Update" states If TDH.SYS.UPDATE returns an error, then the host VMM can continue with the non-update sequence (TDH.SYS.CONFIG, TDH.SYS.KEY.CONFIG etc.). In this case all existing TDs are lost. Alternatively, the host VMM can request the P-SEAMLDR to update to another TDX module. If that update is successful, existing TDs are preserved. No error is expected if the new module is fully compatible, and userspace should enforce that as part of update image selection. Given the complexity and uncertain value of the recovery paths above, simply propagate errors. Note: the location and the format of handoff data is defined by the TDX module. The new module knows where to get handoff data and how to parse it. The kernel doesn't need to provide its location, format etc. Signed-off-by: Chao Gao Reviewed-by: Tony Lindgren Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Rick Edgecombe --- arch/x86/virt/vmx/tdx/seamldr.c | 5 +++++ arch/x86/virt/vmx/tdx/tdx.c | 13 +++++++++++++ arch/x86/virt/vmx/tdx/tdx.h | 2 ++ 3 files changed, 20 insertions(+) diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamld= r.c index a026de7f7bcd..ff95d8dd1162 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -189,6 +189,7 @@ enum module_update_state { MODULE_UPDATE_SHUTDOWN, MODULE_UPDATE_CPU_INSTALL, MODULE_UPDATE_CPU_INIT, + MODULE_UPDATE_RUN_UPDATE, MODULE_UPDATE_DONE, }; =20 @@ -269,6 +270,10 @@ static int do_seamldr_install_module(void *seamldr_par= ams) case MODULE_UPDATE_CPU_INIT: ret =3D tdx_cpu_enable(); break; + case MODULE_UPDATE_RUN_UPDATE: + if (is_lead_cpu) + ret =3D tdx_module_run_update(); + break; default: break; } diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 5292dd8d1e36..e3f5aa272850 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1305,6 +1305,19 @@ int tdx_module_shutdown(void) return 0; } =20 +int tdx_module_run_update(void) +{ + struct tdx_module_args args =3D {}; + int ret; + + ret =3D seamcall_prerr(TDH_SYS_UPDATE, &args); + if (ret) + return ret; + + tdx_module_state.initialized =3D true; + return 0; +} + static bool is_pamt_page(unsigned long phys) { struct tdmr_info_list *tdmr_list =3D &tdx_tdmr_list; diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index f0c20dea0388..bdfd0e1e337a 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -47,6 +47,7 @@ #define TDH_VP_WR 43 #define TDH_SYS_CONFIG 45 #define TDH_SYS_SHUTDOWN 52 +#define TDH_SYS_UPDATE 53 #define TDH_SYS_DISABLE 69 =20 /* @@ -110,5 +111,6 @@ struct tdmr_info_list { }; =20 int tdx_module_shutdown(void); +int tdx_module_run_update(void); =20 #endif --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B00B3ED5C8; Wed, 20 May 2026 13:40:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284436; cv=none; b=EPlDtqbM5E/oVdHS1ogIEpi20BKV0aIJ1DxPbfOamJmGZTLpVoX+cA9HuhqztF5af8lzqry+eq7n7aTueXqqXH1zNVTV9LlYBnriNvhVn2E0koTkik2stSh0ltvEqZz1GaZHQ7Kcm466ooA7p/JFAkaorXcmHVVa4/Tp4WQvXaI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284436; c=relaxed/simple; bh=hOoQJsF3eoYLl4ehmDFfBhq4rnZyHDdnTvgvj7hVnpQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VhBMxNHi/kJOU8NSuzac6TsfMuBHs+qTPW3U6mWr7m4aFe9niVNg+3+/iHDq30aqYqul+WskGNFXwZ4Ty4nnXIWz8xPrQDFHrUoSnPFU2PfjQfWdGdJrnQlxEkgSvsoCpVhWn7ll5/ebMaPrjStzHxDapucJ3r5F4w86XEq6wTI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=NGHz61FZ; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="NGHz61FZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284434; x=1810820434; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=hOoQJsF3eoYLl4ehmDFfBhq4rnZyHDdnTvgvj7hVnpQ=; b=NGHz61FZi6ngMylB8n9MKDrh7ecMCYcOO9n47sv69OIEezhxuF467GU5 wo63zK7ooOsg3w19a5xt+2pLy64wHwtcfbhr9CeWPoyfh7LmoI4sbSpkx Z9m75hLw30wBg5WogVLIDP4xlbbXiMxczhlhpQpPSyV6Jt820ZOLB6L1c orv5+L3rYRZHt1HcZoUo/qrxwFrQIpzHr82j0niJ+XDIGG/Ycw47iiH/g 8W0eEW8Yv+GqpekutsthhKHlOUJVePOcplHHhWFvokxm4/o8+Ls5sf9Cu 6j9oOKQ5naaKfSDgW6U3RkZHWQ0eoEZLI4GruUFBGnnLWlbkNwgNzGL3J A==; X-CSE-ConnectionGUID: mc+mh0WxTT26aR+6M5d8+w== X-CSE-MsgGUID: 3AKxGXbHS+29ykrnthNsxg== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146636" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146636" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:34 -0700 X-CSE-ConnectionGUID: XQRyVHvfTLyiQLipH1CjjQ== X-CSE-MsgGUID: TISOXAucRJmuzJiL2nVqVw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235924023" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:28 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 21/25] x86/virt/tdx: Refresh TDX module version after update Date: Wed, 20 May 2026 06:38:24 -0700 Message-ID: <20260520133909.409394-22-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The kernel exposes the TDX module version through sysfs so userspace can check update compatibility. That information needs to remain accurate across runtime updates. A runtime update may change the module's update_version, so refresh the cached version right after a successful update. Drop __ro_after_init from tdx_sysinfo because it is now updated at runtime. Do not refresh the rest of tdx_sysinfo, even if some values change across updates. TDX module updates are backward compatible, so existing tdx_sysinfo consumers, such as KVM, can continue to operate without seeing the new values. Refreshing the full structure would be risky. A tdx_sysinfo consumer may initialize its TDX support based on the features originally reported in tdx_sysinfo. If a runtime update adds new features and the full structure is refreshed, that consumer could observe and use the newly reported features without having performed the setup required to use them safely. Signed-off-by: Chao Gao Reviewed-by: Rick Edgecombe --- v9: - don't print old and new version [Dave] - explain why it's OK to hide changes from the tdx_sysinfo users [Dave] - update versions in stop_machine context - don't mention major/minor versions are idential across updates. That fact= is not relevant here. --- arch/x86/virt/vmx/tdx/tdx.c | 6 +++++- arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index e3f5aa272850..55670365a388 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -67,7 +67,7 @@ static struct tdmr_info_list tdx_tdmr_list; /* All TDX-usable memory regions. Protected by mem_hotplug_lock. */ static LIST_HEAD(tdx_memlist); =20 -static struct tdx_sys_info tdx_sysinfo __ro_after_init; +static struct tdx_sys_info tdx_sysinfo; =20 static DEFINE_RAW_SPINLOCK(sysinit_lock); =20 @@ -1314,6 +1314,10 @@ int tdx_module_run_update(void) if (ret) return ret; =20 + /* Shouldn't fail as the update has succeeded. */ + ret =3D get_tdx_sys_info_version(&tdx_sysinfo.version); + WARN_ON_ONCE(ret); + tdx_module_state.initialized =3D true; return 0; } diff --git a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c b/arch/x86/virt/vm= x/tdx/tdx_global_metadata.c index e793dec688ab..e49c300f23d4 100644 --- a/arch/x86/virt/vmx/tdx/tdx_global_metadata.c +++ b/arch/x86/virt/vmx/tdx/tdx_global_metadata.c @@ -7,7 +7,7 @@ * Include this file to other C file instead. */ =20 -static __init int get_tdx_sys_info_version(struct tdx_sys_info_version *sy= sinfo_version) +static int get_tdx_sys_info_version(struct tdx_sys_info_version *sysinfo_v= ersion) { int ret =3D 0; u64 val; --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 943923EEAFC; Wed, 20 May 2026 13:40:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284437; cv=none; b=F9OlYP0atahn/VOCkBY62cn++4sh/xFIVccwzEc/L7jbb1aOUIqyaq13lKb3pcs2DApiL5qwgR9IA5SEVX2kopyc5hG4qQzDMHMMFqDo+5BGcki+zlltR/NxwEVsVojstvC++EiT11wEBGAmMOad4NIRyC7Ki0ZDCpl8m7ZwXsE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284437; c=relaxed/simple; bh=SfUqIbovDctXOfDJoZGNmcLgvKdlszSKEqnHPTKF+R8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=c2DqOnFwbTJmkFHqXPxmn2/E1uBeIIW0gfkbhBYQUoTZRGJ4LxtDCYLePJWrLyqxtdcx3BjmCYr56kSzLEfAnot2ps1RvVXp5iuFBJizVZc59I2cJq8pQdONrYwCSxegPWf8JnWZlrU1k0kA03rNXR9ZvizpHRr9dG7ezn1iCtw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Oj9RqqCu; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Oj9RqqCu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284435; x=1810820435; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SfUqIbovDctXOfDJoZGNmcLgvKdlszSKEqnHPTKF+R8=; b=Oj9RqqCueEO/ikHR5g0e0vZWnOTUlbWanm5s+kvjI6OLRIyQrQ6Vtif+ owML9OiGcP/VsPv/M7MXBAYKzK/NfFUHKpazWovSH8FhZ/0goacVeC+mF 4PwkHAOdx3xRGCoIOgoublexNe8O/zaJI+pPuRR+FDVKF1eWLRGu2DnaZ E0uwMV7JLpzEyMyCdhgvvuzaaRb10kXr4iYCQq5rMGlrwNiiyJ5O2/gay IO0OF2DzGEfP++eDes5BJK0jrtPad30lm5iPX/n3p4kibxAuG4/+SC1Tf +3+pwSalZLeBfn+3elH98jsBOFM1wO999LfgWRhS+0B+qqMyTG7FIRmru Q==; X-CSE-ConnectionGUID: i4rdJgpPSjGfTyh13i/G2Q== X-CSE-MsgGUID: oZOFYrhoSqe0Isi9WIPB0w== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146646" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146646" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:35 -0700 X-CSE-ConnectionGUID: N+h68RMFSIWGPKHyvwlvEA== X-CSE-MsgGUID: aFTXQAufQSuOslCzBirO/A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235924035" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:34 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 22/25] x86/virt/tdx: Reject updates during compatibility-sensitive operations Date: Wed, 20 May 2026 06:38:25 -0700 Message-ID: <20260520133909.409394-23-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A TDX module erratum can cause TD state corruption if a module update races with a compatibility-sensitive operation. For example, if an update races with TD build, the TD measurement hash may be corrupted, which can later cause attestation failure. Handle this by requesting the TDX module to detect such races during TDH.SYS.SHUTDOWN and reject the update when one is found. Report the failure to userspace as -EBUSY so the update can be retried. The downside is that module updates can be blocked indefinitely if compatibility-sensitive operations do not quiesce. In that case, userspace must resolve the conflict and retry the update. Do not pre-check whether the TDX module supports this race-detection capability. If it does not, rely on the TDX module to reject module shutdown. =3D=3D Alternatives =3D=3D Two alternatives were considered and rejected [1]: a. Fail TD build when the race occurs. This would complicate KVM error handling and risk KVM uABI instability. b. Allow the issue to leak through. This would make the problem harder to detect and recover from. Signed-off-by: Chao Gao Link: https://lore.kernel.org/linux-coco/aQIbM5m09G0FYTzE@google.com/ # [1] --- v10: - Don't add a "dead" TDX_FEATURE0 bit [Sashiko] - s/BIT/BIT_ULL --- arch/x86/include/asm/tdx.h | 5 +++-- arch/x86/virt/vmx/tdx/tdx.c | 30 ++++++++++++++++++++++++--- drivers/virt/coco/tdx-host/tdx-host.c | 2 ++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 5d750fe53669..282cb0e08b8e 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -29,8 +29,9 @@ /* * TDX module SEAMCALL leaf function error codes */ -#define TDX_SUCCESS 0ULL -#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL +#define TDX_SUCCESS 0ULL +#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL +#define TDX_UPDATE_COMPAT_SENSITIVE 0x8000051200000000ULL =20 /* Bit definitions of TDX_FEATURES0 metadata field */ #define TDX_FEATURES0_NO_RBP_MOD BIT_ULL(18) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 55670365a388..0c5660c9ab45 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1274,11 +1274,14 @@ static __init int tdx_enable(void) } subsys_initcall(tdx_enable); =20 +#define TDX_SYS_SHUTDOWN_AVOID_COMPAT_SENSITIVE BIT_ULL(16) + int tdx_module_shutdown(void) { struct tdx_sys_info_handoff handoff =3D {}; struct tdx_module_args args =3D {}; int ret, cpu; + u64 err; =20 ret =3D get_tdx_sys_info_handoff(&handoff); WARN_ON_ONCE(ret); @@ -1288,9 +1291,30 @@ int tdx_module_shutdown(void) * module can produce and most likely supported by newer modules. */ args.rcx =3D handoff.module_hv; - ret =3D seamcall_prerr(TDH_SYS_SHUTDOWN, &args); - if (ret) - return ret; + + /* + * This flag tells the TDX module to reject shutdown if it races + * with a "sensitive" ongoing operation. That eliminates exposure + * to a TDX erratum which can corrupt TDX guest states. + * + * This flag is not supported by all TDX modules and may cause + * the shutdown (and subsequent update procedure) to fail. + */ + args.rcx |=3D TDX_SYS_SHUTDOWN_AVOID_COMPAT_SENSITIVE; + + err =3D seamcall(TDH_SYS_SHUTDOWN, &args); + + /* + * The shutdown ran into a "sensitive" ongoing operation. Signal + * to userspace that it can retry. + */ + if ((err & TDX_SEAMCALL_STATUS_MASK) =3D=3D TDX_UPDATE_COMPAT_SENSITIVE) + return -EBUSY; + + if (err) { + seamcall_err(TDH_SYS_SHUTDOWN, err, &args); + return -EIO; + } =20 /* * Clear global and per-CPU initialization flags so the new module diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index b32ab595047f..291464490fe0 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -145,6 +145,8 @@ static enum fw_upload_err tdx_fw_write(struct fw_upload= *fwl, const u8 *data, case 0: *written =3D data_len; return FW_UPLOAD_ERR_NONE; + case -EBUSY: + return FW_UPLOAD_ERR_BUSY; default: return FW_UPLOAD_ERR_FW_INVALID; } --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C1ECD2E3397; Wed, 20 May 2026 13:40:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284437; cv=none; b=MefWFG3uEIwzh5CpZUA5LR69ciLeqzYuNAnBH64UApbvpGoCYdnJpd86XaUvyex3zp4nnSW49v2kVsvSvMmI7brZHPs1Q/IlAyKErPDG9Um7g2rJuuQ8ZCh/1IQunysJiC6f1T9r6nW/uOWyZIAe3ZjkhrFJDa5hVFDI75nctkw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284437; c=relaxed/simple; bh=NKjcSYXRbvLTovLssfzj1NQJ+Uo5FfLtMzRr4pePg8w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TzYER/KqnRo7zyVfY60jtlMUJZUaX24zK1KcK9pL9fta4y8HrD3Fmkj5A1G7oA6goNDkJfIvTzPJiaabyiYemlN5+Bkh4xlj12wiCOt1ks2pIgP3f3D6wRDtaWMFnf5YPz95SHqws3ugxK9hug43w7k7gLu4gByaRVRphX770TY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=PAbA1OC0; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="PAbA1OC0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284436; x=1810820436; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=NKjcSYXRbvLTovLssfzj1NQJ+Uo5FfLtMzRr4pePg8w=; b=PAbA1OC0Oo/ax67MC9j4/g8NDCZytsBhds/KV0gS4jhdIQ8FSkBxYSUu PGj6G72bhlrNrEok5au18iPc8i0OA/x883iz2JsjAgmH8ch99M2zkzhMY UKynxBDhCwy+CbI/IAxKvY+vYdeuYnXmUewdanZgIq/wEoEy450MqqdN4 GskiX5ntzlN6TrawmwaTirlx2Fd81ltY0n5hO5yPQqnaOgAQXFm1k60hX rR8nqRbFqSAWD0BiP6aBn1s+Ysev0wIYlo9t4MaN24AiHW/EZbqnCgv/3 UoXHaDwSR9cOBY4XYA47tI+6yQGUX3eGSz3hHn/CRszcoTbwak/P5iZH5 w==; X-CSE-ConnectionGUID: jjr/Zy/7S+q7fNyz2ZM+QQ== X-CSE-MsgGUID: XXG2/hUdT9ObL6J/BrSujg== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146655" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146655" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:36 -0700 X-CSE-ConnectionGUID: ITYUc7h9Q1CJT03wVv5gaQ== X-CSE-MsgGUID: HvAYQfPUQQ+r6RIp3MPTHQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235924045" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:35 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" Subject: [PATCH v10 23/25] x86/virt/tdx: Enable TDX module runtime updates Date: Wed, 20 May 2026 06:38:26 -0700 Message-ID: <20260520133909.409394-24-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" All pieces of TDX module runtime updates are in place. Enable it if it is supported. Signed-off-by: Chao Gao Reviewed-by: Xu Yilun Reviewed-by: Tony Lindgren Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Rick Edgecombe --- arch/x86/include/asm/tdx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 282cb0e08b8e..c848483d815f 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -34,6 +34,7 @@ #define TDX_UPDATE_COMPAT_SENSITIVE 0x8000051200000000ULL =20 /* Bit definitions of TDX_FEATURES0 metadata field */ +#define TDX_FEATURES0_TD_PRESERVING BIT_ULL(1) #define TDX_FEATURES0_NO_RBP_MOD BIT_ULL(18) =20 #ifndef __ASSEMBLER__ @@ -114,8 +115,7 @@ const struct tdx_sys_info *tdx_get_sysinfo(void); =20 static inline bool tdx_supports_runtime_update(const struct tdx_sys_info *= sysinfo) { - /* To be enabled when kernel is ready. */ - return false; + return sysinfo->features.tdx_features0 & TDX_FEATURES0_TD_PRESERVING; } =20 int tdx_guest_keyid_alloc(void); --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A96893F0A98; Wed, 20 May 2026 13:40:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284442; cv=none; b=HI35n+a/4K4pGuoMjefV2IvNsKtpN78tEliKP4wgs7jkRLPBaDTgHLlaVRSPCNemedeLnqaVTOZXTqztfBVdXxJ81o5W5JOvFPA+yh52XEqJiplBhIG7XZE/dpPvrN50M4LztnUBj8cjhq1h5rKUCvBi4Pt9H63uW64hwf8dLHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284442; c=relaxed/simple; bh=A2JgB4DHHopxCwX7Y7WmXKD8JTPjRRUlFhYez/KTiCQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KD+2Gm9T7qOXFg6oPLTHM4j20017i3r+eSHRcKKknM7/SbpNF2BCKfx/B1lGosQEztudPAB5Z2rO+wNf93r8Jpy0dv9wZAfd371z4wZXLoIpjDBUDg/nedjwt7IuwFYbZvbFDFuZhYxJ3qgeHBc8QE/ZDwcNEzoIkZmanIUMHIg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=NWYn1uwN; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="NWYn1uwN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284437; x=1810820437; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=A2JgB4DHHopxCwX7Y7WmXKD8JTPjRRUlFhYez/KTiCQ=; b=NWYn1uwNGyp6rNSkHryOUmdVWkt/8XOkEhq/NYHLC/V8vOkpM0jddGow /q+9Zccn4aSpTwq/GHPMEON/MvKknepUpltqLFC9N3bJKi4Kwz0Orx709 a19UGDVXC0ShBhJesMchymKUiZfBF4ti1Dz1JI+M5v3Wfu261uQ7v92Dp VlSQboTIwpvACuzfvoKIA7RbsIMAsiagw5FKKcqyzGgPzCzdnYu32re+6 4RslFaWp80rj/0SstAfEp56uMdBlUe1/U+DSwltI4cElO0YTnZ1+PAK3E s9nc65icDYNTNFqDjlbQAuJXto86K5qwuIlQVRRPGEt/MREtUgI8GxHLJ A==; X-CSE-ConnectionGUID: ijb80/rrQIKJne85ITyRBg== X-CSE-MsgGUID: Ss0oo2o0T3aQFpUmxtwAzg== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146666" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146666" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:37 -0700 X-CSE-ConnectionGUID: TGM1ThbJQqedZXv1X1Oxrg== X-CSE-MsgGUID: ySTuf/V8TzaL6WySQc86ZQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235924053" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:36 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, x86@kernel.org, linux-kernel@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Dan Williams Subject: [PATCH v10 24/25] coco/tdx-host: Document TDX module update compatibility criteria Date: Wed, 20 May 2026 06:38:27 -0700 Message-ID: <20260520133909.409394-25-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The TDX module update protocol facilitates compatible runtime updates. Document the compatibility criteria and indicators of update failures. Note that runtime TDX module updates are an "update at your own risk" operation; userspace is responsible for ensuring that the update meets the compatibility criteria. Signed-off-by: Chao Gao Reviewed-by: Dan Williams Reviewed-by: Kiryl Shutsemau (Meta) --- v9: - Reword the update error descriptions. --- .../ABI/testing/sysfs-devices-faux-tdx-host | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host b/Docume= ntation/ABI/testing/sysfs-devices-faux-tdx-host index 69b4cfc99d87..5f18ac972468 100644 --- a/Documentation/ABI/testing/sysfs-devices-faux-tdx-host +++ b/Documentation/ABI/testing/sysfs-devices-faux-tdx-host @@ -24,3 +24,43 @@ Description: (RO) Report the number of remaining updates= . TDX maintains a See Intel=C2=AE Trust Domain Extensions - SEAM Loader (SEAMLDR) Interface Specification, Chapter "SEAMLDR_INFO" and Chapter "SEAMLDR.INSTALL" for more information. + +What: /sys/devices/faux/tdx_host/firmware/tdx_module +Contact: linux-coco@lists.linux.dev +Description: (Directory) The tdx_module directory implements the fw_upload + sysfs ABI, see Documentation/ABI/testing/sysfs-class-firmware + for the general description of the attributes @data, @cancel, + @error, @loading, @remaining_size, and @status. This ABI + facilitates "Compatible TDX module Updates". A compatible update + is one that meets the following criteria: + + Does not interrupt or interfere with any current TDX + operation or TD VM. + + Does not invalidate any previously consumed module metadata + values outside of the TEE_TCB_SVN_2 field (updated Security + Version Number) in TD Quotes. + + Does not require validation of new module metadata fields. By + implication, new module features and capabilities are only + available by installing the module at reboot (BIOS or EFI + helper loaded). + + See tdx_host/firmware/tdx_module/error for information on + update failure indicators. + +What: /sys/devices/faux/tdx_host/firmware/tdx_module/error +Contact: linux-coco@lists.linux.dev +Description: (RO) See Documentation/ABI/testing/sysfs-class-firmware for + baseline expectations for this file. The part in the + : format can be: + + "device-busy": The update conflicted with an ongoing + compatibility-sensitive operation. + + "firmware-invalid": The update failed for any other reason. + + "firmware-invalid" may be fatal, causing all TDs and the TDX + module to be lost and preventing further TDX operations. This + occurs when reading /sys/devices/faux/tdx_host/version returns + -ENXIO. --=20 2.52.0 From nobody Sun May 24 23:28:57 2026 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A13A03F1ABC; Wed, 20 May 2026 13:40:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.19 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284442; cv=none; b=f0j+lBU/cHRQ9cZ13YTcUZNEoLxy2g8b6woDSxdplzgPAG7sHnkomX+s/KUENYYnr1+dHDGv2exwkEG7z5sZngU6EMDUWckywUiJWtgGge93E1fNavh6We2/sm0bpP5RcoJTB/KpZb/PyOqbiQjKFXOoXy/BT9UiwIFhv5ykdMY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779284442; c=relaxed/simple; bh=g7DBKzISsVeAPEr5fRf6vFci06L9JPnHLfj1n6CF7wg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iFnVuEanIScXCD1OOW8xOCqmw5mFsfwjEdM+Lile+tLhslE5HKsbUeiriV3E3vK92Pgb4KeqOsnOCndQahaKSEdOS428aXGA2/s3xToUMnxHh14EMTNK0WOORO4wuNGVKS+NjwPDH92+hBkjOXicGbH5yaRk5g9/brnsZVKSB+s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=CS22Quc4; arc=none smtp.client-ip=198.175.65.19 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="CS22Quc4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779284438; x=1810820438; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=g7DBKzISsVeAPEr5fRf6vFci06L9JPnHLfj1n6CF7wg=; b=CS22Quc4VwmvZlXrV95N2sSD1CeF8wV5mrb7F6ylyKdxbnxh1+R2xtn5 JEa4v4Cfa9u/HUP4ek0uEVi5+Qz/VFXDR7Hjvvy1Ho0VIu34Ltni77Vk+ mdIYGcAbA8CQepOtGGiqwS8MAV8QdutxZtznwsEUO9ZdLKq9P9TCNeTcO nSglj3dHft2jPIOJ0aXCt75FZ4GIcj2xXJQmVI8ky8Zmc+/ajrbJH/zcH jJa+zyLBEr0O2v68Cb1a+Da0xmFwlWHrn2oMMiF64sYevDCVLOXiNglo2 8a+q95zD+21usyg5Qf89PicZJhLXag3wB6hdBjvxjW4sAzVJrtwDooBfD w==; X-CSE-ConnectionGUID: 4pXlbu0fRomlnumLAkoUDQ== X-CSE-MsgGUID: oe814QsnSEGTS+JAdyN40A== X-IronPort-AV: E=McAfee;i="6800,10657,11792"; a="80146676" X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="80146676" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by orvoesa111.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:38 -0700 X-CSE-ConnectionGUID: Br5tsnbLSS+ReL3/FmNuyg== X-CSE-MsgGUID: 3m2xUakcTpifgy+YxDwPOg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.23,244,1770624000"; d="scan'208";a="235924061" Received: from 984fee019967.jf.intel.com ([10.23.153.244]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2026 06:40:37 -0700 From: Chao Gao To: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org Cc: binbin.wu@linux.intel.com, dave.hansen@linux.intel.com, djbw@kernel.org, ira.weiny@intel.com, kai.huang@intel.com, kas@kernel.org, nik.borisov@suse.com, paulmck@kernel.org, pbonzini@redhat.com, reinette.chatre@intel.com, rick.p.edgecombe@intel.com, sagis@google.com, seanjc@google.com, tony.lindgren@linux.intel.com, vannapurve@google.com, vishal.l.verma@intel.com, yilun.xu@linux.intel.com, xiaoyao.li@intel.com, yan.y.zhao@intel.com, Chao Gao , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" , Jonathan Corbet , Shuah Khan Subject: [PATCH v10 25/25] x86/virt/tdx: Document TDX module update Date: Wed, 20 May 2026 06:38:28 -0700 Message-ID: <20260520133909.409394-26-chao.gao@intel.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260520133909.409394-1-chao.gao@intel.com> References: <20260520133909.409394-1-chao.gao@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Document TDX module update 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 Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Reviewed-by: Rick Edgecombe --- 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 1a3b5bac1021..9d2b7db166b5 100644 --- a/Documentation/arch/x86/tdx.rst +++ b/Documentation/arch/x86/tdx.rst @@ -73,6 +73,40 @@ initialize:: =20 [..] virt/tdx: TDX-Module initialization failed ... =20 +TDX module Runtime Update +------------------------- + +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. + +If updates failed, running TDs may be killed and further TDX operations may +not be 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/tdx-module-binaries + TDX Interaction to Other Kernel Components ------------------------------------------ =20 --=20 2.52.0