aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/stacktrace.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-04-21 06:08:11 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-21 06:08:11 -0400
commit667f0cee3e0321151aa7a1a5222afe67ca4be0ea (patch)
tree5f4a7a5c228a21e893f95774ca95f9925abf4b1f /arch/sparc/kernel/stacktrace.c
parent87e8f0e3e6d0b720a2462ebc5667eaa462752f74 (diff)
sparc64: Fix stack dumping and tracing when function graph is enabled.
Like x86, when the function graph tracer is enabled, emit the ftrace stub as well as the program counter it will be transformed back into. We duplicate a lot of similar stack walking logic in 3 or 4 spots, so eventually we should consolidate things like x86 does. Thanks to Frederic Weisbecker for pointing this out. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/stacktrace.c')
-rw-r--r--arch/sparc/kernel/stacktrace.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/arch/sparc/kernel/stacktrace.c b/arch/sparc/kernel/stacktrace.c
index acb12f673757..3e0815349630 100644
--- a/arch/sparc/kernel/stacktrace.c
+++ b/arch/sparc/kernel/stacktrace.c
@@ -1,6 +1,7 @@
1#include <linux/sched.h> 1#include <linux/sched.h>
2#include <linux/stacktrace.h> 2#include <linux/stacktrace.h>
3#include <linux/thread_info.h> 3#include <linux/thread_info.h>
4#include <linux/ftrace.h>
4#include <linux/module.h> 5#include <linux/module.h>
5#include <asm/ptrace.h> 6#include <asm/ptrace.h>
6#include <asm/stacktrace.h> 7#include <asm/stacktrace.h>
@@ -12,6 +13,10 @@ static void __save_stack_trace(struct thread_info *tp,
12 bool skip_sched) 13 bool skip_sched)
13{ 14{
14 unsigned long ksp, fp; 15 unsigned long ksp, fp;
16#ifdef CONFIG_FUNCTION_GRAPH_TRACER
17 struct task_struct *t;
18 int graph = 0;
19#endif
15 20
16 if (tp == current_thread_info()) { 21 if (tp == current_thread_info()) {
17 stack_trace_flush(); 22 stack_trace_flush();
@@ -21,6 +26,9 @@ static void __save_stack_trace(struct thread_info *tp,
21 } 26 }
22 27
23 fp = ksp + STACK_BIAS; 28 fp = ksp + STACK_BIAS;
29#ifdef CONFIG_FUNCTION_GRAPH_TRACER
30 t = tp->task;
31#endif
24 do { 32 do {
25 struct sparc_stackf *sf; 33 struct sparc_stackf *sf;
26 struct pt_regs *regs; 34 struct pt_regs *regs;
@@ -44,8 +52,21 @@ static void __save_stack_trace(struct thread_info *tp,
44 52
45 if (trace->skip > 0) 53 if (trace->skip > 0)
46 trace->skip--; 54 trace->skip--;
47 else if (!skip_sched || !in_sched_functions(pc)) 55 else if (!skip_sched || !in_sched_functions(pc)) {
48 trace->entries[trace->nr_entries++] = pc; 56 trace->entries[trace->nr_entries++] = pc;
57#ifdef CONFIG_FUNCTION_GRAPH_TRACER
58 if ((pc + 8UL) == (unsigned long) &return_to_handler) {
59 int index = t->curr_ret_stack;
60 if (t->ret_stack && index >= graph) {
61 pc = t->ret_stack[index - graph].ret;
62 if (trace->nr_entries <
63 trace->max_entries)
64 trace->entries[trace->nr_entries++] = pc;
65 graph++;
66 }
67 }
68#endif
69 }
49 } while (trace->nr_entries < trace->max_entries); 70 } while (trace->nr_entries < trace->max_entries);
50} 71}
51 72