arch: riscv: print callee-saved-registers in fatal error
Print callee-saved registers during fatal error to help with debugging. Signed-off-by: Yong Cong Sin <ycsin@meta.com>
This commit is contained in:
parent
7e0a334060
commit
30b122b3f0
|
@ -101,9 +101,21 @@ static void unwind_stack(const z_arch_esf_t *esf)
|
|||
|
||||
FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason,
|
||||
const z_arch_esf_t *esf)
|
||||
{
|
||||
z_riscv_fatal_error_csf(reason, esf, NULL);
|
||||
}
|
||||
|
||||
FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf_t *esf,
|
||||
const _callee_saved_t *csf)
|
||||
{
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
if (esf != NULL) {
|
||||
/*
|
||||
* Kernel stack pointer prior this exception i.e. before
|
||||
* storing the exception stack frame.
|
||||
*/
|
||||
uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t);
|
||||
|
||||
LOG_ERR(" a0: " PR_REG " t0: " PR_REG, esf->a0, esf->t0);
|
||||
LOG_ERR(" a1: " PR_REG " t1: " PR_REG, esf->a1, esf->t1);
|
||||
LOG_ERR(" a2: " PR_REG " t2: " PR_REG, esf->a2, esf->t2);
|
||||
|
@ -119,8 +131,15 @@ FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason,
|
|||
LOG_ERR(" a7: " PR_REG, esf->a7);
|
||||
#endif /* CONFIG_RISCV_ISA_RV32E */
|
||||
#ifdef CONFIG_USERSPACE
|
||||
LOG_ERR(" sp: " PR_REG, esf->sp);
|
||||
if ((esf->mstatus & MSTATUS_MPP) == 0) {
|
||||
/*
|
||||
* Exception happened in user space:
|
||||
* consider the saved user stack instead.
|
||||
*/
|
||||
sp = esf->sp;
|
||||
}
|
||||
#endif
|
||||
LOG_ERR(" sp: " PR_REG, sp);
|
||||
LOG_ERR(" ra: " PR_REG, esf->ra);
|
||||
LOG_ERR(" mepc: " PR_REG, esf->mepc);
|
||||
LOG_ERR("mstatus: " PR_REG, esf->mstatus);
|
||||
|
@ -129,6 +148,21 @@ FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason,
|
|||
unwind_stack(esf);
|
||||
#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */
|
||||
}
|
||||
|
||||
if (csf != NULL) {
|
||||
#if defined(CONFIG_RISCV_ISA_RV32E)
|
||||
LOG_ERR(" s0: " PR_REG, csf->s0);
|
||||
LOG_ERR(" s1: " PR_REG, csf->s1);
|
||||
#else
|
||||
LOG_ERR(" s0: " PR_REG " s6: " PR_REG, csf->s0, csf->s6);
|
||||
LOG_ERR(" s1: " PR_REG " s7: " PR_REG, csf->s1, csf->s7);
|
||||
LOG_ERR(" s2: " PR_REG " s8: " PR_REG, csf->s2, csf->s8);
|
||||
LOG_ERR(" s3: " PR_REG " s9: " PR_REG, csf->s3, csf->s9);
|
||||
LOG_ERR(" s4: " PR_REG " s10: " PR_REG, csf->s4, csf->s10);
|
||||
LOG_ERR(" s5: " PR_REG " s11: " PR_REG, csf->s5, csf->s11);
|
||||
#endif /* CONFIG_RISCV_ISA_RV32E */
|
||||
LOG_ERR("");
|
||||
}
|
||||
#endif /* CONFIG_EXCEPTION_DEBUG */
|
||||
z_fatal_error(reason, esf);
|
||||
CODE_UNREACHABLE;
|
||||
|
|
|
@ -41,6 +41,23 @@
|
|||
RV_I( op a7, __z_arch_esf_t_a7_OFFSET(sp) );\
|
||||
RV_E( op ra, __z_arch_esf_t_ra_OFFSET(sp) )
|
||||
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
/* Convenience macro for storing callee saved register [s0 - s11] states. */
|
||||
#define STORE_CALLEE_SAVED() \
|
||||
RV_E( sr s0, ___callee_saved_t_s0_OFFSET(sp) );\
|
||||
RV_E( sr s1, ___callee_saved_t_s1_OFFSET(sp) );\
|
||||
RV_I( sr s2, ___callee_saved_t_s2_OFFSET(sp) );\
|
||||
RV_I( sr s3, ___callee_saved_t_s3_OFFSET(sp) );\
|
||||
RV_I( sr s4, ___callee_saved_t_s4_OFFSET(sp) );\
|
||||
RV_I( sr s5, ___callee_saved_t_s5_OFFSET(sp) );\
|
||||
RV_I( sr s6, ___callee_saved_t_s6_OFFSET(sp) );\
|
||||
RV_I( sr s7, ___callee_saved_t_s7_OFFSET(sp) );\
|
||||
RV_I( sr s8, ___callee_saved_t_s8_OFFSET(sp) );\
|
||||
RV_I( sr s9, ___callee_saved_t_s9_OFFSET(sp) );\
|
||||
RV_I( sr s10, ___callee_saved_t_s10_OFFSET(sp) );\
|
||||
RV_I( sr s11, ___callee_saved_t_s11_OFFSET(sp) )
|
||||
#endif /* CONFIG_EXCEPTION_DEBUG */
|
||||
|
||||
.macro get_current_cpu dst
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_USERSPACE)
|
||||
csrr \dst, mscratch
|
||||
|
@ -61,7 +78,7 @@ GTEXT(__soc_save_context)
|
|||
GTEXT(__soc_restore_context)
|
||||
#endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */
|
||||
|
||||
GTEXT(z_riscv_fatal_error)
|
||||
GTEXT(z_riscv_fatal_error_csf)
|
||||
GTEXT(z_get_next_switch_handle)
|
||||
GTEXT(z_riscv_switch)
|
||||
GTEXT(z_riscv_thread_start)
|
||||
|
@ -386,7 +403,17 @@ do_fault:
|
|||
/* Handle RV_ECALL_RUNTIME_EXCEPT. Retrieve reason in a0, esf in A1. */
|
||||
lr a0, __z_arch_esf_t_a0_OFFSET(sp)
|
||||
1: mv a1, sp
|
||||
tail z_riscv_fatal_error
|
||||
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
/* Allocate space for caller-saved registers on current thread stack */
|
||||
addi sp, sp, -__callee_saved_t_SIZEOF
|
||||
|
||||
/* Save callee-saved registers to be passed as 3rd arg */
|
||||
STORE_CALLEE_SAVED() ;
|
||||
mv a2, sp
|
||||
#endif
|
||||
|
||||
tail z_riscv_fatal_error_csf
|
||||
|
||||
#if defined(CONFIG_IRQ_OFFLOAD)
|
||||
do_irq_offload:
|
||||
|
|
|
@ -126,6 +126,10 @@ GEN_SOC_OFFSET_SYMS();
|
|||
|
||||
GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, sizeof(z_arch_esf_t));
|
||||
|
||||
#ifdef CONFIG_EXCEPTION_DEBUG
|
||||
GEN_ABSOLUTE_SYM(__callee_saved_t_SIZEOF, ROUND_UP(sizeof(_callee_saved_t), ARCH_STACK_PTR_ALIGN));
|
||||
#endif /* CONFIG_EXCEPTION_DEBUG */
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
GEN_OFFSET_SYM(_cpu_arch_t, user_exc_sp);
|
||||
GEN_OFFSET_SYM(_cpu_arch_t, user_exc_tmp0);
|
||||
|
|
|
@ -69,9 +69,13 @@ arch_switch(void *switch_to, void **switched_from)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Thin wrapper around z_riscv_fatal_error_csf */
|
||||
FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason,
|
||||
const z_arch_esf_t *esf);
|
||||
|
||||
FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf_t *esf,
|
||||
const _callee_saved_t *csf);
|
||||
|
||||
static inline bool arch_is_in_isr(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
|
|
|
@ -60,6 +60,8 @@ Architectures
|
|||
|
||||
* Implemented frame-pointer based stack unwinding.
|
||||
|
||||
* The fatal error message triggered from a fault now contains the callee-saved-registers states.
|
||||
|
||||
* Xtensa
|
||||
|
||||
Bluetooth
|
||||
|
|
Loading…
Reference in a new issue