61 lines · 1.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0#include <linux/sched.h>#include <linux/sched/task_stack.h>#include <linux/stacktrace.h>#include <linux/kallsyms.h> #include <asm/thread_info.h>#include <asm/ptrace.h> static __always_inline unsigned long alpha_get_current_ksp(void){	unsigned long sp; 	asm volatile("mov $30, %0" : "=r"(sp));	return sp;} static void alpha_scan_kernel_stack(unsigned long ksp,				    stack_trace_consume_fn consume_entry,				    void *cookie){	unsigned long *p = (unsigned long *)ksp; 	if (unlikely(ksp & (sizeof(unsigned long) - 1)))		return; 	while (!kstack_end(p)) {		unsigned long addr = READ_ONCE_NOCHECK(*p++); 		if (!__kernel_text_address(addr))			continue; 		if (!consume_entry(cookie, addr))			break;	}} noinline void arch_stack_walk(stack_trace_consume_fn consume_entry,				      void *cookie,				      struct task_struct *task,				      struct pt_regs *regs){	unsigned long ksp; 	if (!task)		task = current; 	if (regs && task == current) {		/*		 * pt_regs is stored on the kernel stack; regs+1 matches		 * what arch/alpha/kernel/traps.c uses as the trace start.		 */		ksp = (unsigned long)(regs + 1);	} else if (task == current) {		ksp = alpha_get_current_ksp();	} else {		ksp = task_thread_info(task)->pcb.ksp;	} 	alpha_scan_kernel_stack(ksp, consume_entry, cookie);}