diff options
author | Stafford Horne <shorne@gmail.com> | 2017-07-24 15:44:35 +0300 |
---|---|---|
committer | Stafford Horne <shorne@gmail.com> | 2017-11-03 08:01:15 +0300 |
commit | eecac38b0423a69715073ecbde581dafd1abb28b (patch) | |
tree | 6c675e769ef8a5f0fb81b4ea2dd7596be9c5aebd /arch/openrisc/kernel/stacktrace.c | |
parent | 306e5e50a32140452849fff42fca104511fd6668 (diff) | |
download | linux-eecac38b0423a69715073ecbde581dafd1abb28b.tar.xz |
openrisc: support framepointers and STACKTRACE_SUPPORT
For lockdep support a reliable stack trace mechanism is needed. This
patch adds support in OpenRISC for the stacktrace framework, implemented
by a simple unwinder api. The unwinder api supports both framepointer
and basic stack tracing.
The unwinder is now used to replace the stack_dump() implementation as
well. The new traces are inline with other architectures trace format:
Call trace:
[<c0004448>] show_stack+0x3c/0x58
[<c031c940>] dump_stack+0xa8/0xe4
[<c0008104>] __cpu_up+0x64/0x130
[<c000d268>] bringup_cpu+0x3c/0x178
[<c000d038>] cpuhp_invoke_callback+0xa8/0x1fc
[<c000d680>] cpuhp_up_callbacks+0x44/0x14c
[<c000e400>] cpu_up+0x14c/0x1bc
[<c041da60>] smp_init+0x104/0x15c
[<c033843c>] ? kernel_init+0x0/0x140
[<c0415e04>] kernel_init_freeable+0xbc/0x25c
[<c033843c>] ? kernel_init+0x0/0x140
[<c0338458>] kernel_init+0x1c/0x140
[<c003a174>] ? schedule_tail+0x18/0xa0
[<c0006b80>] ret_from_fork+0x1c/0x9c
Signed-off-by: Stafford Horne <shorne@gmail.com>
Diffstat (limited to 'arch/openrisc/kernel/stacktrace.c')
-rw-r--r-- | arch/openrisc/kernel/stacktrace.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/arch/openrisc/kernel/stacktrace.c b/arch/openrisc/kernel/stacktrace.c new file mode 100644 index 000000000000..43f140a28bc7 --- /dev/null +++ b/arch/openrisc/kernel/stacktrace.c @@ -0,0 +1,86 @@ +/* + * Stack trace utility for OpenRISC + * + * Copyright (C) 2017 Stafford Horne <shorne@gmail.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + * Losely based on work from sh and powerpc. + */ + +#include <linux/export.h> +#include <linux/sched.h> +#include <linux/sched/debug.h> +#include <linux/stacktrace.h> + +#include <asm/processor.h> +#include <asm/unwinder.h> + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +static void +save_stack_address(void *data, unsigned long addr, int reliable) +{ + struct stack_trace *trace = data; + + if (!reliable) + return; + + if (trace->skip > 0) { + trace->skip--; + return; + } + + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = addr; +} + +void save_stack_trace(struct stack_trace *trace) +{ + unwind_stack(trace, (unsigned long *) &trace, save_stack_address); +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +static void +save_stack_address_nosched(void *data, unsigned long addr, int reliable) +{ + struct stack_trace *trace = (struct stack_trace *)data; + + if (!reliable) + return; + + if (in_sched_functions(addr)) + return; + + if (trace->skip > 0) { + trace->skip--; + return; + } + + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = addr; +} + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + unsigned long *sp = NULL; + + if (tsk == current) + sp = (unsigned long *) &sp; + else + sp = (unsigned long *) KSTK_ESP(tsk); + + unwind_stack(trace, sp, save_stack_address_nosched); +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); + +void +save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) +{ + unwind_stack(trace, (unsigned long *) regs->sp, + save_stack_address_nosched); +} +EXPORT_SYMBOL_GPL(save_stack_trace_regs); |