soc: gd32: gd32vf103: keep the mcause.interrupt by SOC-specific context

For Nuclei ECLIC, the interrupt level (mintstatus.MIL) is restored from
the previous interrupt level (mcause.MPIL) only if mcause.interrupt is set.
This behavior is not defined in the RISC-V CLIC spec.
If an ISR causes a context switch and mcause.interrupt is not set in the
next context (e.g. the next context is yielded from ecall), interrupts will
be masked after MRET because the interrupt level is not restored.

Use SOC-specific context to set mcause.interrupt to ensure the interrupt
level is restored correctly.

Signed-off-by: Jimmy Zheng <jimmyzhe@andestech.com>
This commit is contained in:
Jimmy Zheng 2024-08-07 09:48:58 +08:00 committed by Benjamin Cabé
commit f216c434d0
5 changed files with 76 additions and 0 deletions

View file

@ -3,6 +3,7 @@
zephyr_sources(entry.S)
zephyr_sources(soc.c)
zephyr_sources(soc_irq.S)
zephyr_include_directories(.)

View file

@ -14,6 +14,7 @@ config SOC_SERIES_GD32VF103
select RISCV_ISA_EXT_ZIFENCEI
select RISCV_HAS_CLIC
select RISCV_SOC_HAS_GP_RELATIVE_ADDRESSING
select RISCV_SOC_CONTEXT_SAVE
select ATOMIC_OPERATIONS_C
select INCLUDE_RESET_VECTOR
select GD32_HAS_AFIO_PINMUX

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 Andes Technology Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SOC_RISCV_GD32_GD32VF103_SOC_CONTEXT_H
#define SOC_RISCV_GD32_GD32VF103_SOC_CONTEXT_H
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
#define SOC_ESF_MEMBERS
#define SOC_ESF_INIT
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
#endif /* SOC_RISCV_GD32_GD32VF103_SOC_CONTEXT_H */

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2024 Andes Technology Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/offsets.h>
#include <zephyr/toolchain.h>
#include <zephyr/arch/riscv/irq.h>
/* Exports */
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
GTEXT(__soc_save_context)
GTEXT(__soc_restore_context)
#endif
#ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
SECTION_FUNC(exception.other, __soc_save_context)
ret
SECTION_FUNC(exception.other, __soc_restore_context)
/*
* For Nuclei ECLIC, the interrupt level (mintstatus.MIL) is restored
* from the previous interrupt level (mcause.MPIL) only if
* mcause.interrupt is set when executing MRET.
* Always set the next context's mcause.interrupt to ensure the
* interrupt level is restored correctly after MRET.
*/
addi a0, a0, -__struct_arch_esf_soc_context_OFFSET
lw t0, __struct_arch_esf_mcause_OFFSET(a0)
li t1, 1 << RISCV_MCAUSE_IRQ_POS
or t0, t0, t1
sw t0, __struct_arch_esf_mcause_OFFSET(a0)
ret
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2024 Andes Technology Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SOC_RISCV_GD32_GD32VF103_SOC_OFFSETS_H_
#define SOC_RISCV_GD32_GD32VF103_SOC_OFFSETS_H_
#ifdef CONFIG_RISCV_SOC_OFFSETS
#define GEN_SOC_OFFSET_SYMS()
#endif /* CONFIG_RISCV_SOC_OFFSETS */
#endif /* SOC_RISCV_GD32_GD32VF103_SOC_OFFSETS_H_*/