xref: /openbmc/linux/arch/s390/kernel/stacktrace.c (revision e5c86679)
1 /*
2  * Stack trace management functions
3  *
4  *  Copyright IBM Corp. 2006
5  *  Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
6  */
7 
8 #include <linux/sched.h>
9 #include <linux/sched/debug.h>
10 #include <linux/stacktrace.h>
11 #include <linux/kallsyms.h>
12 #include <linux/export.h>
13 
14 static int __save_address(void *data, unsigned long address, int nosched)
15 {
16 	struct stack_trace *trace = data;
17 
18 	if (nosched && in_sched_functions(address))
19 		return 0;
20 	if (trace->skip > 0) {
21 		trace->skip--;
22 		return 0;
23 	}
24 	if (trace->nr_entries < trace->max_entries) {
25 		trace->entries[trace->nr_entries++] = address;
26 		return 0;
27 	}
28 	return 1;
29 }
30 
31 static int save_address(void *data, unsigned long address, int reliable)
32 {
33 	return __save_address(data, address, 0);
34 }
35 
36 static int save_address_nosched(void *data, unsigned long address, int reliable)
37 {
38 	return __save_address(data, address, 1);
39 }
40 
41 void save_stack_trace(struct stack_trace *trace)
42 {
43 	unsigned long sp;
44 
45 	sp = current_stack_pointer();
46 	dump_trace(save_address, trace, NULL, sp);
47 	if (trace->nr_entries < trace->max_entries)
48 		trace->entries[trace->nr_entries++] = ULONG_MAX;
49 }
50 EXPORT_SYMBOL_GPL(save_stack_trace);
51 
52 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
53 {
54 	unsigned long sp;
55 
56 	sp = tsk->thread.ksp;
57 	if (tsk == current)
58 		sp = current_stack_pointer();
59 	dump_trace(save_address_nosched, trace, tsk, sp);
60 	if (trace->nr_entries < trace->max_entries)
61 		trace->entries[trace->nr_entries++] = ULONG_MAX;
62 }
63 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
64 
65 void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
66 {
67 	unsigned long sp;
68 
69 	sp = kernel_stack_pointer(regs);
70 	dump_trace(save_address, trace, NULL, sp);
71 	if (trace->nr_entries < trace->max_entries)
72 		trace->entries[trace->nr_entries++] = ULONG_MAX;
73 }
74 EXPORT_SYMBOL_GPL(save_stack_trace_regs);
75