arch: riscv: Add support for stack unwind without fp
Add a stack unwind implementation that only uses `sp` Signed-off-by: Yong Cong Sin <ycsin@meta.com>
This commit is contained in:
parent
1472195197
commit
10a807537b
3 changed files with 65 additions and 18 deletions
|
@ -50,7 +50,6 @@ config RISCV_ENABLE_FRAME_POINTER
|
|||
config RISCV_EXCEPTION_STACK_TRACE
|
||||
bool
|
||||
default y
|
||||
depends on RISCV_ENABLE_FRAME_POINTER
|
||||
depends on EXCEPTION_STACK_TRACE
|
||||
imply THREAD_STACK_INFO
|
||||
help
|
||||
|
|
|
@ -28,6 +28,27 @@ static const struct z_exc_handle exceptions[] = {
|
|||
#define NO_REG " "
|
||||
#endif
|
||||
|
||||
static inline uintptr_t get_sp(const z_arch_esf_t *esf)
|
||||
{
|
||||
/*
|
||||
* 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);
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
if ((esf->mstatus & MSTATUS_MPP) == PRV_U) {
|
||||
/*
|
||||
* Exception happened in user space:
|
||||
* consider the saved user stack instead.
|
||||
*/
|
||||
sp = esf->sp;
|
||||
}
|
||||
#endif
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE
|
||||
#define MAX_STACK_FRAMES 8
|
||||
|
||||
|
@ -75,6 +96,7 @@ static inline bool in_text_region(uintptr_t addr)
|
|||
return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RISCV_ENABLE_FRAME_POINTER
|
||||
static void unwind_stack(const z_arch_esf_t *esf)
|
||||
{
|
||||
uintptr_t fp = esf->s0;
|
||||
|
@ -103,6 +125,36 @@ static void unwind_stack(const z_arch_esf_t *esf)
|
|||
|
||||
LOG_ERR("");
|
||||
}
|
||||
#else /* !CONFIG_RISCV_ENABLE_FRAME_POINTER */
|
||||
static void unwind_stack(const z_arch_esf_t *esf)
|
||||
{
|
||||
uintptr_t sp = get_sp(esf);
|
||||
uintptr_t ra;
|
||||
uintptr_t *ksp = (uintptr_t *)sp;
|
||||
|
||||
if (esf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERR("call trace:");
|
||||
|
||||
for (int i = 0;
|
||||
(i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && in_stack_bound((uintptr_t)ksp);
|
||||
ksp++) {
|
||||
ra = *ksp;
|
||||
if (in_text_region(ra)) {
|
||||
LOG_ERR(" %2d: sp: " PR_REG " ra: " PR_REG, i, (uintptr_t)ksp, ra);
|
||||
/*
|
||||
* Increment the iterator only if `ra` is within the text region to get the
|
||||
* most out of it
|
||||
*/
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERR("");
|
||||
}
|
||||
#endif /* CONFIG_RISCV_ENABLE_FRAME_POINTER */
|
||||
#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */
|
||||
|
||||
FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason,
|
||||
|
@ -116,12 +168,6 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf
|
|||
{
|
||||
#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);
|
||||
|
@ -136,16 +182,7 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf
|
|||
LOG_ERR(" a6: " PR_REG " t6: " PR_REG, esf->a6, esf->t6);
|
||||
LOG_ERR(" a7: " PR_REG, esf->a7);
|
||||
#endif /* CONFIG_RISCV_ISA_RV32E */
|
||||
#ifdef CONFIG_USERSPACE
|
||||
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(" sp: " PR_REG, get_sp(esf));
|
||||
LOG_ERR(" ra: " PR_REG, esf->ra);
|
||||
LOG_ERR(" mepc: " PR_REG, esf->mepc);
|
||||
LOG_ERR("mstatus: " PR_REG, esf->mstatus);
|
||||
|
|
|
@ -4,7 +4,7 @@ common:
|
|||
ignore_qemu_crash: true
|
||||
tags: kernel
|
||||
tests:
|
||||
arch.common.stack_unwind.riscv:
|
||||
arch.common.stack_unwind.riscv_fp:
|
||||
arch_allow: riscv
|
||||
integration_platforms:
|
||||
- qemu_riscv32
|
||||
|
@ -16,6 +16,17 @@ tests:
|
|||
- "E: call trace:"
|
||||
- "E: 0: fp: \\w+ ra: \\w+"
|
||||
- "E: 1: fp: \\w+ ra: \\w+"
|
||||
arch.common.stack_unwind.riscv_sp:
|
||||
arch_allow: riscv
|
||||
integration_platforms:
|
||||
- qemu_riscv32
|
||||
- qemu_riscv64
|
||||
harness_config:
|
||||
type: multi_line
|
||||
regex:
|
||||
- "E: call trace:"
|
||||
- "E: 0: sp: \\w+ ra: \\w+"
|
||||
- "E: 1: sp: \\w+ ra: \\w+"
|
||||
arch.common.stack_unwind.x86:
|
||||
arch_allow: x86
|
||||
extra_configs:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue