diff options
| -rw-r--r-- | arch/s390/Kconfig | 3 | ||||
| -rw-r--r-- | arch/s390/kernel/stacktrace.c | 31 |
2 files changed, 26 insertions, 8 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index f0e7ccf1b206..92a4f7b4323a 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -16,6 +16,9 @@ config LOCKDEP_SUPPORT | |||
| 16 | config STACKTRACE_SUPPORT | 16 | config STACKTRACE_SUPPORT |
| 17 | def_bool y | 17 | def_bool y |
| 18 | 18 | ||
| 19 | config HAVE_LATENCYTOP_SUPPORT | ||
| 20 | def_bool y | ||
| 21 | |||
| 19 | config RWSEM_GENERIC_SPINLOCK | 22 | config RWSEM_GENERIC_SPINLOCK |
| 20 | bool | 23 | bool |
| 21 | 24 | ||
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c index da6924729964..85e46a5d0e08 100644 --- a/arch/s390/kernel/stacktrace.c +++ b/arch/s390/kernel/stacktrace.c | |||
| @@ -14,7 +14,8 @@ | |||
| 14 | static unsigned long save_context_stack(struct stack_trace *trace, | 14 | static unsigned long save_context_stack(struct stack_trace *trace, |
| 15 | unsigned long sp, | 15 | unsigned long sp, |
| 16 | unsigned long low, | 16 | unsigned long low, |
| 17 | unsigned long high) | 17 | unsigned long high, |
| 18 | int savesched) | ||
| 18 | { | 19 | { |
| 19 | struct stack_frame *sf; | 20 | struct stack_frame *sf; |
| 20 | struct pt_regs *regs; | 21 | struct pt_regs *regs; |
| @@ -47,10 +48,12 @@ static unsigned long save_context_stack(struct stack_trace *trace, | |||
| 47 | return sp; | 48 | return sp; |
| 48 | regs = (struct pt_regs *)sp; | 49 | regs = (struct pt_regs *)sp; |
| 49 | addr = regs->psw.addr & PSW_ADDR_INSN; | 50 | addr = regs->psw.addr & PSW_ADDR_INSN; |
| 50 | if (!trace->skip) | 51 | if (savesched || !in_sched_functions(addr)) { |
| 51 | trace->entries[trace->nr_entries++] = addr; | 52 | if (!trace->skip) |
| 52 | else | 53 | trace->entries[trace->nr_entries++] = addr; |
| 53 | trace->skip--; | 54 | else |
| 55 | trace->skip--; | ||
| 56 | } | ||
| 54 | if (trace->nr_entries >= trace->max_entries) | 57 | if (trace->nr_entries >= trace->max_entries) |
| 55 | return sp; | 58 | return sp; |
| 56 | low = sp; | 59 | low = sp; |
| @@ -66,15 +69,27 @@ void save_stack_trace(struct stack_trace *trace) | |||
| 66 | orig_sp = sp & PSW_ADDR_INSN; | 69 | orig_sp = sp & PSW_ADDR_INSN; |
| 67 | new_sp = save_context_stack(trace, orig_sp, | 70 | new_sp = save_context_stack(trace, orig_sp, |
| 68 | S390_lowcore.panic_stack - PAGE_SIZE, | 71 | S390_lowcore.panic_stack - PAGE_SIZE, |
| 69 | S390_lowcore.panic_stack); | 72 | S390_lowcore.panic_stack, 1); |
| 70 | if (new_sp != orig_sp) | 73 | if (new_sp != orig_sp) |
| 71 | return; | 74 | return; |
| 72 | new_sp = save_context_stack(trace, new_sp, | 75 | new_sp = save_context_stack(trace, new_sp, |
| 73 | S390_lowcore.async_stack - ASYNC_SIZE, | 76 | S390_lowcore.async_stack - ASYNC_SIZE, |
| 74 | S390_lowcore.async_stack); | 77 | S390_lowcore.async_stack, 1); |
| 75 | if (new_sp != orig_sp) | 78 | if (new_sp != orig_sp) |
| 76 | return; | 79 | return; |
| 77 | save_context_stack(trace, new_sp, | 80 | save_context_stack(trace, new_sp, |
| 78 | S390_lowcore.thread_info, | 81 | S390_lowcore.thread_info, |
| 79 | S390_lowcore.thread_info + THREAD_SIZE); | 82 | S390_lowcore.thread_info + THREAD_SIZE, 1); |
| 83 | } | ||
| 84 | |||
| 85 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | ||
| 86 | { | ||
| 87 | unsigned long sp, low, high; | ||
| 88 | |||
| 89 | sp = tsk->thread.ksp & PSW_ADDR_INSN; | ||
| 90 | low = (unsigned long) task_stack_page(tsk); | ||
| 91 | high = (unsigned long) task_pt_regs(tsk); | ||
| 92 | save_context_stack(trace, sp, low, high, 0); | ||
| 93 | if (trace->nr_entries < trace->max_entries) | ||
| 94 | trace->entries[trace->nr_entries++] = ULONG_MAX; | ||
| 80 | } | 95 | } |
