aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kconfig3
-rw-r--r--arch/powerpc/kernel/stacktrace.c37
2 files changed, 30 insertions, 10 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index aaf99892d1b3..5e2185432ad3 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -53,6 +53,9 @@ config STACKTRACE_SUPPORT
53 bool 53 bool
54 default y 54 default y
55 55
56config HAVE_LATENCYTOP_SUPPORT
57 def_bool y
58
56config TRACE_IRQFLAGS_SUPPORT 59config TRACE_IRQFLAGS_SUPPORT
57 bool 60 bool
58 depends on PPC64 61 depends on PPC64
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 962944038430..6a4fb003fa54 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -10,33 +10,34 @@
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 */ 11 */
12 12
13#include <linux/module.h>
13#include <linux/sched.h> 14#include <linux/sched.h>
14#include <linux/stacktrace.h> 15#include <linux/stacktrace.h>
15#include <asm/ptrace.h> 16#include <asm/ptrace.h>
17#include <asm/processor.h>
16 18
17/* 19/*
18 * Save stack-backtrace addresses into a stack_trace buffer. 20 * Save stack-backtrace addresses into a stack_trace buffer.
19 */ 21 */
20void save_stack_trace(struct stack_trace *trace) 22static void save_context_stack(struct stack_trace *trace, unsigned long sp,
23 struct task_struct *tsk, int savesched)
21{ 24{
22 unsigned long sp;
23
24 asm("mr %0,1" : "=r" (sp));
25
26 for (;;) { 25 for (;;) {
27 unsigned long *stack = (unsigned long *) sp; 26 unsigned long *stack = (unsigned long *) sp;
28 unsigned long newsp, ip; 27 unsigned long newsp, ip;
29 28
30 if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) 29 if (!validate_sp(sp, tsk, STACK_FRAME_OVERHEAD))
31 return; 30 return;
32 31
33 newsp = stack[0]; 32 newsp = stack[0];
34 ip = stack[STACK_FRAME_LR_SAVE]; 33 ip = stack[STACK_FRAME_LR_SAVE];
35 34
36 if (!trace->skip) 35 if (savesched || !in_sched_functions(ip)) {
37 trace->entries[trace->nr_entries++] = ip; 36 if (!trace->skip)
38 else 37 trace->entries[trace->nr_entries++] = ip;
39 trace->skip--; 38 else
39 trace->skip--;
40 }
40 41
41 if (trace->nr_entries >= trace->max_entries) 42 if (trace->nr_entries >= trace->max_entries)
42 return; 43 return;
@@ -44,3 +45,19 @@ void save_stack_trace(struct stack_trace *trace)
44 sp = newsp; 45 sp = newsp;
45 } 46 }
46} 47}
48
49void save_stack_trace(struct stack_trace *trace)
50{
51 unsigned long sp;
52
53 asm("mr %0,1" : "=r" (sp));
54
55 save_context_stack(trace, sp, current, 1);
56}
57EXPORT_SYMBOL_GPL(save_stack_trace);
58
59void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
60{
61 save_context_stack(trace, tsk->thread.regs->gpr[1], tsk, 0);
62}
63EXPORT_SYMBOL_GPL(save_stack_trace_tsk);