1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. */ 3 4 #include <linux/sched/debug.h> 5 #include <linux/sched/task_stack.h> 6 #include <linux/stacktrace.h> 7 #include <linux/ftrace.h> 8 9 void save_stack_trace(struct stack_trace *trace) 10 { 11 save_stack_trace_tsk(current, trace); 12 } 13 EXPORT_SYMBOL_GPL(save_stack_trace); 14 15 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 16 { 17 unsigned long *fp, *stack_start, *stack_end; 18 unsigned long addr; 19 int skip = trace->skip; 20 int savesched; 21 int graph_idx = 0; 22 23 if (tsk == current) { 24 asm volatile("mov %0, r8\n":"=r"(fp)); 25 savesched = 1; 26 } else { 27 fp = (unsigned long *)thread_saved_fp(tsk); 28 savesched = 0; 29 } 30 31 addr = (unsigned long) fp & THREAD_MASK; 32 stack_start = (unsigned long *) addr; 33 stack_end = (unsigned long *) (addr + THREAD_SIZE); 34 35 while (fp > stack_start && fp < stack_end) { 36 unsigned long lpp, fpp; 37 38 fpp = fp[0]; 39 lpp = fp[1]; 40 if (!__kernel_text_address(lpp)) 41 break; 42 else 43 lpp = ftrace_graph_ret_addr(tsk, &graph_idx, lpp, NULL); 44 45 if (savesched || !in_sched_functions(lpp)) { 46 if (skip) { 47 skip--; 48 } else { 49 trace->entries[trace->nr_entries++] = lpp; 50 if (trace->nr_entries >= trace->max_entries) 51 break; 52 } 53 } 54 fp = (unsigned long *)fpp; 55 } 56 } 57 EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 58