microblaze: Add stack unwinder

Implement intelligent backtracing by searching for stack frame creation,
and emitting only return addresses. Use print_hex_dump() to display the
entire binary kernel stack.

Limitation: MMU kernels are not currently able to trace beyond a system trap
(interrupt, syscall, etc.). It is the intent of this patch to provide
infrastructure that can be extended to add this capability later.

Changes from V1:
* Removed checks in find_frame_creation() that prevented location of the frame
  creation instruction in heavily optimized code
* Various formatting/commenting/file location tweaks per review comments
* Dropped Kconfig option to enable STACKTRACE as something logically separate

Signed-off-by: Steven J. Magnani <steve@digidescorp.com>
diff --git a/arch/microblaze/kernel/stacktrace.c b/arch/microblaze/kernel/stacktrace.c
index 123692f..84bc668 100644
--- a/arch/microblaze/kernel/stacktrace.c
+++ b/arch/microblaze/kernel/stacktrace.c
@@ -14,52 +14,18 @@
 #include <linux/thread_info.h>
 #include <linux/ptrace.h>
 #include <linux/module.h>
+#include <asm/unwind.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;
-		}
-	}
+	/* Exclude our helper functions from the trace*/
+	trace->skip += 2;
+	microblaze_unwind(NULL, trace);
 }
 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;
-		}
-	}
+	microblaze_unwind(tsk, trace);
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);