From 131bda944704293fa75295060aec96061cdb3749 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Mon, 31 Aug 2026 21:08:17 +0800 Subject: [PATCH] lib: sbi_hsm: Validate state before updating start context sbi_hsm_hart_start() acquires the target hart's start ticket, then writes next_arg1, next_addr and next_mode before checking whether the target is stopped. A start request for a non-retentively suspended hart is rejected, but those writes have already replaced the resume context consumed by sbi_hsm_hart_resume_finish(). The same ordering also lets other rejected start requests modify target scratch state. Check the state immediately after acquiring the start ticket and before updating the scratch context. The ticket serializes start requests for the target; retain the cmpxchg as the publication barrier and defensive state check. Fixes: e8e9ed3790fe ("lib: sbi: Set the state of a hart to START_PENDING after the hart is ready") Signed-off-by: Pengpeng Hou Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20260831130817.54625-1-pengpeng@iscas.ac.cn Signed-off-by: Anup Patel --- lib/sbi/sbi_hsm.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c index 0a355f9c..0e5498d7 100644 --- a/lib/sbi/sbi_hsm.c +++ b/lib/sbi/sbi_hsm.c @@ -332,6 +332,16 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch, if (!hsm_start_ticket_acquire(hdata)) return SBI_EINVAL; + /* + * Ensure target hart is in correct state before updating + * next_arg1, next_addr, and next_mode in target hart scratch. + */ + hstate = atomic_read(&hdata->state); + if (hstate != SBI_HSM_STATE_STOPPED) { + rc = hstate == SBI_HSM_STATE_STARTED ? SBI_EALREADY : SBI_EINVAL; + goto err; + } + init_count = sbi_init_count(hartindex); entry_count = sbi_entry_count(hartindex); @@ -346,17 +356,8 @@ int sbi_hsm_hart_start(struct sbi_scratch *scratch, */ hstate = atomic_cmpxchg(&hdata->state, SBI_HSM_STATE_STOPPED, SBI_HSM_STATE_START_PENDING); - if (hstate == SBI_HSM_STATE_STARTED) { - rc = SBI_EALREADY; - goto err; - } - - /** - * if a hart is already transition to start or stop, another start call - * is considered as invalid request. - */ if (hstate != SBI_HSM_STATE_STOPPED) { - rc = SBI_EINVAL; + rc = hstate == SBI_HSM_STATE_STARTED ? SBI_EALREADY : SBI_EINVAL; goto err; }