1// SPDX-License-Identifier: GPL-2.0 2// Copyright (C) 2005-2017 Andes Technology Corporation 3 4#include <linux/sched/debug.h> 5#include <linux/sched/task_stack.h> 6#include <linux/stacktrace.h> 7 8void save_stack_trace(struct stack_trace *trace) 9{ 10 save_stack_trace_tsk(current, trace); 11} 12EXPORT_SYMBOL_GPL(save_stack_trace); 13 14void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 15{ 16 unsigned long *fpn; 17 int skip = trace->skip; 18 int savesched; 19 20 if (tsk == current) { 21 __asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn)); 22 savesched = 1; 23 } else { 24 fpn = (unsigned long *)thread_saved_fp(tsk); 25 savesched = 0; 26 } 27 28 while (!kstack_end(fpn) && !((unsigned long)fpn & 0x3) 29 && (fpn >= (unsigned long *)TASK_SIZE)) { 30 unsigned long lpp, fpp; 31 32 lpp = fpn[-1]; 33 fpp = fpn[FP_OFFSET]; 34 if (!__kernel_text_address(lpp)) 35 break; 36 37 if (savesched || !in_sched_functions(lpp)) { 38 if (skip) { 39 skip--; 40 } else { 41 trace->entries[trace->nr_entries++] = lpp; 42 if (trace->nr_entries >= trace->max_entries) 43 break; 44 } 45 } 46 fpn = (unsigned long *)fpp; 47 } 48} 49EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 50