riscv: Introduce RISCV_ALWAYS_SWITCH_THROUGH_ECALL

Some early RISC-V SoCs have a problem when an `mret` instruction is used
outside a trap handler.

After the latest Zephyr RISC-V huge rework, the arch_switch code is
indeed calling `mret` when not in handler mode, breaking some early
RISC-V platforms.

Optionally restore the old behavior by adding a new
CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL symbol.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
This commit is contained in:
Carlo Caione 2022-06-30 14:40:52 +02:00 committed by Carles Cufí
commit 7a11d883cc
4 changed files with 27 additions and 2 deletions

View file

@ -278,6 +278,15 @@ is_kernel_syscall:
beq t0, t1, do_irq_offload
#endif
#ifdef CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL
li t1, RV_ECALL_SCHEDULE
bne t0, t1, skip_schedule
lr a0, __z_arch_esf_t_a0_OFFSET(sp)
lr a1, __z_arch_esf_t_a1_OFFSET(sp)
j reschedule
skip_schedule:
#endif
/* default fault code is K_ERR_KERNEL_OOPS */
li a0, 3
j 1f
@ -483,7 +492,7 @@ irq_done:
call z_check_stack_sentinel
#endif
reschedule:
check_reschedule:
/* Get pointer to current thread on this CPU */
lr a1, ___cpu_t_current_OFFSET(s0)
@ -501,6 +510,8 @@ reschedule:
addi sp, sp, 16
beqz a0, no_reschedule
reschedule:
/*
* Perform context switch:
* a0 = new thread