From bdfa666f3ed68df41cf6f80a79eaf2a3ce44cd53 Mon Sep 17 00:00:00 2001 From: "liang.huang" Date: Wed, 15 Jul 2026 12:12:57 +0800 Subject: [PATCH] arch/risc-v: fix stale ustkptr used for backtrace in kernel stack mode xcp.ustkptr is only assigned once in up_initial_state() when a task is created and, since the syscall fast path was optimized in e6973c764c, is never updated afterwards. up_backtrace() used "ustkptr != NULL" to decide whether a task is currently blocked inside a syscall, and *(ustkptr + 1) as the frame pointer to resume tracing from. Since ustkptr is now a dead value fixed at task creation time, the check is always true and the "frame pointer" it derives points at stale data near the initial stack top, unrelated to where the task is actually blocked. Use rtcb->flags & TCB_FLAG_SYSCALL together with xcp.sregs, which dispatch_syscall() maintains precisely across the entire syscall execution window (including any nested context switches caused by blocking), to locate the frame pointer/return address saved at syscall entry instead. Signed-off-by: liang.huang --- arch/risc-v/src/common/riscv_backtrace.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/risc-v/src/common/riscv_backtrace.c b/arch/risc-v/src/common/riscv_backtrace.c index 947a7f9dbde..052aea9dfd7 100644 --- a/arch/risc-v/src/common/riscv_backtrace.c +++ b/arch/risc-v/src/common/riscv_backtrace.c @@ -180,12 +180,13 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size, int skip) else { #ifdef CONFIG_ARCH_KERNEL_STACK - if (rtcb->xcp.ustkptr != NULL) + if ((rtcb->flags & TCB_FLAG_SYSCALL) != 0) { ret = backtrace(rtcb->stack_base_ptr, (uintptr_t *) ((uintptr_t)rtcb->stack_base_ptr + rtcb->adj_stack_size), - (void *)*(rtcb->xcp.ustkptr + 1), NULL, + (void *)rtcb->xcp.sregs[REG_FP], + (void *)rtcb->xcp.sregs[REG_EPC], buffer, size, &skip); } else @@ -201,12 +202,13 @@ int up_backtrace(struct tcb_s *tcb, void **buffer, int size, int skip) else { #ifdef CONFIG_ARCH_KERNEL_STACK - if (tcb->xcp.ustkptr != NULL) + if ((tcb->flags & TCB_FLAG_SYSCALL) != 0) { ret = backtrace(tcb->stack_base_ptr, (uintptr_t *)((uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size), - (void *)*(tcb->xcp.ustkptr + 1), NULL, + (void *)tcb->xcp.sregs[REG_FP], + (void *)tcb->xcp.sregs[REG_EPC], buffer, size, &skip); } else