Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

RISC-V: Enable HOTPLUG_PARALLEL for secondary CPUs

The core kernel already supports parallel bringup of secondary
CPUs (aka HOTPLUG_PARALLEL). The x86 and MIPS architectures
already use HOTPLUG_PARALLEL and ARM is also moving toward it.

On RISC-V, there is no arch specific global data accessed in the
RISC-V secondary CPU bringup path so enabling HOTPLUG_PARALLEL for
RISC-V would only require:
1) Providing RISC-V specific arch_cpuhp_kick_ap_alive()
2) Calling cpuhp_ap_sync_alive() from smp_callin()

This patch is tested natively with OpenSBI on QEMU RV64 virt machine
with 64 cores and also tested with KVM RISC-V guest with 32 VCPUs.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Link: https://patch.msgid.link/20250905122512.71684-1-apatel@ventanamicro.com
Signed-off-by: Paul Walmsley <pjw@kernel.org>

authored by

Anup Patel and committed by
Paul Walmsley
231fb999 4427259c

+16 -1
+1 -1
arch/riscv/Kconfig
··· 198 198 select HAVE_SAMPLE_FTRACE_DIRECT_MULTI 199 199 select HAVE_STACKPROTECTOR 200 200 select HAVE_SYSCALL_TRACEPOINTS 201 - select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU 201 + select HOTPLUG_PARALLEL if HOTPLUG_CPU 202 202 select IRQ_DOMAIN 203 203 select IRQ_FORCED_THREADING 204 204 select KASAN_VMALLOC if KASAN
+15
arch/riscv/kernel/smpboot.c
··· 39 39 40 40 #include "head.h" 41 41 42 + #ifndef CONFIG_HOTPLUG_PARALLEL 42 43 static DECLARE_COMPLETION(cpu_running); 44 + #endif 43 45 44 46 void __init smp_prepare_cpus(unsigned int max_cpus) 45 47 { ··· 181 179 return -EOPNOTSUPP; 182 180 } 183 181 182 + #ifdef CONFIG_HOTPLUG_PARALLEL 183 + int arch_cpuhp_kick_ap_alive(unsigned int cpu, struct task_struct *tidle) 184 + { 185 + return start_secondary_cpu(cpu, tidle); 186 + } 187 + #else 184 188 int __cpu_up(unsigned int cpu, struct task_struct *tidle) 185 189 { 186 190 int ret = 0; ··· 207 199 208 200 return ret; 209 201 } 202 + #endif 210 203 211 204 void __init smp_cpus_done(unsigned int max_cpus) 212 205 { ··· 234 225 mmgrab(mm); 235 226 current->active_mm = mm; 236 227 228 + #ifdef CONFIG_HOTPLUG_PARALLEL 229 + cpuhp_ap_sync_alive(); 230 + #endif 231 + 237 232 store_cpu_topology(curr_cpuid); 238 233 notify_cpu_starting(curr_cpuid); 239 234 ··· 256 243 */ 257 244 local_flush_icache_all(); 258 245 local_flush_tlb_all(); 246 + #ifndef CONFIG_HOTPLUG_PARALLEL 259 247 complete(&cpu_running); 248 + #endif 260 249 /* 261 250 * Disable preemption before enabling interrupts, so we don't try to 262 251 * schedule a CPU that hasn't actually started yet.