From 68799d507da32fde0459c6abffba33182ba73f2f Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Tue, 16 Jan 2024 16:31:26 +0100 Subject: [PATCH] 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 --- arch/riscv/Kconfig | 7 ++++++ arch/riscv/core/isr.S | 13 +++++++--- include/zephyr/arch/riscv/irq.h | 6 +++-- soc/riscv/common/riscv-privileged/soc_irq.S | 27 --------------------- soc/riscv/espressif_esp32/esp32c3/soc_irq.S | 6 ----- soc/riscv/ite_ec/common/soc_irq.S | 18 -------------- soc/riscv/openisa_rv32m1/soc_irq.S | 10 -------- 7 files changed, 21 insertions(+), 66 deletions(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 433bbe30aff..2e55d446a75 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -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 diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index 04e829a726e..422c2ce23bf 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -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 diff --git a/include/zephyr/arch/riscv/irq.h b/include/zephyr/arch/riscv/irq.h index 3cf0d28523c..c3764f8289b 100644 --- a/include/zephyr/arch/riscv/irq.h +++ b/include/zephyr/arch/riscv/irq.h @@ -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 diff --git a/soc/riscv/common/riscv-privileged/soc_irq.S b/soc/riscv/common/riscv-privileged/soc_irq.S index 377edbf600d..acf7e724aea 100644 --- a/soc/riscv/common/riscv-privileged/soc_irq.S +++ b/soc/riscv/common/riscv-privileged/soc_irq.S @@ -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 diff --git a/soc/riscv/espressif_esp32/esp32c3/soc_irq.S b/soc/riscv/espressif_esp32/esp32c3/soc_irq.S index c1ad164c153..6ce11ae6a81 100644 --- a/soc/riscv/espressif_esp32/esp32c3/soc_irq.S +++ b/soc/riscv/espressif_esp32/esp32c3/soc_irq.S @@ -7,15 +7,9 @@ #include /* 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) diff --git a/soc/riscv/ite_ec/common/soc_irq.S b/soc/riscv/ite_ec/common/soc_irq.S index a412ca6a796..ceb0f3afecb 100644 --- a/soc/riscv/ite_ec/common/soc_irq.S +++ b/soc/riscv/ite_ec/common/soc_irq.S @@ -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 diff --git a/soc/riscv/openisa_rv32m1/soc_irq.S b/soc/riscv/openisa_rv32m1/soc_irq.S index 23222ea2c70..d3059d2bd28 100644 --- a/soc/riscv/openisa_rv32m1/soc_irq.S +++ b/soc/riscv/openisa_rv32m1/soc_irq.S @@ -10,22 +10,12 @@ #include /* 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: *