arch: riscv: optionally stores a pointer to csf in struct arch_esf

The callee-saved-registers can be helpful to debug the state of
a core upon an exception, however, currently there's no way to
access that information in user-implemented
`k_sys_fatal_error_handler()`, even though the csf is already stored
in the stack.

This patch conditionally add a `csf` member in the `arch_esf` when
`CONFIG_EXTRA_EXCEPTION_INFO=y`*, which the `_isr_wrapper` would update
when a fatal error occurs before invoking `z_riscv_fatal_error_csf()`.

Functions such as `k_sys_fatal_error_handler()` would then be able
to access the callee-saved-registers at the time of exception via
`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.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
This commit is contained in:
Yong Cong Sin 2024-09-06 00:13:01 +08:00 committed by Carles Cufí
commit 26d75ab796
5 changed files with 35 additions and 1 deletions

View file

@ -238,6 +238,14 @@ config RISCV_HART_MASK
i.e. 128, 129, ..(0x80, 8x81, ..), this can be configured to 63 (0x7f) i.e. 128, 129, ..(0x80, 8x81, ..), this can be configured to 63 (0x7f)
such that we can extract the bits that start from 0. 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 config RISCV_PMP
bool "RISC-V PMP Support" bool "RISC-V PMP Support"
select THREAD_STACK_INFO select THREAD_STACK_INFO

View file

@ -450,10 +450,15 @@ do_fault:
STORE_CALLEE_SAVED() ; STORE_CALLEE_SAVED() ;
mv a2, sp 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 tail z_riscv_fatal_error_csf
#else #else
tail z_riscv_fatal_error tail z_riscv_fatal_error
#endif #endif /* CONFIG_EXCEPTION_DEBUG */
#if defined(CONFIG_IRQ_OFFLOAD) #if defined(CONFIG_IRQ_OFFLOAD)
do_irq_offload: do_irq_offload:

View file

@ -118,6 +118,10 @@ GEN_OFFSET_STRUCT(arch_esf, s0);
GEN_OFFSET_STRUCT(arch_esf, sp); GEN_OFFSET_STRUCT(arch_esf, sp);
#endif #endif
#ifdef CONFIG_EXTRA_EXCEPTION_INFO
GEN_OFFSET_STRUCT(arch_esf, csf);
#endif /* CONFIG_EXTRA_EXCEPTION_INFO */
#if defined(CONFIG_RISCV_SOC_CONTEXT_SAVE) #if defined(CONFIG_RISCV_SOC_CONTEXT_SAVE)
GEN_OFFSET_STRUCT(arch_esf, soc_context); GEN_OFFSET_STRUCT(arch_esf, soc_context);
#endif #endif

View file

@ -64,6 +64,13 @@ Architectures
* The stack traces upon fatal exception now prints the address of stack pointer (sp) or frame * The stack traces upon fatal exception now prints the address of stack pointer (sp) or frame
pointer (fp) depending on the build configuration. 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 * Xtensa
* x86 * x86

View file

@ -45,6 +45,12 @@ struct soc_esf {
}; };
#endif #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) #if defined(CONFIG_RISCV_SOC_HAS_ISR_STACKING)
SOC_ISR_STACKING_ESF_DECLARE; SOC_ISR_STACKING_ESF_DECLARE;
#else #else
@ -81,6 +87,10 @@ struct arch_esf {
unsigned long sp; /* preserved (user or kernel) stack pointer */ unsigned long sp; /* preserved (user or kernel) stack pointer */
#endif #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 #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE
struct soc_esf soc_context; struct soc_esf soc_context;
#endif #endif