From d9ab35577bef5d1905721d6ae52db4a03b57303f Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Wed, 29 Dec 2021 10:22:48 -0800 Subject: [PATCH] arch/riscv: Boot secondary CPUs for SMP support Secondary CPUs are now initialised and made available to the system. If the system has more CPUs than configured via CONFIG_MP_NUM_CPUS, those are still left looping as before. Some implementations of `soc_interrupt_init` also changed to use `arch_irq_lock` instead of `irq_lock`. Signed-off-by: Ederson de Souza --- arch/riscv/core/CMakeLists.txt | 1 + arch/riscv/core/reset.S | 31 ++++++++++---- arch/riscv/core/smp.c | 40 +++++++++++++++++++ .../riscv-privilege/common/soc_common_irq.c | 2 +- soc/riscv/riscv-privilege/neorv32/soc.c | 2 +- 5 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 arch/riscv/core/smp.c diff --git a/arch/riscv/core/CMakeLists.txt b/arch/riscv/core/CMakeLists.txt index da3982c550b..2b7c884f59e 100644 --- a/arch/riscv/core/CMakeLists.txt +++ b/arch/riscv/core/CMakeLists.txt @@ -13,6 +13,7 @@ zephyr_library_sources( reboot.c reset.S switch.S + smp.c thread.c ) diff --git a/arch/riscv/core/reset.S b/arch/riscv/core/reset.S index da43d852cfa..2a99bfc706b 100644 --- a/arch/riscv/core/reset.S +++ b/arch/riscv/core/reset.S @@ -15,6 +15,9 @@ GTEXT(__reset) /* imports */ GTEXT(_PrepC) +GTEXT(riscv_cpu_wake_flag) +GTEXT(riscv_cpu_sp) +GTEXT(z_riscv_secondary_cpu_init) #if CONFIG_INCLUDE_RESET_VECTOR SECTION_FUNC(reset, __reset) @@ -33,18 +36,17 @@ SECTION_FUNC(reset, __reset) * the C domain */ SECTION_FUNC(TEXT, __initialize) - /* - * This will boot master core, just halt other cores. - * Note: need to be updated for complete SMP support - */ csrr a0, mhartid - beqz a0, boot_master_core + beqz a0, boot_first_core -loop_slave_core: + li t0, CONFIG_MP_NUM_CPUS + blt a0, t0, boot_secondary_core + +loop_unconfigured_cores: wfi - j loop_slave_core + j loop_unconfigured_cores -boot_master_core: +boot_first_core: #ifdef CONFIG_FPU /* @@ -93,3 +95,16 @@ aa_loop: * and then enters kernel z_cstart */ call _PrepC + +boot_secondary_core: + la t0, riscv_cpu_wake_flag + RV_OP_LOADREG t0, 0x00(t0) + bne a0, t0, boot_secondary_core + + /* Set up stack */ + la t0, riscv_cpu_sp + RV_OP_LOADREG sp, 0x00(t0) + + la t0, riscv_cpu_wake_flag + RV_OP_STOREREG x0, 0x00(t0) + j z_riscv_secondary_cpu_init diff --git a/arch/riscv/core/smp.c b/arch/riscv/core/smp.c new file mode 100644 index 00000000000..ded7102c85b --- /dev/null +++ b/arch/riscv/core/smp.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +volatile struct { + arch_cpustart_t fn; + void *arg; +} riscv_cpu_init[CONFIG_MP_NUM_CPUS]; + +volatile uintptr_t riscv_cpu_wake_flag; +volatile void *riscv_cpu_sp; + +void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, + arch_cpustart_t fn, void *arg) +{ + riscv_cpu_init[cpu_num].fn = fn; + riscv_cpu_init[cpu_num].arg = arg; + + riscv_cpu_sp = Z_THREAD_STACK_BUFFER(stack) + sz; + riscv_cpu_wake_flag = cpu_num; + + while (riscv_cpu_wake_flag != 0U) { + ; + } +} + +void z_riscv_secondary_cpu_init(int cpu_num) +{ +#if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT) + soc_interrupt_init(); +#endif +#ifdef CONFIG_PMP_STACK_GUARD + z_riscv_configure_interrupt_stack_guard(); +#endif + riscv_cpu_init[cpu_num].fn(riscv_cpu_init[cpu_num].arg); +} diff --git a/soc/riscv/riscv-privilege/common/soc_common_irq.c b/soc/riscv/riscv-privilege/common/soc_common_irq.c index e79d01622db..03ac8dcda20 100644 --- a/soc/riscv/riscv-privilege/common/soc_common_irq.c +++ b/soc/riscv/riscv-privilege/common/soc_common_irq.c @@ -107,7 +107,7 @@ int arch_irq_is_enabled(unsigned int irq) __weak void soc_interrupt_init(void) { /* ensure that all interrupts are disabled */ - (void)irq_lock(); + (void)arch_irq_lock(); __asm__ volatile ("csrwi mie, 0\n" "csrwi mip, 0\n"); diff --git a/soc/riscv/riscv-privilege/neorv32/soc.c b/soc/riscv/riscv-privilege/neorv32/soc.c index fa629bfbb52..8953fb62d5a 100644 --- a/soc/riscv/riscv-privilege/neorv32/soc.c +++ b/soc/riscv/riscv-privilege/neorv32/soc.c @@ -10,7 +10,7 @@ #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT) void soc_interrupt_init(void) { - (void)irq_lock(); + (void)arch_irq_lock(); __asm__ volatile ("csrwi mie, 0\n"); }