[PATCH v5 10/22] x86/virt/seamldr: Abort updates if errors occurred midway

From: Chao Gao

Date: Sun Mar 15 2026 - 10:05:27 EST


The TDX module update process has multiple steps, each of which may
encounter failures.

The current state machine of updates proceeds to the next step regardless
of errors. But continuing updates when errors occur midway is pointless.

Abort the update by setting a flag to indicate that a CPU has encountered
an error, forcing all CPUs to exit the execution loop. Note that failing
CPUs do not acknowledge the current step. This keeps all other CPUs waiting
in the current step (since advancing to the next step requires all CPUs to
acknowledge the current step) until they detect the fault flag and exit the
loop.

Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx>
Reviewed-by: Xu Yilun <yilun.xu@xxxxxxxxxxxxxxx>
Reviewed-by: Tony Lindgren <tony.lindgren@xxxxxxxxxxxxxxx>
Reviewed-by: Kai Huang <kai.huang@xxxxxxxxx>
---
v5:
- Replace failed count from atomic_t to int since it's now protected by
a lock.

v3:
- Instead of fast-forward to the final stage, exit the execution loop
directly.
---
arch/x86/virt/vmx/tdx/seamldr.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/x86/virt/vmx/tdx/seamldr.c b/arch/x86/virt/vmx/tdx/seamldr.c
index 978fcca92128..e195703398e7 100644
--- a/arch/x86/virt/vmx/tdx/seamldr.c
+++ b/arch/x86/virt/vmx/tdx/seamldr.c
@@ -190,6 +190,7 @@ enum module_update_state {
static struct {
enum module_update_state state;
int thread_ack;
+ int failed;
/*
* Protect update_data. Raw spinlock as it will be acquired from
* interrupt-disabled contexts.
@@ -237,12 +238,17 @@ static int do_seamldr_install_module(void *seamldr_params)
break;
}

- ack_state();
+ if (ret) {
+ scoped_guard(raw_spinlock, &update_data.lock)
+ update_data.failed++;
+ } else {
+ ack_state();
+ }
} else {
touch_nmi_watchdog();
rcu_momentary_eqs();
}
- } while (curstate != MODULE_UPDATE_DONE);
+ } while (curstate != MODULE_UPDATE_DONE && !READ_ONCE(update_data.failed));

return ret;
}
@@ -264,6 +270,7 @@ int seamldr_install_module(const u8 *data, u32 size)
if (IS_ERR(params))
return PTR_ERR(params);

+ update_data.failed = 0;
set_target_state(MODULE_UPDATE_START + 1);
return stop_machine(do_seamldr_install_module, params, cpu_online_mask);
}
--
2.47.3