arch: riscv: make __soc_is_irq optional

It looks like all SoCs in tree check if an exception comes from an IRQ
the same way, so let's provide a common logic by default, still
customizable if the SoC selects RISCV_SOC_ISR_CHECK.

Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
This commit is contained in:
Gerard Marull-Paretas 2024-01-16 16:31:26 +01:00 committed by Carles Cufí
commit 68799d507d
7 changed files with 21 additions and 66 deletions

View file

@ -172,6 +172,13 @@ config RISCV_HAS_CLIC
help
Does the SOC provide support for a Core-Local Interrupt Controller (CLIC).
config RISCV_SOC_EXCEPTION_FROM_IRQ
bool
help
Option selected by SoCs that require a custom mechanism to check if
an exception is the result of an interrupt or not. If selected,
__soc_is_irq() needs to be implemented by the SoC.
config RISCV_SOC_INTERRUPT_INIT
bool "SOC-based interrupt initialization"
help

View file

@ -51,7 +51,9 @@
/* imports */
GDATA(_sw_isr_table)
#ifdef CONFIG_RISCV_SOC_EXCEPTION_FROM_IRQ
GTEXT(__soc_is_irq)
#endif
GTEXT(__soc_handle_irq)
GTEXT(_Fault)
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
@ -95,7 +97,8 @@ GTEXT(_isr_wrapper)
* what standard behavior is defined). Hence, the arch level code expects
* the following functions to be provided at the SOC level:
*
* - __soc_is_irq: decide if we're handling an interrupt or an exception
* - __soc_is_irq (optional): decide if we're handling an interrupt or an
exception
* - __soc_handle_irq: handle SoC-specific details for a pending IRQ
* (e.g. clear a pending bit in a SoC-specific register)
*
@ -288,10 +291,14 @@ no_fp: /* increment _current->arch.exception_depth */
* function (that needs to be implemented by each SOC). The result is
* returned via register a0 (1: interrupt, 0 exception)
*/
#ifdef CONFIG_RISCV_SOC_EXCEPTION_FROM_IRQ
jal ra, __soc_is_irq
/* If a0 != 0, jump to is_interrupt */
bnez a0, is_interrupt
#else
csrr t0, mcause
srli t0, t0, RISCV_MCAUSE_IRQ_POS
bnez t0, is_interrupt
#endif
/*
* If the exception is the result of an ECALL, check whether to

View file

@ -39,9 +39,11 @@ extern "C" {
#define RISCV_IRQ_MEXT 11
#ifdef CONFIG_64BIT
#define RISCV_MCAUSE_IRQ_BIT (1 << 63)
#define RISCV_MCAUSE_IRQ_POS 63U
#define RISCV_MCAUSE_IRQ_BIT BIT64(RISCV_MCAUSE_IRQ_POS)
#else
#define RISCV_MCAUSE_IRQ_BIT (1 << 31)
#define RISCV_MCAUSE_IRQ_POS 31U
#define RISCV_MCAUSE_IRQ_BIT BIT(RISCV_MCAUSE_IRQ_POS)
#endif
#ifndef _ASMLANGUAGE

View file

@ -32,30 +32,3 @@ SECTION_FUNC(exception.other, __soc_handle_irq)
/* Return */
ret
/*
* __soc_is_irq is defined as .weak to allow re-implementation by
* SOCs that do not truly follow the riscv privilege specification.
*/
WTEXT(__soc_is_irq)
/*
* SOC-specific function to determine if the exception is the result of a
* an interrupt or an exception
* return 1 (interrupt) or 0 (exception)
*
*/
SECTION_FUNC(exception.other, __soc_is_irq)
/* Read mcause and check if interrupt bit is set */
csrr t0, mcause
li t1, RISCV_MCAUSE_IRQ_BIT
and t0, t0, t1
/* If interrupt bit is not set, return with 0 */
addi a0, x0, 0
beqz t0, not_interrupt
addi a0, a0, 1
not_interrupt:
/* return */
ret

View file

@ -7,15 +7,9 @@
#include <zephyr/toolchain.h>
/* Exports */
GTEXT(__soc_is_irq)
GTEXT(__soc_handle_irq)
GTEXT(soc_intr_get_next_source)
SECTION_FUNC(exception.other, __soc_is_irq)
csrr a0, mcause
srli a0, a0, 31
ret
SECTION_FUNC(exception.other, __soc_handle_irq)
addi sp, sp,-4
sw ra, 0x00(sp)

View file

@ -25,21 +25,3 @@ GTEXT(__soc_handle_irq)
*/
SECTION_FUNC(exception.other, __soc_handle_irq)
j get_irq
/*
* __soc_is_irq is defined as .weak to allow re-implementation by
* SOCs that does not truely follow the riscv privilege specification.
*/
WTEXT(__soc_is_irq)
/*
* SOC-specific function to determine if the exception is the result of a
* an interrupt or an exception
* return 1 (interrupt) or 0 (exception)
*
*/
SECTION_FUNC(exception.other, __soc_is_irq)
/* Read mcause and check if interrupt bit (bit 31) is set */
csrr a0, mcause
srli a0, a0, 31
ret

View file

@ -10,22 +10,12 @@
#include <soc.h>
/* Exports */
GTEXT(__soc_is_irq)
GTEXT(__soc_handle_irq)
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
GTEXT(__soc_save_context)
GTEXT(__soc_restore_context)
#endif
/*
* Whether we're in an IRQ is bog-standard RISC-V on this SoC:
* yes if the top mcause bit is set, otherwise no.
*/
SECTION_FUNC(exception.other, __soc_is_irq)
csrr a0, mcause
srli a0, a0, 31
ret
/*
* With a0 == irq_num, this is equivalent to:
*