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