Skip to content

Commit

Permalink
arch: riscv: stacktrace: handle user threads
Browse files Browse the repository at this point in the history
Handle user threads stack bound validation in
`in_stack_bound()` to get more accurate traces.

If `CONFIG_PMP_POWER_OF_TWO_ALIGNMENT` is enabled:

```
+------------+ <- thread.arch.priv_stack_start
| Guard      | } Z_RISCV_STACK_GUARD_SIZE
+------------+
| Priv Stack | } CONFIG_PRIVILEGED_STACK_SIZE
+------------+ <- thread.arch.priv_stack_start +
                  CONFIG_PRIVILEGED_STACK_SIZE +
                  Z_RISCV_STACK_GUARD_SIZE
```

otherwise:

```
+------------+ <- thread.stack_obj
| Guard      | } Z_RISCV_STACK_GUARD_SIZE
+------------+
| Priv Stack | } CONFIG_PRIVILEGED_STACK_SIZE
+------------+ <- thread.stack_info.start
| Thread     |
| stack      |
|            |
+............|
| TLS        | } thread.stack_info.delta
+------------+ <- thread.stack_info.start +
                  thread.stack_info.size
```

See: zephyr/include/zephyr/arch/riscv/arch.h

Signed-off-by: Yong Cong Sin <[email protected]>
  • Loading branch information
ycsin authored and henrikbrixandersen committed May 29, 2024
1 parent 602c993 commit 6e8d979
Showing 1 changed file with 16 additions and 6 deletions.
22 changes: 16 additions & 6 deletions arch/riscv/core/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct stackframe {
LOG_ERR(" %2d: " SFP_FMT PR_REG " ra: " PR_REG, idx, sfp, ra)
#endif

static bool in_stack_bound(uintptr_t addr)
static bool in_stack_bound(uintptr_t addr, const z_arch_esf_t *esf)
{
#ifdef CONFIG_THREAD_STACK_INFO
uintptr_t start, end;
Expand All @@ -54,8 +54,17 @@ static bool in_stack_bound(uintptr_t addr)
start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]);
end = start + CONFIG_ISR_STACK_SIZE;
#ifdef CONFIG_USERSPACE
/* TODO: handle user threads */
#endif
} else if (((esf->mstatus & MSTATUS_MPP) == PRV_U) &&
((_current->base.user_options & K_USER) != 0)) {
/* See: zephyr/include/zephyr/arch/riscv/arch.h */
if (IS_ENABLED(CONFIG_PMP_POWER_OF_TWO_ALIGNMENT)) {
start = _current->arch.priv_stack_start - CONFIG_PRIVILEGED_STACK_SIZE;
end = _current->arch.priv_stack_start;
} else {
start = _current->stack_info.start - CONFIG_PRIVILEGED_STACK_SIZE;
end = _current->stack_info.start;
}
#endif /* CONFIG_USERSPACE */
} else {
start = _current->stack_info.start;
end = Z_STACK_PTR_ALIGN(_current->stack_info.start + _current->stack_info.size);
Expand All @@ -64,6 +73,7 @@ static bool in_stack_bound(uintptr_t addr)
return (addr >= start) && (addr < end);
#else
ARG_UNUSED(addr);
ARG_UNUSED(esf);
return true;
#endif /* CONFIG_THREAD_STACK_INFO */
}
Expand All @@ -84,7 +94,7 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf)

LOG_ERR("call trace:");

for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound(fp);) {
for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound(fp, esf);) {
frame = (struct stackframe *)fp - 1;
ra = frame->ra;
if (in_text_region(ra)) {
Expand Down Expand Up @@ -113,8 +123,8 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf)

LOG_ERR("call trace:");

for (int i = 0;
(i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && in_stack_bound((uintptr_t)ksp);
for (int i = 0; (i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) &&
in_stack_bound((uintptr_t)ksp, esf);
ksp++) {
ra = *ksp;
if (in_text_region(ra)) {
Expand Down

0 comments on commit 6e8d979

Please sign in to comment.