summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/microblaze/Kconfig3
-rw-r--r--arch/microblaze/kernel/Makefile1
-rw-r--r--arch/microblaze/kernel/stacktrace.c65
3 files changed, 69 insertions, 0 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index bbd8327f189..8e1c4f7d3e6 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -57,6 +57,9 @@ config GENERIC_GPIO
config GENERIC_CSUM
def_bool y
+config STACKTRACE_SUPPORT
+ def_bool y
+
config PCI
def_bool n
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
index fddd0c403d4..c465a5c4669 100644
--- a/arch/microblaze/kernel/Makefile
+++ b/arch/microblaze/kernel/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_SELFMOD) += selfmod.o
obj-$(CONFIG_HEART_BEAT) += heartbeat.o
obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
obj-$(CONFIG_MMU) += misc.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += entry$(MMU).o
diff --git a/arch/microblaze/kernel/stacktrace.c b/arch/microblaze/kernel/stacktrace.c
new file mode 100644
index 00000000000..123692f2264
--- /dev/null
+++ b/arch/microblaze/kernel/stacktrace.c
@@ -0,0 +1,65 @@
+/*
+ * Stack trace support for Microblaze.
+ *
+ * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2009 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <linux/ptrace.h>
+#include <linux/module.h>
+
+/* FIXME initial support */
+void save_stack_trace(struct stack_trace *trace)
+{
+ unsigned long *sp;
+ unsigned long addr;
+ asm("addik %0, r1, 0" : "=r" (sp));
+
+ while (!kstack_end(sp)) {
+ addr = *sp++;
+ if (__kernel_text_address(addr)) {
+ if (trace->skip > 0)
+ trace->skip--;
+ else
+ trace->entries[trace->nr_entries++] = addr;
+
+ if (trace->nr_entries >= trace->max_entries)
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+ unsigned int *sp;
+ unsigned long addr;
+
+ struct thread_info *ti = task_thread_info(tsk);
+
+ if (tsk == current)
+ asm("addik %0, r1, 0" : "=r" (sp));
+ else
+ sp = (unsigned int *)ti->cpu_context.r1;
+
+ while (!kstack_end(sp)) {
+ addr = *sp++;
+ if (__kernel_text_address(addr)) {
+ if (trace->skip > 0)
+ trace->skip--;
+ else
+ trace->entries[trace->nr_entries++] = addr;
+
+ if (trace->nr_entries >= trace->max_entries)
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(save_stack_trace_tsk);