1 // SPDX-License-Identifier: GPL-2.0-only
3 * Stack tracing support
5 * Copyright (C) 2012 ARM Ltd.
7 #include <linux/kernel.h>
8 #include <linux/export.h>
9 #include <linux/ftrace.h>
10 #include <linux/sched.h>
11 #include <linux/sched/debug.h>
12 #include <linux/sched/task_stack.h>
13 #include <linux/stacktrace.h>
16 #include <asm/stack_pointer.h>
17 #include <asm/stacktrace.h>
20 * Start an unwind from a pt_regs.
22 * The unwind will begin at the PC within the regs.
24 * The regs must be on a stack currently owned by the calling task.
26 static inline void unwind_init_from_regs(struct unwind_state *state,
29 unwind_init_common(state, current);
31 state->fp = regs->regs[29];
36 * Start an unwind from a caller.
38 * The unwind will begin at the caller of whichever function this is inlined
41 * The function which invokes this must be noinline.
43 static __always_inline void unwind_init_from_caller(struct unwind_state *state)
45 unwind_init_common(state, current);
47 state->fp = (unsigned long)__builtin_frame_address(1);
48 state->pc = (unsigned long)__builtin_return_address(0);
52 * Start an unwind from a blocked task.
54 * The unwind will begin at the blocked tasks saved PC (i.e. the caller of
57 * The caller should ensure the task is blocked in cpu_switch_to() for the
58 * duration of the unwind, or the unwind will be bogus. It is never valid to
59 * call this for the current task.
61 static inline void unwind_init_from_task(struct unwind_state *state,
62 struct task_struct *task)
64 unwind_init_common(state, task);
66 state->fp = thread_saved_fp(task);
67 state->pc = thread_saved_pc(task);
70 static bool dump_backtrace_entry(void *arg, unsigned long where)
73 printk("%s %pSb\n", loglvl, (void *)where);
77 void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
80 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
82 if (regs && user_mode(regs))
88 if (!try_get_task_stack(tsk))
91 printk("%sCall trace:\n", loglvl);
92 arch_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs);
97 void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
99 dump_backtrace(NULL, tsk, loglvl);
103 noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
104 void *cookie, struct task_struct *task,
105 struct pt_regs *regs)
107 struct unwind_state state;
112 unwind_init_from_regs(&state, regs);
113 } else if (task == current) {
114 unwind_init_from_caller(&state);
116 unwind_init_from_task(&state, task);
119 unwind(&state, consume_entry, cookie);