1 #include <linux/sched.h> 2 #include <linux/stacktrace.h> 3 #include <linux/thread_info.h> 4 #include <linux/module.h> 5 #include <asm/ptrace.h> 6 #include <asm/stacktrace.h> 7 8 #include "kstack.h" 9 10 static void __save_stack_trace(struct thread_info *tp, 11 struct stack_trace *trace, 12 bool skip_sched) 13 { 14 unsigned long ksp, fp; 15 16 if (tp == current_thread_info()) { 17 stack_trace_flush(); 18 __asm__ __volatile__("mov %%fp, %0" : "=r" (ksp)); 19 } else { 20 ksp = tp->ksp; 21 } 22 23 fp = ksp + STACK_BIAS; 24 do { 25 struct sparc_stackf *sf; 26 struct pt_regs *regs; 27 unsigned long pc; 28 29 if (!kstack_valid(tp, fp)) 30 break; 31 32 sf = (struct sparc_stackf *) fp; 33 regs = (struct pt_regs *) (sf + 1); 34 35 if (kstack_is_trap_frame(tp, regs)) { 36 if (!(regs->tstate & TSTATE_PRIV)) 37 break; 38 pc = regs->tpc; 39 fp = regs->u_regs[UREG_I6] + STACK_BIAS; 40 } else { 41 pc = sf->callers_pc; 42 fp = (unsigned long)sf->fp + STACK_BIAS; 43 } 44 45 if (trace->skip > 0) 46 trace->skip--; 47 else if (!skip_sched || !in_sched_functions(pc)) 48 trace->entries[trace->nr_entries++] = pc; 49 } while (trace->nr_entries < trace->max_entries); 50 } 51 52 void save_stack_trace(struct stack_trace *trace) 53 { 54 __save_stack_trace(current_thread_info(), trace, false); 55 } 56 EXPORT_SYMBOL_GPL(save_stack_trace); 57 58 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 59 { 60 struct thread_info *tp = task_thread_info(tsk); 61 62 __save_stack_trace(tp, trace, true); 63 } 64 EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 65