aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/stacktrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/stacktrace.c')
-rw-r--r--arch/sh/kernel/stacktrace.c87
1 files changed, 61 insertions, 26 deletions
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
index 1a2a5eb76e41..6c24a400b05e 100644
--- a/arch/sh/kernel/stacktrace.c
+++ b/arch/sh/kernel/stacktrace.c
@@ -14,46 +14,81 @@
14#include <linux/thread_info.h> 14#include <linux/thread_info.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <asm/ptrace.h> 16#include <asm/ptrace.h>
17#include <asm/stacktrace.h>
18
19static void save_stack_warning(void *data, char *msg)
20{
21}
22
23static void
24save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
25{
26}
27
28static int save_stack_stack(void *data, char *name)
29{
30 return 0;
31}
17 32
18/* 33/*
19 * Save stack-backtrace addresses into a stack_trace buffer. 34 * Save stack-backtrace addresses into a stack_trace buffer.
20 */ 35 */
36static void save_stack_address(void *data, unsigned long addr, int reliable)
37{
38 struct stack_trace *trace = data;
39
40 if (trace->skip > 0) {
41 trace->skip--;
42 return;
43 }
44
45 if (trace->nr_entries < trace->max_entries)
46 trace->entries[trace->nr_entries++] = addr;
47}
48
49static const struct stacktrace_ops save_stack_ops = {
50 .warning = save_stack_warning,
51 .warning_symbol = save_stack_warning_symbol,
52 .stack = save_stack_stack,
53 .address = save_stack_address,
54};
55
21void save_stack_trace(struct stack_trace *trace) 56void save_stack_trace(struct stack_trace *trace)
22{ 57{
23 unsigned long *sp = (unsigned long *)current_stack_pointer; 58 unsigned long *sp = (unsigned long *)current_stack_pointer;
24 59
25 while (!kstack_end(sp)) { 60 dump_trace(current, NULL, sp, &save_stack_ops, trace);
26 unsigned long addr = *sp++;
27
28 if (__kernel_text_address(addr)) {
29 if (trace->skip > 0)
30 trace->skip--;
31 else
32 trace->entries[trace->nr_entries++] = addr;
33 if (trace->nr_entries >= trace->max_entries)
34 break;
35 }
36 }
37} 61}
38EXPORT_SYMBOL_GPL(save_stack_trace); 62EXPORT_SYMBOL_GPL(save_stack_trace);
39 63
64static void
65save_stack_address_nosched(void *data, unsigned long addr, int reliable)
66{
67 struct stack_trace *trace = (struct stack_trace *)data;
68
69 if (in_sched_functions(addr))
70 return;
71
72 if (trace->skip > 0) {
73 trace->skip--;
74 return;
75 }
76
77 if (trace->nr_entries < trace->max_entries)
78 trace->entries[trace->nr_entries++] = addr;
79}
80
81static const struct stacktrace_ops save_stack_ops_nosched = {
82 .warning = save_stack_warning,
83 .warning_symbol = save_stack_warning_symbol,
84 .stack = save_stack_stack,
85 .address = save_stack_address_nosched,
86};
87
40void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 88void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
41{ 89{
42 unsigned long *sp = (unsigned long *)tsk->thread.sp; 90 unsigned long *sp = (unsigned long *)tsk->thread.sp;
43 91
44 while (!kstack_end(sp)) { 92 dump_trace(current, NULL, sp, &save_stack_ops_nosched, trace);
45 unsigned long addr = *sp++;
46
47 if (__kernel_text_address(addr)) {
48 if (in_sched_functions(addr))
49 break;
50 if (trace->skip > 0)
51 trace->skip--;
52 else
53 trace->entries[trace->nr_entries++] = addr;
54 if (trace->nr_entries >= trace->max_entries)
55 break;
56 }
57 }
58} 93}
59EXPORT_SYMBOL_GPL(save_stack_trace_tsk); 94EXPORT_SYMBOL_GPL(save_stack_trace_tsk);