diff --git a/include/kernel.h b/include/kernel.h index c5764b14730..35dc1459f2e 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -5553,6 +5553,12 @@ extern void z_init_static_threads(void); * @internal */ extern bool z_is_thread_essential(void); + +#ifdef CONFIG_SMP +void z_smp_thread_init(void *arg, struct k_thread *thread); +void z_smp_thread_swap(void); +#endif + /** * @internal */ diff --git a/kernel/Kconfig b/kernel/Kconfig index 6e3e0792202..5dbb91ccde9 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -785,6 +785,14 @@ config SMP When true, kernel will be built with SMP support, allowing more than one CPU to schedule Zephyr tasks at a time. +config SMP_BOOT_DELAY + bool "Delay booting secondary cores" + depends on SMP + help + By default Zephyr will boot all available CPUs during start up. + Select this option to skip this and allow architecture code boot + secondary CPUs at a later time. + config MP_NUM_CPUS int "Number of CPUs/cores" default 1 diff --git a/kernel/smp.c b/kernel/smp.c index 6e58a7b8964..193897bd36d 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -50,28 +50,43 @@ void z_smp_release_global_lock(struct k_thread *thread) } #if CONFIG_MP_NUM_CPUS > 1 -static FUNC_NORETURN void smp_init_top(void *arg) + +void z_smp_thread_init(void *arg, struct k_thread *thread) { atomic_t *cpu_start_flag = arg; - struct k_thread dummy_thread; /* Wait for the signal to begin scheduling */ while (!atomic_get(cpu_start_flag)) { } - z_dummy_thread_init(&dummy_thread); + z_dummy_thread_init(thread); +} + +void z_smp_thread_swap(void) +{ + z_swap_unlocked(); +} + +#ifndef CONFIG_SMP_BOOT_DELAY +static FUNC_NORETURN void smp_init_top(void *arg) +{ + struct k_thread dummy_thread; + + z_smp_thread_init(arg, &dummy_thread); smp_timer_init(); + z_swap_unlocked(); CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } #endif +#endif void z_smp_init(void) { (void)atomic_clear(&start_flag); -#if defined(CONFIG_SMP) && (CONFIG_MP_NUM_CPUS > 1) +#if CONFIG_MP_NUM_CPUS > 1 && !defined(CONFIG_SMP_BOOT_DELAY) for (int i = 1; i < CONFIG_MP_NUM_CPUS; i++) { arch_start_cpu(i, z_interrupt_stacks[i], CONFIG_ISR_STACK_SIZE, smp_init_top, &start_flag);