diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 4ef91c6be8d..575c9871c13 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -238,6 +238,14 @@ config RISCV_HART_MASK i.e. 128, 129, ..(0x80, 8x81, ..), this can be configured to 63 (0x7f) such that we can extract the bits that start from 0. +config EXTRA_EXCEPTION_INFO + bool "Collect extra exception info" + depends on EXCEPTION_DEBUG + help + This option enables the collection of extra information, such as + register state, when a fault occurs. This information can be useful + to collect for post-mortem analysis and debug of issues. + config RISCV_PMP bool "RISC-V PMP Support" select THREAD_STACK_INFO diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index bd21fed6b55..7e885da93a4 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -450,10 +450,15 @@ do_fault: STORE_CALLEE_SAVED() ; mv a2, sp +#ifdef CONFIG_EXTRA_EXCEPTION_INFO + /* Store csf's addr into esf (a1 still holds the pointer to the esf at this point) */ + sr a2 __struct_arch_esf_csf_OFFSET(a1) +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + tail z_riscv_fatal_error_csf #else tail z_riscv_fatal_error -#endif +#endif /* CONFIG_EXCEPTION_DEBUG */ #if defined(CONFIG_IRQ_OFFLOAD) do_irq_offload: diff --git a/arch/riscv/core/offsets/offsets.c b/arch/riscv/core/offsets/offsets.c index 7b2d55953b2..99eba096824 100644 --- a/arch/riscv/core/offsets/offsets.c +++ b/arch/riscv/core/offsets/offsets.c @@ -118,6 +118,10 @@ GEN_OFFSET_STRUCT(arch_esf, s0); GEN_OFFSET_STRUCT(arch_esf, sp); #endif +#ifdef CONFIG_EXTRA_EXCEPTION_INFO +GEN_OFFSET_STRUCT(arch_esf, csf); +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + #if defined(CONFIG_RISCV_SOC_CONTEXT_SAVE) GEN_OFFSET_STRUCT(arch_esf, soc_context); #endif diff --git a/doc/releases/release-notes-4.0.rst b/doc/releases/release-notes-4.0.rst index 05225a2dc58..a43f4e18cc1 100644 --- a/doc/releases/release-notes-4.0.rst +++ b/doc/releases/release-notes-4.0.rst @@ -64,6 +64,13 @@ Architectures * The stack traces upon fatal exception now prints the address of stack pointer (sp) or frame pointer (fp) depending on the build configuration. + * When :kconfig:option:`CONFIG_EXTRA_EXCEPTION_INFO` is enabled, the exception stack frame (arch_esf) + has an additional field ``csf`` that points to the callee-saved-registers upon an fatal error, + which can be accessed in :c:func:`k_sys_fatal_error_handler` by ``esf->csf``. + + * For SoCs that select `RISCV_SOC_HAS_ISR_STACKING`, the `SOC_ISR_STACKING_ESF_DECLARE` has to + include the `csf` member, otherwise the build would fail. + * Xtensa * x86 diff --git a/include/zephyr/arch/riscv/exception.h b/include/zephyr/arch/riscv/exception.h index 097776227bb..4e46417048c 100644 --- a/include/zephyr/arch/riscv/exception.h +++ b/include/zephyr/arch/riscv/exception.h @@ -45,6 +45,12 @@ struct soc_esf { }; #endif +#ifdef CONFIG_EXTRA_EXCEPTION_INFO +/* Forward declaration */ +struct _callee_saved; +typedef struct _callee_saved _callee_saved_t; +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + #if defined(CONFIG_RISCV_SOC_HAS_ISR_STACKING) SOC_ISR_STACKING_ESF_DECLARE; #else @@ -81,6 +87,10 @@ struct arch_esf { unsigned long sp; /* preserved (user or kernel) stack pointer */ #endif +#ifdef CONFIG_EXTRA_EXCEPTION_INFO + _callee_saved_t *csf; /* pointer to callee-saved-registers */ +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ + #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE struct soc_esf soc_context; #endif