blob: 355db9db82104d11bac97f7c23c59fa363859757 [file] [log] [blame]
Heiko Carstens5bdc9b42006-07-03 00:24:41 -07001/*
Heiko Carstens5bdc9b42006-07-03 00:24:41 -07002 * Stack trace management functions
3 *
Heiko Carstensa53c8fa2012-07-20 11:15:04 +02004 * Copyright IBM Corp. 2006
Heiko Carstens5bdc9b42006-07-03 00:24:41 -07005 * 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>
Heiko Carstens8de2ce82008-07-17 17:16:45 +020011#include <linux/module.h>
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070012
Heiko Carstens758d39e2016-02-09 12:58:54 +010013static int __save_address(void *data, unsigned long address, int nosched)
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070014{
Heiko Carstens758d39e2016-02-09 12:58:54 +010015 struct stack_trace *trace = data;
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070016
Heiko Carstens758d39e2016-02-09 12:58:54 +010017 if (nosched && in_sched_functions(address))
18 return 0;
19 if (trace->skip > 0) {
20 trace->skip--;
21 return 0;
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070022 }
Heiko Carstens758d39e2016-02-09 12:58:54 +010023 if (trace->nr_entries < trace->max_entries) {
24 trace->entries[trace->nr_entries++] = address;
25 return 0;
26 }
27 return 1;
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070028}
29
Heiko Carstensd0208632016-10-17 11:08:31 +020030static int save_address(void *data, unsigned long address, int reliable)
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070031{
Heiko Carstens758d39e2016-02-09 12:58:54 +010032 return __save_address(data, address, 0);
33}
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070034
Heiko Carstensd0208632016-10-17 11:08:31 +020035static int save_address_nosched(void *data, unsigned long address, int reliable)
Heiko Carstens758d39e2016-02-09 12:58:54 +010036{
37 return __save_address(data, address, 1);
Heiko Carstens66adce82016-02-01 14:14:04 +010038}
39
40void save_stack_trace(struct stack_trace *trace)
41{
Heiko Carstens66adce82016-02-01 14:14:04 +010042 unsigned long sp;
43
Heiko Carstens76737ce2016-01-31 17:06:16 +010044 sp = current_stack_pointer();
Heiko Carstens758d39e2016-02-09 12:58:54 +010045 dump_trace(save_address, trace, NULL, sp);
Heiko Carstensf6331aa2016-02-01 14:06:57 +010046 if (trace->nr_entries < trace->max_entries)
47 trace->entries[trace->nr_entries++] = ULONG_MAX;
Heiko Carstensa3afe702008-02-05 16:50:45 +010048}
Ingo Molnar7b4c9502008-07-03 09:17:55 +020049EXPORT_SYMBOL_GPL(save_stack_trace);
Heiko Carstensa3afe702008-02-05 16:50:45 +010050
51void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
52{
Heiko Carstens758d39e2016-02-09 12:58:54 +010053 unsigned long sp;
Heiko Carstensa3afe702008-02-05 16:50:45 +010054
Heiko Carstens9cb1cce2016-01-18 13:12:19 +010055 sp = tsk->thread.ksp;
Heiko Carstens76737ce2016-01-31 17:06:16 +010056 if (tsk == current)
57 sp = current_stack_pointer();
Heiko Carstens758d39e2016-02-09 12:58:54 +010058 dump_trace(save_address_nosched, trace, tsk, sp);
Heiko Carstensa3afe702008-02-05 16:50:45 +010059 if (trace->nr_entries < trace->max_entries)
60 trace->entries[trace->nr_entries++] = ULONG_MAX;
Heiko Carstens5bdc9b42006-07-03 00:24:41 -070061}
Ingo Molnar7b4c9502008-07-03 09:17:55 +020062EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
Pratyush Anande0115872016-01-29 10:50:28 +053063
64void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
65{
66 unsigned long sp;
67
68 sp = kernel_stack_pointer(regs);
Heiko Carstens758d39e2016-02-09 12:58:54 +010069 dump_trace(save_address, trace, NULL, sp);
Pratyush Anande0115872016-01-29 10:50:28 +053070 if (trace->nr_entries < trace->max_entries)
71 trace->entries[trace->nr_entries++] = ULONG_MAX;
72}
73EXPORT_SYMBOL_GPL(save_stack_trace_regs);