[PATCH v3 10/12] arm64: smp: Pass CPU ID to update_cpu_boot_status()

From: Jinjie Ruan

Date: Wed Jun 24 2026 - 05:29:54 EST


To support CONFIG_HOTPLUG_PARALLEL, the CPU boot status tracking must
be refactored from a single global variable (secondary_data.status)
to a per-CPU tracking structure to prevent multi-core race conditions.

Add a 'cpu' parameter to update_cpu_boot_status() and update all its
callsites to pass the corresponding CPU ID. This allows updating the
boot status at a per-CPU granularity during parallel bringup.

Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
arch/arm64/include/asm/smp.h | 6 +++---
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/kernel/smp.c | 8 ++++----
arch/arm64/mm/context.c | 5 +++--
4 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 10ea4f543069..e2151a01731f 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -122,7 +122,7 @@ static inline void __noreturn cpu_park_loop(void)
}
}

-static inline void update_cpu_boot_status(int val)
+static inline void update_cpu_boot_status(unsigned int cpu, int val)
{
WRITE_ONCE(secondary_data.status, val);
/* Ensure the visibility of the status update */
@@ -134,9 +134,9 @@ static inline void update_cpu_boot_status(int val)
* which calls for a kernel panic. Update the boot status and park the calling
* CPU.
*/
-static inline void __noreturn cpu_panic_kernel(void)
+static inline void __noreturn cpu_panic_kernel(unsigned int cpu)
{
- update_cpu_boot_status(CPU_PANIC_KERNEL);
+ update_cpu_boot_status(cpu, CPU_PANIC_KERNEL);
cpu_park_loop();
}

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index a1a13f3e01ed..abc3aef9c206 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -3685,7 +3685,7 @@ static void verify_local_cpu_caps(u16 scope_mask)
caps->desc, system_has_cap, cpu_has_cap);

if (cpucap_panic_on_conflict(caps))
- cpu_panic_kernel();
+ cpu_panic_kernel(smp_processor_id());
else
cpu_die_early();
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 6b9586a69429..14b94df26b44 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -116,7 +116,7 @@ int arch_cpuhp_kick_ap_alive(unsigned int cpu, struct task_struct *idle)
* page tables.
*/
secondary_data.task = idle;
- update_cpu_boot_status(CPU_MMU_OFF);
+ update_cpu_boot_status(cpu, CPU_MMU_OFF);

/* Now bring the CPU into our world */
ret = boot_secondary(cpu, idle);
@@ -262,7 +262,7 @@ asmlinkage notrace void secondary_start_kernel(void)
pr_info("CPU%u: Booted secondary processor 0x%010lx [0x%08x]\n",
cpu, (unsigned long)mpidr,
read_cpuid_id());
- update_cpu_boot_status(CPU_BOOT_SUCCESS);
+ update_cpu_boot_status(cpu, CPU_BOOT_SUCCESS);
set_cpu_online(cpu, true);

/*
@@ -420,11 +420,11 @@ void __noreturn cpu_die_early(void)
rcutree_report_cpu_dead();

if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
- update_cpu_boot_status(CPU_KILL_ME);
+ update_cpu_boot_status(cpu, CPU_KILL_ME);
__cpu_try_die(cpu);
}

- update_cpu_boot_status(CPU_STUCK_IN_KERNEL);
+ update_cpu_boot_status(cpu, CPU_STUCK_IN_KERNEL);

cpu_park_loop();
}
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 0f4a28b87469..e78ae989ad57 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -63,6 +63,7 @@ static u32 get_cpu_asid_bits(void)
/* Check if the current cpu's ASIDBits is compatible with asid_bits */
void verify_cpu_asid_bits(void)
{
+ unsigned int cpu = smp_processor_id();
u32 asid = get_cpu_asid_bits();

if (asid < asid_bits) {
@@ -71,8 +72,8 @@ void verify_cpu_asid_bits(void)
* fewer ASID bits than the boot CPU.
*/
pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n",
- smp_processor_id(), asid, asid_bits);
- cpu_panic_kernel();
+ cpu, asid, asid_bits);
+ cpu_panic_kernel(cpu);
}
}

--
2.34.1