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)
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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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