From aa6f4d2b6547a9949d87c9b09a872a7015366588 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 14 May 2015 18:19:03 +0200 Subject: CRIS: add STACKTRACE_SUPPORT Add stacktrace support, which is required for lockdep and tracing. The stack tracing simply looks at all kernel text symbols found on the stack, similar to the trap stack dumping code, which can also be converted to use this. Signed-off-by: Rabin Vincent Signed-off-by: Jesper Nilsson --- arch/cris/Kconfig | 3 ++ arch/cris/include/asm/stacktrace.h | 8 ++++ arch/cris/kernel/Makefile | 1 + arch/cris/kernel/stacktrace.c | 76 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 arch/cris/include/asm/stacktrace.h create mode 100644 arch/cris/kernel/stacktrace.c diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index e7ba2d4bdd4f..61f4acceb9d4 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -40,6 +40,9 @@ config TRACE_IRQFLAGS_SUPPORT depends on ETRAX_ARCH_V32 def_bool y +config STACKTRACE_SUPPORT + def_bool y + config CRIS bool default y diff --git a/arch/cris/include/asm/stacktrace.h b/arch/cris/include/asm/stacktrace.h new file mode 100644 index 000000000000..2d90856943ad --- /dev/null +++ b/arch/cris/include/asm/stacktrace.h @@ -0,0 +1,8 @@ +#ifndef __CRIS_STACKTRACE_H +#define __CRIS_STACKTRACE_H + +void walk_stackframe(unsigned long sp, + int (*fn)(unsigned long addr, void *data), + void *data); + +#endif diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile index edef71f12bb8..5fae398ca915 100644 --- a/arch/cris/kernel/Makefile +++ b/arch/cris/kernel/Makefile @@ -8,6 +8,7 @@ extra-y := vmlinux.lds obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o obj-y += devicetree.o +obj-y += stacktrace.o obj-$(CONFIG_MODULES) += crisksyms.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/cris/kernel/stacktrace.c b/arch/cris/kernel/stacktrace.c new file mode 100644 index 000000000000..99838c74456d --- /dev/null +++ b/arch/cris/kernel/stacktrace.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include + +void walk_stackframe(unsigned long sp, + int (*fn)(unsigned long addr, void *data), + void *data) +{ + unsigned long high = ALIGN(sp, THREAD_SIZE); + + for (; sp <= high - 4; sp += 4) { + unsigned long addr = *(unsigned long *) sp; + + if (!kernel_text_address(addr)) + continue; + + if (fn(addr, data)) + break; + } +} + +struct stack_trace_data { + struct stack_trace *trace; + unsigned int no_sched_functions; + unsigned int skip; +}; + +#ifdef CONFIG_STACKTRACE + +static int save_trace(unsigned long addr, void *d) +{ + struct stack_trace_data *data = d; + struct stack_trace *trace = data->trace; + + if (data->no_sched_functions && in_sched_functions(addr)) + return 0; + + if (data->skip) { + data->skip--; + return 0; + } + + trace->entries[trace->nr_entries++] = addr; + + return trace->nr_entries >= trace->max_entries; +} + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + struct stack_trace_data data; + unsigned long sp; + + data.trace = trace; + data.skip = trace->skip; + + if (tsk != current) { + data.no_sched_functions = 1; + sp = tsk->thread.ksp; + } else { + data.no_sched_functions = 0; + sp = rdsp(); + } + + walk_stackframe(sp, save_trace, &data); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} + +void save_stack_trace(struct stack_trace *trace) +{ + save_stack_trace_tsk(current, trace); +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +#endif /* CONFIG_STACKTRACE */ -- cgit v1.2.3-58-ga151