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.
Save mcause.MPIL for nested interrupt, and use
CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL to ensure ISR doesn't switch out
without 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 Jul 11, 2024
1 parent dcfc3e7 commit e23074a
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 2 deletions.
1 change: 1 addition & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ config RISCV_HAS_PLIC
config RISCV_HAS_CLIC
bool
depends on RISCV_PRIVILEGED
select RISCV_ALWAYS_SWITCH_THROUGH_ECALL if MULTITHREADING
help
Does the SOC provide support for a Core-Local Interrupt Controller (CLIC).

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_RISCV_HAS_CLIC
/* Save mcause register */
csrr t0, mcause
sr t0, __struct_arch_esf_mcause_OFFSET(sp)
#endif /* CONFIG_RISCV_HAS_CLIC */

/* Save MEPC register */
csrr t0, mepc
sr t0, __struct_arch_esf_mepc_OFFSET(sp)
Expand Down Expand Up @@ -685,6 +691,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_RISCV_HAS_CLIC
/* Restore MCAUSE register for previous interrupt level. */
lr t1, __struct_arch_esf_mcause_OFFSET(sp)
csrw mcause, t1
#endif /* CONFIG_RISCV_HAS_CLIC */

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_RISCV_HAS_CLIC
GEN_OFFSET_STRUCT(arch_esf, mcause);
#endif /* CONFIG_RISCV_HAS_CLIC */

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_RISCV_HAS_CLIC
/* 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 @@ -72,6 +72,10 @@ struct arch_esf {
unsigned long a7; /* function argument */
#endif /* !CONFIG_RISCV_ISA_RV32E */

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

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

Expand Down
4 changes: 2 additions & 2 deletions soc/nordic/common/vpr/soc_isr_stacking.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
unsigned long a0; \
unsigned long a1; \
unsigned long mepc; \
unsigned long _mcause; \
unsigned long mcause; \
} __aligned(16);

#else /* DT_PROP(VPR_CPU, nordic_bus_width) == 32 */
Expand All @@ -56,7 +56,7 @@
unsigned long a2; \
unsigned long a1; \
unsigned long a0; \
unsigned long _mcause; \
unsigned long mcause; \
unsigned long mepc; \
} __aligned(16);

Expand Down

0 comments on commit e23074a

Please sign in to comment.