After shutting down the running TDX module, the next step is to install the new TDX Module supplied by userspace. P-SEAMLDR provides the SEAMLDR.INSTALL SEAMCALL for that. The SEAMCALL accepts the seamldr_params struct and should be called serially on all CPUs. Invoke the SEAMLDR.INSTALL SEAMCALL serially on all CPUs and add a new spinlock to enforce serialization. Signed-off-by: Chao Gao Tested-by: Farrah Chen --- arch/x86/virt/vmx/tdx/seamldr.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c index b497fa72ebb6..13c34e6378e0 100644 --- a/arch/x86/virt/vmx/tdx/seamldr.c +++ b/arch/x86/virt/vmx/tdx/seamldr.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,7 @@ /* P-SEAMLDR SEAMCALL leaf function */ #define P_SEAMLDR_INFO 0x8000000000000000 +#define P_SEAMLDR_INSTALL 0x8000000000000001 /* P-SEAMLDR can accept up to 496 4KB pages for TDX module binary */ #define SEAMLDR_MAX_NR_MODULE_4KB_PAGES 496 @@ -45,6 +47,7 @@ struct seamldr_params { } __packed; static struct seamldr_info seamldr_info __aligned(256); +static DEFINE_RAW_SPINLOCK(seamldr_lock); static inline int seamldr_call(u64 fn, struct tdx_module_args *args) { @@ -235,6 +238,7 @@ static struct seamldr_params *init_seamldr_params(const u8 *data, u32 size) enum tdp_state { TDP_START, TDP_SHUTDOWN, + TDP_CPU_INSTALL, TDP_DONE, }; @@ -272,9 +276,10 @@ static void print_update_failure_message(void) * See multi_cpu_stop() from where this multi-cpu state-machine was * adopted, and the rationale for touch_nmi_watchdog() */ -static int do_seamldr_install_module(void *params) +static int do_seamldr_install_module(void *seamldr_params) { enum tdp_state newstate, curstate = TDP_START; + struct tdx_module_args args = {}; int cpu = smp_processor_id(); bool primary; int ret = 0; @@ -293,6 +298,11 @@ static int do_seamldr_install_module(void *params) if (primary) ret = tdx_module_shutdown(); break; + case TDP_CPU_INSTALL: + args.rcx = __pa(seamldr_params); + scoped_guard(raw_spinlock, &seamldr_lock) + ret = seamldr_call(P_SEAMLDR_INSTALL, &args); + break; default: break; } -- 2.47.3