From eecac38b0423a69715073ecbde581dafd1abb28b Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Mon, 24 Jul 2017 21:44:35 +0900 Subject: 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: [] show_stack+0x3c/0x58 [] dump_stack+0xa8/0xe4 [] __cpu_up+0x64/0x130 [] bringup_cpu+0x3c/0x178 [] cpuhp_invoke_callback+0xa8/0x1fc [] cpuhp_up_callbacks+0x44/0x14c [] cpu_up+0x14c/0x1bc [] smp_init+0x104/0x15c [] ? kernel_init+0x0/0x140 [] kernel_init_freeable+0xbc/0x25c [] ? kernel_init+0x0/0x140 [] kernel_init+0x1c/0x140 [] ? schedule_tail+0x18/0xa0 [] ret_from_fork+0x1c/0x9c Signed-off-by: Stafford Horne --- arch/openrisc/kernel/stacktrace.c | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 arch/openrisc/kernel/stacktrace.c (limited to 'arch/openrisc/kernel/stacktrace.c') 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 + * + * 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 +#include +#include +#include + +#include +#include + +/* + * 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); -- cgit v1.2.3