xref: /openbmc/linux/arch/csky/kernel/stacktrace.c (revision be709d48)
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