diff options
-rw-r--r-- | arch/sparc/kernel/perf_event.c | 14 | ||||
-rw-r--r-- | arch/sparc/kernel/stacktrace.c | 23 | ||||
-rw-r--r-- | arch/sparc/kernel/traps_64.c | 14 |
3 files changed, 50 insertions, 1 deletions
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index e2771939341d..34ce49f80eac 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 | ||
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 | ||
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 9da57f032983..42ad2ba85010 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/kdebug.h> | 19 | #include <linux/kdebug.h> |
20 | #include <linux/ftrace.h> | ||
20 | #include <linux/gfp.h> | 21 | #include <linux/gfp.h> |
21 | 22 | ||
22 | #include <asm/smp.h> | 23 | #include <asm/smp.h> |
@@ -2154,6 +2155,9 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) | |||
2154 | unsigned long fp, thread_base, ksp; | 2155 | unsigned long fp, thread_base, ksp; |
2155 | struct thread_info *tp; | 2156 | struct thread_info *tp; |
2156 | int count = 0; | 2157 | int count = 0; |
2158 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
2159 | int graph = 0; | ||
2160 | #endif | ||
2157 | 2161 | ||
2158 | ksp = (unsigned long) _ksp; | 2162 | ksp = (unsigned long) _ksp; |
2159 | if (!tsk) | 2163 | if (!tsk) |
@@ -2193,6 +2197,16 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) | |||
2193 | } | 2197 | } |
2194 | 2198 | ||
2195 | printk(" [%016lx] %pS\n", pc, (void *) pc); | 2199 | printk(" [%016lx] %pS\n", pc, (void *) pc); |
2200 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
2201 | if ((pc + 8UL) == (unsigned long) &return_to_handler) { | ||
2202 | int index = tsk->curr_ret_stack; | ||
2203 | if (tsk->ret_stack && index >= graph) { | ||
2204 | pc = tsk->ret_stack[index - graph].ret; | ||
2205 | printk(" [%016lx] %pS\n", pc, (void *) pc); | ||
2206 | graph++; | ||
2207 | } | ||
2208 | } | ||
2209 | #endif | ||
2196 | } while (++count < 16); | 2210 | } while (++count < 16); |
2197 | } | 2211 | } |
2198 | 2212 | ||