Skip to content

Commit

Permalink
arch: riscv: handle interrupt level for CLIC
Browse files Browse the repository at this point in the history
CLIC supports mintstatus.MIL (RO) and mcause.MPIL (RW) for the current
interrupt level and the previous interrut level before a trap. Each ISR
must execute MRET to set mcause.MPIL back to mintstatus.MIL.

This commit introduces CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION to handle
mcause.MPIL for interrupt preemption in nested ISR, and uses
CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL to ensure ISR always switch out
with MRET.

e.g.
  With CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL=n, a context-switch in
  ISR may skip MRET in this flow:
  IRQ -> _isr_wrapper -> z_riscv_switch() -> retrun to arch_switch()

Signed-off-by: Jimmy Zheng <jimmyzhe@andestech.com>
  • Loading branch information
jimmyzhe committed Sep 23, 2024
1 parent 4cc3134 commit bcf3c28
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 0 deletions.
9 changes: 9 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,18 @@ config RISCV_HAS_PLIC
config RISCV_HAS_CLIC
bool
depends on RISCV_PRIVILEGED
select RISCV_ALWAYS_SWITCH_THROUGH_ECALL if MULTITHREADING
select CLIC_SUPPORT_INTERRUPT_PREEMPTION if !NRFX_CLIC
help
Does the SOC provide support for a Core-Local Interrupt Controller (CLIC).

config CLIC_SUPPORT_INTERRUPT_PREEMPTION
bool
depends on RISCV_HAS_CLIC
help
This option handles interrupt level in ISR to support interrupt
preemption for nested interrupt.

config RISCV_SOC_EXCEPTION_FROM_IRQ
bool
help
Expand Down
13 changes: 13 additions & 0 deletions arch/riscv/core/isr.S
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ SECTION_FUNC(exception.entry, _isr_wrapper)
sr s0, __struct_arch_esf_s0_OFFSET(sp)
get_current_cpu s0

#ifdef CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION
/* Save mcause register */
csrr t0, mcause
sr t0, __struct_arch_esf_mcause_OFFSET(sp)
#endif /* CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION */

/* Save MEPC register */
csrr t0, mepc
sr t0, __struct_arch_esf_mepc_OFFSET(sp)
Expand Down Expand Up @@ -721,6 +727,13 @@ fp_trap_exit:
/* Restore MEPC and MSTATUS registers */
lr t0, __struct_arch_esf_mepc_OFFSET(sp)
lr t2, __struct_arch_esf_mstatus_OFFSET(sp)

#ifdef CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION
/* Restore MCAUSE register for previous interrupt level. */
lr t1, __struct_arch_esf_mcause_OFFSET(sp)
csrw mcause, t1
#endif /* CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION */

csrw mepc, t0
csrw mstatus, t2

Expand Down
4 changes: 4 additions & 0 deletions arch/riscv/core/offsets/offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ GEN_OFFSET_STRUCT(arch_esf, a7);
GEN_OFFSET_STRUCT(arch_esf, mepc);
GEN_OFFSET_STRUCT(arch_esf, mstatus);

#ifdef CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION
GEN_OFFSET_STRUCT(arch_esf, mcause);
#endif /* CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION */

GEN_OFFSET_STRUCT(arch_esf, s0);

#ifdef CONFIG_USERSPACE
Expand Down
5 changes: 5 additions & 0 deletions arch/riscv/core/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
stack_init->soc_context = soc_esf_init;
#endif

#ifdef CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION
/* Clear the previous interrupt level. */
stack_init->mcause = 0;
#endif

thread->callee_saved.sp = (unsigned long)stack_init;

/* where to go when returning from z_riscv_switch() */
Expand Down
4 changes: 4 additions & 0 deletions include/zephyr/arch/riscv/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ struct arch_esf {
unsigned long a7; /* function argument */
#endif /* !CONFIG_RISCV_ISA_RV32E */

#ifdef CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION
unsigned long mcause; /* machine cause register */
#endif /* CONFIG_CLIC_SUPPORT_INTERRUPT_PREEMPTION */

unsigned long mepc; /* machine exception program counter */
unsigned long mstatus; /* machine status register */

Expand Down

0 comments on commit bcf3c28

Please sign in to comment.