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 <katsuhiro@katsuster.net>
This commit is contained in:
Katsuhiro Suzuki 2023-11-09 13:50:31 +09:00 committed by Carles Cufí
commit 4ce5f7ebe1
2 changed files with 15 additions and 6 deletions

View file

@ -93,16 +93,24 @@ aa_loop:
boot_secondary_core: boot_secondary_core:
#if CONFIG_MP_MAX_NUM_CPUS > 1 #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 la t0, riscv_cpu_wake_flag
lr t0, 0(t0) lr t0, 0(t0)
bne a0, t0, boot_secondary_core bne a0, t0, wait_secondary_wake_flag
/* Set up stack */ /* Set up stack */
la t0, riscv_cpu_sp la t0, riscv_cpu_sp
lr sp, 0(t0) lr sp, 0(t0)
la t0, riscv_cpu_wake_flag la t0, riscv_cpu_boot_flag
sr zero, 0(t0) li t1, 1
sr t1, 0(t0)
j z_riscv_secondary_cpu_init j z_riscv_secondary_cpu_init
#else #else
j loop_unconfigured_cores j loop_unconfigured_cores

View file

@ -17,6 +17,7 @@ volatile struct {
} riscv_cpu_init[CONFIG_MP_MAX_NUM_CPUS]; } riscv_cpu_init[CONFIG_MP_MAX_NUM_CPUS];
volatile uintptr_t riscv_cpu_wake_flag; volatile uintptr_t riscv_cpu_wake_flag;
volatile uintptr_t riscv_cpu_boot_flag;
volatile void *riscv_cpu_sp; volatile void *riscv_cpu_sp;
extern void __start(void); 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_init[cpu_num].arg = arg;
riscv_cpu_sp = Z_KERNEL_STACK_BUFFER(stack) + sz; 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 #ifdef CONFIG_PM_CPU_OPS
if (pm_cpu_on(cpu_num, (uintptr_t)&__start)) { 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 #endif
while (riscv_cpu_wake_flag != 0U) { while (riscv_cpu_boot_flag == 0U) {
; riscv_cpu_wake_flag = _kernel.cpus[cpu_num].arch.hartid;
} }
} }