[PATCH v3 06/12] arm64: smp: Use generic HOTPLUG_SPLIT_STARTUP machinery for CPU onlining
From: Jinjie Ruan <hidden>
Date: 2026-06-24 09:26:23
Also in:
linux-mips, lkml
Subsystem:
arm64 port (aarch64 architecture), the rest · Maintainers:
Catalin Marinas, Will Deacon, Linus Torvalds
From: Will Deacon <will@kernel.org> In preparation for enabling parallel bringup of secondary CPUs on arm64, take the baby step of moving from HOTPLUG_CORE_SYNC_DEAD to HOTPLUG_SPLIT_STARTUP. To fully enable HOTPLUG_SPLIT_STARTUP, this patch implements: 1) arch_cpuhp_kick_ap_alive(). Kick the secondary CPU via firmware without blocking. 2) arch_cpuhp_cleanup_kick_cpu(). Extracts early boot telemetry upon AP bringup timeouts. 3) Callbacks to cpuhp_ap_sync_alive() inside secondary_start_kernel(). Enforces the initial pre-online boot handshake from the secondary CPU side. Signed-off-by: Will Deacon <will@kernel.org> Signed-off-by: Jinjie Ruan <redacted> --- arch/arm64/Kconfig | 2 +- arch/arm64/kernel/smp.c | 39 +++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index fe60738e5943..24496e9967a8 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig@@ -231,7 +231,7 @@ config ARM64 select HAVE_KPROBES select HAVE_KRETPROBES select HAVE_GENERIC_VDSO - select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU + select HOTPLUG_SPLIT_STARTUP if SMP select HOTPLUG_SMT if HOTPLUG_CPU select IRQ_DOMAIN select IRQ_FORCED_THREADING
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 87f92cf9ffa8..9482e8d38b98 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c@@ -107,12 +107,9 @@ static int boot_secondary(unsigned int cpu, struct task_struct *idle) return -EOPNOTSUPP; } -static DECLARE_COMPLETION(cpu_running); - -int __cpu_up(unsigned int cpu, struct task_struct *idle) +int arch_cpuhp_kick_ap_alive(unsigned int cpu, struct task_struct *idle) { int ret; - long status; /* * We need to tell the secondary core where to find its stack and the
@@ -123,22 +120,22 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) /* Now bring the CPU into our world */ ret = boot_secondary(cpu, idle); - if (ret) { - if (ret != -EPERM) - pr_err("CPU%u: failed to boot: %d\n", cpu, ret); - return ret; - } + if (ret && ret != -EPERM) + pr_err("CPU%u: failed to boot: %d\n", cpu, ret); + return ret; +} + +void arch_cpuhp_cleanup_kick_cpu(unsigned int cpu, bool is_alive) +{ + long status; + + if (is_alive) + return; /* - * CPU was successfully started, wait for it to come online or - * time out. + * We failed to synchronise with the CPU, so check if it left us + * any breadcrumbs. */ - wait_for_completion_timeout(&cpu_running, - msecs_to_jiffies(5000)); - if (cpu_online(cpu)) - return 0; - - pr_crit("CPU%u: failed to come online\n", cpu); secondary_data.task = NULL; status = READ_ONCE(secondary_data.status); if (status == CPU_MMU_OFF)
@@ -170,8 +167,6 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) case CPU_PANIC_KERNEL: panic("CPU%u detected unsupported configuration\n", cpu); } - - return -EIO; } static void init_gic_priority_masking(void)
@@ -231,6 +226,11 @@ asmlinkage notrace void secondary_start_kernel(void) */ check_local_cpu_capabilities(); lockdep_on(); + /* + * Synchronise with the core bringing us online so that it knows + * we made it into the kernel. We're still not 'online'. + */ + cpuhp_ap_sync_alive(); rcutree_report_cpu_starting(cpu); trace_hardirqs_off_finish();
@@ -264,7 +264,6 @@ asmlinkage notrace void secondary_start_kernel(void) read_cpuid_id()); update_cpu_boot_status(CPU_BOOT_SUCCESS); set_cpu_online(cpu, true); - complete(&cpu_running); /* * Secondary CPUs enter the kernel with all DAIF exceptions masked.
--
2.34.1