Skip to content

Commit 7ecdadf

Browse files
guoren83palmer-dabbelt
authored andcommitted
riscv: stacktrace: Make walk_stackframe cross pt_regs frame
The current walk_stackframe with FRAME_POINTER would stop unwinding at ret_from_exception: BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:1518 in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 1, name: init CPU: 0 PID: 1 Comm: init Not tainted 5.10.113-00021-g15c15974895c-dirty torvalds#192 Call Trace: [<ffffffe0002038c8>] walk_stackframe+0x0/0xee [<ffffffe000aecf48>] show_stack+0x32/0x4a [<ffffffe000af1618>] dump_stack_lvl+0x72/0x8e [<ffffffe000af1648>] dump_stack+0x14/0x1c [<ffffffe000239ad2>] ___might_sleep+0x12e/0x138 [<ffffffe000239aec>] __might_sleep+0x10/0x18 [<ffffffe000afe3fe>] down_read+0x22/0xa4 [<ffffffe000207588>] do_page_fault+0xb0/0x2fe [<ffffffe000201b80>] ret_from_exception+0x0/0xc The optimization would help walk_stackframe cross the pt_regs frame and get more backtrace of debug info: BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:1518 in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 1, name: init CPU: 0 PID: 1 Comm: init Not tainted 5.10.113-00021-g15c15974895c-dirty torvalds#192 Call Trace: [<ffffffe0002038c8>] walk_stackframe+0x0/0xee [<ffffffe000aecf48>] show_stack+0x32/0x4a [<ffffffe000af1618>] dump_stack_lvl+0x72/0x8e [<ffffffe000af1648>] dump_stack+0x14/0x1c [<ffffffe000239ad2>] ___might_sleep+0x12e/0x138 [<ffffffe000239aec>] __might_sleep+0x10/0x18 [<ffffffe000afe3fe>] down_read+0x22/0xa4 [<ffffffe000207588>] do_page_fault+0xb0/0x2fe [<ffffffe000201b80>] ret_from_exception+0x0/0xc [<ffffffe000613c06>] riscv_intc_irq+0x1a/0x72 [<ffffffe000201b80>] ret_from_exception+0x0/0xc [<ffffffe00033f44a>] vma_link+0x54/0x160 [<ffffffe000341d7a>] mmap_region+0x2cc/0x4d0 [<ffffffe000342256>] do_mmap+0x2d8/0x3ac [<ffffffe000326318>] vm_mmap_pgoff+0x70/0xb8 [<ffffffe00032638a>] vm_mmap+0x2a/0x36 [<ffffffe0003cfdde>] elf_map+0x72/0x84 [<ffffffe0003d05f8>] load_elf_binary+0x69a/0xec8 [<ffffffe000376240>] bprm_execve+0x246/0x53a [<ffffffe00037786c>] kernel_execve+0xe8/0x124 [<ffffffe000aecdf2>] run_init_process+0xfa/0x10c [<ffffffe000aece16>] try_to_run_init_process+0x12/0x3c [<ffffffe000afa920>] kernel_init+0xb4/0xf8 [<ffffffe000201b80>] ret_from_exception+0x0/0xc Here is the error injection test code for the above output: drivers/irqchip/irq-riscv-intc.c: static asmlinkage void riscv_intc_irq(struct pt_regs *regs) { unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG; + u32 tmp; __get_user(tmp, (u32 *)0); Signed-off-by: Guo Ren <[email protected]> Signed-off-by: Guo Ren <[email protected]> Link: https://lore.kernel.org/r/[email protected] [Palmer: use SYM_CODE_*] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 5c3022e commit 7ecdadf

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

arch/riscv/kernel/entry.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ ret_from_syscall_rejected:
248248
andi t0, t0, _TIF_SYSCALL_WORK
249249
bnez t0, handle_syscall_trace_exit
250250

251-
ret_from_exception:
251+
SYM_CODE_START_NOALIGN(ret_from_exception)
252252
REG_L s0, PT_STATUS(sp)
253253
csrc CSR_STATUS, SR_IE
254254
#ifdef CONFIG_TRACE_IRQFLAGS
@@ -262,6 +262,7 @@ ret_from_exception:
262262
andi s0, s0, SR_SPP
263263
#endif
264264
bnez s0, resume_kernel
265+
SYM_CODE_END(ret_from_exception)
265266

266267
resume_userspace:
267268
/* Interrupts must be disabled here so flags are checked atomically */

arch/riscv/kernel/stacktrace.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#ifdef CONFIG_FRAME_POINTER
1818

19+
extern asmlinkage void ret_from_exception(void);
20+
1921
void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
2022
bool (*fn)(void *, unsigned long), void *arg)
2123
{
@@ -59,6 +61,13 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
5961
fp = frame->fp;
6062
pc = ftrace_graph_ret_addr(current, NULL, frame->ra,
6163
&frame->ra);
64+
if (pc == (unsigned long)ret_from_exception) {
65+
if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc)))
66+
break;
67+
68+
pc = ((struct pt_regs *)sp)->epc;
69+
fp = ((struct pt_regs *)sp)->s0;
70+
}
6271
}
6372

6473
}

0 commit comments

Comments
 (0)