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 10 static __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 18 static 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 38 noinline 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 } 62