GNU Linux-libre 4.14.290-gnu1
[releases.git] / arch / s390 / kernel / stacktrace.c
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);