From 26d75ab7960bab532d8e83d0d6c7bf3cec82e489 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 6 Sep 2024 00:13:01 +0800 Subject: [PATCH] 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 Signed-off-by: Yong Cong Sin --- arch/riscv/Kconfig | 8 ++++++++ arch/riscv/core/isr.S | 7 ++++++- arch/riscv/core/offsets/offsets.c | 4 ++++ doc/releases/release-notes-4.0.rst | 7 +++++++ include/zephyr/arch/riscv/exception.h | 10 ++++++++++ 5 files changed, 35 insertions(+), 1 deletion(-) 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