From nobody Sun May 24 19:34:22 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 2CFE4368958; Fri, 22 May 2026 17:26:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779470780; cv=none; b=OJFGmR2EotYVl0BlrgxS5WZozvFKweemsyz8gbvNuUlIw0Q+3PyrTui+j47URX5B0IFJgc7gErMOp464tZfNNhsKaPCkl/uO9O+xlZ/3Fr1Wa5HtVw9zQSB4YXCyq0xnRnWazBSTluwWIXwNvbfQ36K26HjC1V+UfltPfG7ickc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779470780; c=relaxed/simple; bh=DdDfpZlo8XwqGmPA4zfNfucnZR6Edc5AI2ye4KtB0tc=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=uZP7jFSzRVGa98dUCHwRumJm5NJjMfW7KDuDBsJUxJ5vHa7bvKMiRb6c7QmbJuLPUg4xAigzFEtD3Lju5KhpSWuSQzKwTlYOkv0vHImLuzv6AcVXy+VJUJumALwNgEntIqGnxj/3QEMmMkuUnl6R8DcXtuY3UP2gKVmcHhINdP4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=kQAJC0VI; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=9O16yHTq; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="kQAJC0VI"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="9O16yHTq" Date: Fri, 22 May 2026 17:26:15 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1779470777; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cz00HsJlaKA4GPYSTHPuKCJk2ZvI+dABEmaZtENc0e4=; b=kQAJC0VI8OCKhrcNZN7L8bDsCLnDG5zErQBl4XtUYGSss9NVPkRKz3Gf1k0vc8qi6Ml73j 7QROJDvVCG587kUa5fIZlJ5gj23jMVZTVEaX3t3Bp4kQSxvNva91GAfkmdtTxENIXo+pbH qku83UHZ8yDFSS5XJw+5IkZHNvgme1ZLn4F6zpanB5h4UWiQFcC2nNbBObM8CfIJINIByj fY4gJrPdDnvmyME14PFp2bxBJ9FFmgPkG5Dg3243BKtazFH6e2AuoUL6UbBIteFMmBeiXI Z+L5cac+Gn7HGOfae33CNKdDZ5c3nDzlmZya+Cy/znHFL1/wDaoHMqAF23UaYQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1779470777; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cz00HsJlaKA4GPYSTHPuKCJk2ZvI+dABEmaZtENc0e4=; b=9O16yHTqFt4ECvIlBuKHTSF1yvHVb/VroF5U4PeQWQQADEOoT7InIbZ9P8GacMSJBIMjk2 WekyrP6gIP9I/3AQ== From: "tip-bot2 for Chao Gao" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/tdx] x86/virt/seamldr: Shut down the current TDX module Cc: Chao Gao , Dave Hansen , Tony Lindgren , Xu Yilun , Kai Huang , "Kiryl Shutsemau (Meta)" , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260520222905.44E5B004@davehans-spike.ostc.intel.com> References: <20260520222905.44E5B004@davehans-spike.ostc.intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <177947077591.711.1344496464222353260.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the x86/tdx branch of tip: Commit-ID: 146ac22b2b9665b62e54abba8f2c5a2e1ceeadfe Gitweb: https://git.kernel.org/tip/146ac22b2b9665b62e54abba8f2c5a2e1= ceeadfe Author: Chao Gao AuthorDate: Wed, 20 May 2026 15:29:05 -07:00 Committer: Dave Hansen CommitterDate: Wed, 20 May 2026 15:37:10 -07:00 x86/virt/seamldr: Shut down the current TDX module 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 the 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 Trust Domain Extensions (Intel 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. [ dhansen: fix up function variables, revmove 'cpu'. Return from tdx_module_shutdown() early if handoff call fails. ] Signed-off-by: Chao Gao Signed-off-by: Dave Hansen Reviewed-by: Tony Lindgren Reviewed-by: Xu Yilun Reviewed-by: Kai Huang Reviewed-by: Kiryl Shutsemau (Meta) Link: https://patch.msgid.link/20260520133909.409394-17-chao.gao@intel.com Link: https://patch.msgid.link/20260520222905.44E5B004@davehans-spike.ostc.= intel.com --- arch/x86/include/asm/tdx_global_metadata.h | 4 +++- arch/x86/virt/vmx/tdx/seamldr.c | 15 +++++++++++- arch/x86/virt/vmx/tdx/tdx.c | 25 +++++++++++++++++++- arch/x86/virt/vmx/tdx/tdx.h | 3 ++- arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 13 ++++++++++- 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/tdx_global_metadata.h b/arch/x86/include/= asm/tdx_global_metadata.h index 40689c8..41150d5 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 b03dce2..3fe1d39 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -18,6 +18,7 @@ #include =20 #include "seamcall_internal.h" +#include "tdx.h" =20 /* P-SEAMLDR SEAMCALL leaf function */ #define P_SEAMLDR_INFO 0x8000000000000000 @@ -196,6 +197,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 @@ -247,8 +249,16 @@ static int do_seamldr_install_module(void *seamldr_par= ams) { enum module_update_state curstate =3D MODULE_UPDATE_START; enum module_update_state newstate; + bool is_lead_cpu =3D false; 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. + */ + if (smp_processor_id() =3D=3D 0) + is_lead_cpu =3D true; + do { newstate =3D READ_ONCE(update_ctrl.state); =20 @@ -259,7 +269,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 53cf99c..3fe01b5 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -328,7 +328,7 @@ err: 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,29 @@ 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); + /* + * Handoff information is required for proper + * shutdown. Refuse to shut down without it. + */ + if (ret) + return 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 76c5fb1..f0c20de 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 d54d422..e793dec 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;