aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-12-16 23:40:33 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-17 03:56:19 -0500
commit61c1917f47f73c968e92d04d15370b1dc3ec4592 (patch)
treea20445bcaf484d270bd6cb8de5969702110af687 /arch
parent5b74ed4729ad2b2017453add68104a83206caefb (diff)
perf events, x86/stacktrace: Make stack walking optional
The current print_context_stack helper that does the stack walking job is good for usual stacktraces as it walks through all the stack and reports even addresses that look unreliable, which is nice when we don't have frame pointers for example. But we have users like perf that only require reliable stacktraces, and those may want a more adapted stack walker, so lets make this function a callback in stacktrace_ops that users can tune for their needs. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1261024834-5336-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/stacktrace.h18
-rw-r--r--arch/x86/kernel/cpu/perf_event.c1
-rw-r--r--arch/x86/kernel/dumpstack.c9
-rw-r--r--arch/x86/kernel/dumpstack.h6
-rw-r--r--arch/x86/kernel/dumpstack_32.c2
-rw-r--r--arch/x86/kernel/dumpstack_64.c4
-rw-r--r--arch/x86/kernel/stacktrace.c18
-rw-r--r--arch/x86/oprofile/backtrace.c9
8 files changed, 42 insertions, 25 deletions
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index cf86a5e73815..6c75151a3cca 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -5,6 +5,23 @@ extern int kstack_depth_to_print;
5 5
6int x86_is_stack_id(int id, char *name); 6int x86_is_stack_id(int id, char *name);
7 7
8struct thread_info;
9struct stacktrace_ops;
10
11typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
12 unsigned long *stack,
13 unsigned long bp,
14 const struct stacktrace_ops *ops,
15 void *data,
16 unsigned long *end,
17 int *graph);
18
19extern unsigned long
20print_context_stack(struct thread_info *tinfo,
21 unsigned long *stack, unsigned long bp,
22 const struct stacktrace_ops *ops, void *data,
23 unsigned long *end, int *graph);
24
8/* Generic stack tracer with callbacks */ 25/* Generic stack tracer with callbacks */
9 26
10struct stacktrace_ops { 27struct stacktrace_ops {
@@ -14,6 +31,7 @@ struct stacktrace_ops {
14 void (*address)(void *data, unsigned long address, int reliable); 31 void (*address)(void *data, unsigned long address, int reliable);
15 /* On negative return stop dumping */ 32 /* On negative return stop dumping */
16 int (*stack)(void *data, char *name); 33 int (*stack)(void *data, char *name);
34 walk_stack_t walk_stack;
17}; 35};
18 36
19void dump_trace(struct task_struct *tsk, struct pt_regs *regs, 37void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 45506d5dd8df..d3802ee5a416 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -2336,6 +2336,7 @@ static const struct stacktrace_ops backtrace_ops = {
2336 .warning_symbol = backtrace_warning_symbol, 2336 .warning_symbol = backtrace_warning_symbol,
2337 .stack = backtrace_stack, 2337 .stack = backtrace_stack,
2338 .address = backtrace_address, 2338 .address = backtrace_address,
2339 .walk_stack = print_context_stack,
2339}; 2340};
2340 2341
2341#include "../dumpstack.h" 2342#include "../dumpstack.h"
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 0a0aa1cec8f1..8aaa119b7cad 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -141,10 +141,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
141} 141}
142 142
143static const struct stacktrace_ops print_trace_ops = { 143static const struct stacktrace_ops print_trace_ops = {
144 .warning = print_trace_warning, 144 .warning = print_trace_warning,
145 .warning_symbol = print_trace_warning_symbol, 145 .warning_symbol = print_trace_warning_symbol,
146 .stack = print_trace_stack, 146 .stack = print_trace_stack,
147 .address = print_trace_address, 147 .address = print_trace_address,
148 .walk_stack = print_context_stack,
148}; 149};
149 150
150void 151void
diff --git a/arch/x86/kernel/dumpstack.h b/arch/x86/kernel/dumpstack.h
index 81086c227ab7..4fd1420faffa 100644
--- a/arch/x86/kernel/dumpstack.h
+++ b/arch/x86/kernel/dumpstack.h
@@ -14,12 +14,6 @@
14#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :) 14#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
15#endif 15#endif
16 16
17extern unsigned long
18print_context_stack(struct thread_info *tinfo,
19 unsigned long *stack, unsigned long bp,
20 const struct stacktrace_ops *ops, void *data,
21 unsigned long *end, int *graph);
22
23extern void 17extern void
24show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, 18show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
25 unsigned long *stack, unsigned long bp, char *log_lvl); 19 unsigned long *stack, unsigned long bp, char *log_lvl);
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index e0ed4c7abb62..ae775ca47b25 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -58,7 +58,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
58 58
59 context = (struct thread_info *) 59 context = (struct thread_info *)
60 ((unsigned long)stack & (~(THREAD_SIZE - 1))); 60 ((unsigned long)stack & (~(THREAD_SIZE - 1)));
61 bp = print_context_stack(context, stack, bp, ops, data, NULL, &graph); 61 bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);
62 62
63 stack = (unsigned long *)context->previous_esp; 63 stack = (unsigned long *)context->previous_esp;
64 if (!stack) 64 if (!stack)
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index b13af53883aa..0ad9597073f5 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -188,8 +188,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
188 if (ops->stack(data, id) < 0) 188 if (ops->stack(data, id) < 0)
189 break; 189 break;
190 190
191 bp = print_context_stack(tinfo, stack, bp, ops, 191 bp = ops->walk_stack(tinfo, stack, bp, ops,
192 data, estack_end, &graph); 192 data, estack_end, &graph);
193 ops->stack(data, "<EOE>"); 193 ops->stack(data, "<EOE>");
194 /* 194 /*
195 * We link to the next stack via the 195 * We link to the next stack via the
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index c3eb207181fe..922eefbb3f6c 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -53,17 +53,19 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable)
53} 53}
54 54
55static const struct stacktrace_ops save_stack_ops = { 55static const struct stacktrace_ops save_stack_ops = {
56 .warning = save_stack_warning, 56 .warning = save_stack_warning,
57 .warning_symbol = save_stack_warning_symbol, 57 .warning_symbol = save_stack_warning_symbol,
58 .stack = save_stack_stack, 58 .stack = save_stack_stack,
59 .address = save_stack_address, 59 .address = save_stack_address,
60 .walk_stack = print_context_stack,
60}; 61};
61 62
62static const struct stacktrace_ops save_stack_ops_nosched = { 63static const struct stacktrace_ops save_stack_ops_nosched = {
63 .warning = save_stack_warning, 64 .warning = save_stack_warning,
64 .warning_symbol = save_stack_warning_symbol, 65 .warning_symbol = save_stack_warning_symbol,
65 .stack = save_stack_stack, 66 .stack = save_stack_stack,
66 .address = save_stack_address_nosched, 67 .address = save_stack_address_nosched,
68 .walk_stack = print_context_stack,
67}; 69};
68 70
69/* 71/*
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index 044897be021f..3855096c59b8 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -41,10 +41,11 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
41} 41}
42 42
43static struct stacktrace_ops backtrace_ops = { 43static struct stacktrace_ops backtrace_ops = {
44 .warning = backtrace_warning, 44 .warning = backtrace_warning,
45 .warning_symbol = backtrace_warning_symbol, 45 .warning_symbol = backtrace_warning_symbol,
46 .stack = backtrace_stack, 46 .stack = backtrace_stack,
47 .address = backtrace_address, 47 .address = backtrace_address,
48 .walk_stack = print_context_stack,
48}; 49};
49 50
50struct frame_head { 51struct frame_head {