xref: /linux/arch/s390/kernel/stacktrace.c (revision 80d443e8876602be2c130f79c4de81e12e2a700d)
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/stacktrace.h>
10 #include <linux/kallsyms.h>
11 #include <linux/module.h>
12 
13 static int __save_address(void *data, unsigned long address, int nosched)
14 {
15 	struct stack_trace *trace = data;
16 
17 	if (nosched && in_sched_functions(address))
18 		return 0;
19 	if (trace->skip > 0) {
20 		trace->skip--;
21 		return 0;
22 	}
23 	if (trace->nr_entries < trace->max_entries) {
24 		trace->entries[trace->nr_entries++] = address;
25 		return 0;
26 	}
27 	return 1;
28 }
29 
30 static int save_address(void *data, unsigned long address, int reliable)
31 {
32 	return __save_address(data, address, 0);
33 }
34 
35 static int save_address_nosched(void *data, unsigned long address, int reliable)
36 {
37 	return __save_address(data, address, 1);
38 }
39 
40 void save_stack_trace(struct stack_trace *trace)
41 {
42 	unsigned long sp;
43 
44 	sp = current_stack_pointer();
45 	dump_trace(save_address, trace, NULL, sp);
46 	if (trace->nr_entries < trace->max_entries)
47 		trace->entries[trace->nr_entries++] = ULONG_MAX;
48 }
49 EXPORT_SYMBOL_GPL(save_stack_trace);
50 
51 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
52 {
53 	unsigned long sp;
54 
55 	sp = tsk->thread.ksp;
56 	if (tsk == current)
57 		sp = current_stack_pointer();
58 	dump_trace(save_address_nosched, trace, tsk, sp);
59 	if (trace->nr_entries < trace->max_entries)
60 		trace->entries[trace->nr_entries++] = ULONG_MAX;
61 }
62 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
63 
64 void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
65 {
66 	unsigned long sp;
67 
68 	sp = kernel_stack_pointer(regs);
69 	dump_trace(save_address, trace, NULL, sp);
70 	if (trace->nr_entries < trace->max_entries)
71 		trace->entries[trace->nr_entries++] = ULONG_MAX;
72 }
73 EXPORT_SYMBOL_GPL(save_stack_trace_regs);
74