From 4ce5f7ebe118e466d7d69f9a09c22c2d82d08ae2 Mon Sep 17 00:00:00 2001 From: Katsuhiro Suzuki Date: Thu, 9 Nov 2023 13:50:31 +0900 Subject: [PATCH] arch: riscv: fix hangup of multicore boot This patch fixes hangup of RISC-V multicore boot. Currently boot sequence uses a riscv_cpu_wake_flag to notify wakeup request for secondary core(s). But initial value of riscv_cpu_wake_flag is undefined, so current mechanism is going to hangup if riscv_cpu_wake_flag and mhartid of secondary core have the same value. This is an example situation of this problem: - hart1: check riscv_cpu_wake_flag (value is 1) and end the loop - hart1: set riscv_cpu_wake_flag to 0 - hart0: set riscv_cpu_wake_flag to 1 hart0 expects it will be changed to 0 by hart1 but it has never happened Note: - hart0's mhartid is 0, hart1's mhartid is 1 - hart0 is main, hart1 is secondary in this example Signed-off-by: Katsuhiro Suzuki --- arch/riscv/core/reset.S | 14 +++++++++++--- arch/riscv/core/smp.c | 7 ++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/arch/riscv/core/reset.S b/arch/riscv/core/reset.S index 094e51b9183..e2faa6fe94d 100644 --- a/arch/riscv/core/reset.S +++ b/arch/riscv/core/reset.S @@ -93,16 +93,24 @@ aa_loop: boot_secondary_core: #if CONFIG_MP_MAX_NUM_CPUS > 1 + la t0, riscv_cpu_wake_flag + li t1, -1 + sr t1, 0(t0) + la t0, riscv_cpu_boot_flag + sr zero, 0(t0) + +wait_secondary_wake_flag: la t0, riscv_cpu_wake_flag lr t0, 0(t0) - bne a0, t0, boot_secondary_core + bne a0, t0, wait_secondary_wake_flag /* Set up stack */ la t0, riscv_cpu_sp lr sp, 0(t0) - la t0, riscv_cpu_wake_flag - sr zero, 0(t0) + la t0, riscv_cpu_boot_flag + li t1, 1 + sr t1, 0(t0) j z_riscv_secondary_cpu_init #else j loop_unconfigured_cores diff --git a/arch/riscv/core/smp.c b/arch/riscv/core/smp.c index 7bcfff6828e..a5499d4e16b 100644 --- a/arch/riscv/core/smp.c +++ b/arch/riscv/core/smp.c @@ -17,6 +17,7 @@ volatile struct { } riscv_cpu_init[CONFIG_MP_MAX_NUM_CPUS]; volatile uintptr_t riscv_cpu_wake_flag; +volatile uintptr_t riscv_cpu_boot_flag; volatile void *riscv_cpu_sp; extern void __start(void); @@ -28,7 +29,7 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, riscv_cpu_init[cpu_num].arg = arg; riscv_cpu_sp = Z_KERNEL_STACK_BUFFER(stack) + sz; - riscv_cpu_wake_flag = _kernel.cpus[cpu_num].arch.hartid; + riscv_cpu_boot_flag = 0U; #ifdef CONFIG_PM_CPU_OPS if (pm_cpu_on(cpu_num, (uintptr_t)&__start)) { @@ -37,8 +38,8 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, } #endif - while (riscv_cpu_wake_flag != 0U) { - ; + while (riscv_cpu_boot_flag == 0U) { + riscv_cpu_wake_flag = _kernel.cpus[cpu_num].arch.hartid; } }