diff options
| -rw-r--r-- | arch/powerpc/Kconfig | 3 | ||||
| -rw-r--r-- | arch/powerpc/kernel/stacktrace.c | 37 |
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 | ||
| 56 | config HAVE_LATENCYTOP_SUPPORT | ||
| 57 | def_bool y | ||
| 58 | |||
| 56 | config TRACE_IRQFLAGS_SUPPORT | 59 | config 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 | */ |
| 20 | void save_stack_trace(struct stack_trace *trace) | 22 | static 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 | |||
| 49 | void 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 | } | ||
| 57 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
| 58 | |||
| 59 | void 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 | } | ||
| 63 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk); | ||
