[PATCH 3/5] CRIS: add STACKTRACE_SUPPORT

From: Rabin Vincent
Date: Thu May 14 2015 - 12:46:01 EST


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 <rabin@xxxxxx>
---
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 efe829e..bb6a4f9 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 0000000..2d90856
--- /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 edef71f..5fae398 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 0000000..99838c7
--- /dev/null
+++ b/arch/cris/kernel/stacktrace.c
@@ -0,0 +1,76 @@
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/stacktrace.h>
+#include <asm/stacktrace.h>
+
+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 */
--
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/