aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/perf_event.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/perf_event.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/perf_event.c')
-rw-r--r--arch/sparc/kernel/perf_event.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index e2771939341..34ce49f80ea 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -14,6 +14,7 @@
14 14
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16#include <linux/kprobes.h> 16#include <linux/kprobes.h>
17#include <linux/ftrace.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/kdebug.h> 19#include <linux/kdebug.h>
19#include <linux/mutex.h> 20#include <linux/mutex.h>
@@ -1276,6 +1277,9 @@ static void perf_callchain_kernel(struct pt_regs *regs,
1276 struct perf_callchain_entry *entry) 1277 struct perf_callchain_entry *entry)
1277{ 1278{
1278 unsigned long ksp, fp; 1279 unsigned long ksp, fp;
1280#ifdef CONFIG_FUNCTION_GRAPH_TRACER
1281 int graph = 0;
1282#endif
1279 1283
1280 callchain_store(entry, PERF_CONTEXT_KERNEL); 1284 callchain_store(entry, PERF_CONTEXT_KERNEL);
1281 callchain_store(entry, regs->tpc); 1285 callchain_store(entry, regs->tpc);
@@ -1303,6 +1307,16 @@ static void perf_callchain_kernel(struct pt_regs *regs,
1303 fp = (unsigned long)sf->fp + STACK_BIAS; 1307 fp = (unsigned long)sf->fp + STACK_BIAS;
1304 } 1308 }
1305 callchain_store(entry, pc); 1309 callchain_store(entry, pc);
1310#ifdef CONFIG_FUNCTION_GRAPH_TRACER
1311 if ((pc + 8UL) == (unsigned long) &return_to_handler) {
1312 int index = current->curr_ret_stack;
1313 if (current->ret_stack && index >= graph) {
1314 pc = current->ret_stack[index - graph].ret;
1315 callchain_store(entry, pc);
1316 graph++;
1317 }
1318 }
1319#endif
1306 } while (entry->nr < PERF_MAX_STACK_DEPTH); 1320 } while (entry->nr < PERF_MAX_STACK_DEPTH);
1307} 1321}
1308 1322