projects/linux·blob uaccess-cleanups · refs

61 lines · 1.3 KiB

1// SPDX-License-Identifier: GPL-2.0
2#include <linux/sched.h>
3#include <linux/sched/task_stack.h>
4#include <linux/stacktrace.h>
5#include <linux/kallsyms.h>
6
7#include <asm/thread_info.h>
8#include <asm/ptrace.h>
9
10static __always_inline unsigned long alpha_get_current_ksp(void)
11{
12 unsigned long sp;
13
14 asm volatile("mov $30, %0" : "=r"(sp));
15 return sp;
16}
17
18static void alpha_scan_kernel_stack(unsigned long ksp,
19 stack_trace_consume_fn consume_entry,
20 void *cookie)
21{
22 unsigned long *p = (unsigned long *)ksp;
23
24 if (unlikely(ksp & (sizeof(unsigned long) - 1)))
25 return;
26
27 while (!kstack_end(p)) {
28 unsigned long addr = READ_ONCE_NOCHECK(*p++);
29
30 if (!__kernel_text_address(addr))
31 continue;
32
33 if (!consume_entry(cookie, addr))
34 break;
35 }
36}
37
38noinline void arch_stack_walk(stack_trace_consume_fn consume_entry,
39 void *cookie,
40 struct task_struct *task,
41 struct pt_regs *regs)
42{
43 unsigned long ksp;
44
45 if (!task)
46 task = current;
47
48 if (regs && task == current) {
49 /*
50 * pt_regs is stored on the kernel stack; regs+1 matches
51 * what arch/alpha/kernel/traps.c uses as the trace start.
52 */
53 ksp = (unsigned long)(regs + 1);
54 } else if (task == current) {
55 ksp = alpha_get_current_ksp();
56 } else {
57 ksp = task_thread_info(task)->pcb.ksp;
58 }
59
60 alpha_scan_kernel_stack(ksp, consume_entry, cookie);
61}