Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / microblaze / kernel / traps.c
index 75e49202a5ed6bcb14cf4d629f082349685fae1a..ba034d421ec27933f54d4950a3e7d3cec2761cc2 100644 (file)
 
 #include <asm/exceptions.h>
 #include <asm/system.h>
+#include <asm/unwind.h>
 
 void trap_init(void)
 {
        __enable_hw_exceptions();
 }
 
-static unsigned long kstack_depth_to_print = 24;
+static unsigned long kstack_depth_to_print;    /* 0 == entire stack */
 
 static int __init kstack_setup(char *s)
 {
@@ -30,31 +31,47 @@ static int __init kstack_setup(char *s)
 }
 __setup("kstack=", kstack_setup);
 
-void show_trace(struct task_struct *task, unsigned long *stack)
+void show_stack(struct task_struct *task, unsigned long *sp)
 {
-       unsigned long addr;
-
-       if (!stack)
-               stack = (unsigned long *)&stack;
+       unsigned long words_to_show;
+       u32 fp = (u32) sp;
+
+       if (fp == 0) {
+               if (task) {
+                       fp = ((struct thread_info *)
+                               (task->stack))->cpu_context.r1;
+               } else {
+                       /* Pick up caller of dump_stack() */
+                       fp = (u32)&sp - 8;
+               }
+       }
 
-       printk(KERN_NOTICE "Call Trace: ");
-#ifdef CONFIG_KALLSYMS
-       printk(KERN_NOTICE "\n");
-#endif
-       while (!kstack_end(stack)) {
-               addr = *stack++;
-               /*
-                * If the address is either in the text segment of the
-                * kernel, or in the region which contains vmalloc'ed
-                * memory, it *may* be the address of a calling
-                * routine; if so, print it so that someone tracing
-                * down the cause of the crash will be able to figure
-                * out the call path that was taken.
-                */
-               if (kernel_text_address(addr))
-                       print_ip_sym(addr);
+       words_to_show = (THREAD_SIZE - (fp & (THREAD_SIZE - 1))) >> 2;
+       if (kstack_depth_to_print && (words_to_show > kstack_depth_to_print))
+               words_to_show = kstack_depth_to_print;
+
+       pr_info("Kernel Stack:\n");
+
+       /*
+        * Make the first line an 'odd' size if necessary to get
+        * remaining lines to start at an address multiple of 0x10
+        */
+       if (fp & 0xF) {
+               unsigned long line1_words = (0x10 - (fp & 0xF)) >> 2;
+               if (line1_words < words_to_show) {
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 32,
+                                      4, (void *)fp, line1_words << 2, 0);
+                       fp += line1_words << 2;
+                       words_to_show -= line1_words;
+               }
        }
-       printk(KERN_NOTICE "\n");
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 32, 4, (void *)fp,
+                      words_to_show << 2, 0);
+       printk(KERN_INFO "\n\n");
+
+       pr_info("Call Trace:\n");
+       microblaze_unwind(task, NULL);
+       pr_info("\n");
 
        if (!task)
                task = current;
@@ -62,34 +79,6 @@ void show_trace(struct task_struct *task, unsigned long *stack)
        debug_show_held_locks(task);
 }
 
-void show_stack(struct task_struct *task, unsigned long *sp)
-{
-       unsigned long *stack;
-       int i;
-
-       if (sp == NULL) {
-               if (task)
-                       sp = (unsigned long *) ((struct thread_info *)
-                                               (task->stack))->cpu_context.r1;
-               else
-                       sp = (unsigned long *)&sp;
-       }
-
-       stack = sp;
-
-       printk(KERN_INFO "\nStack:\n  ");
-
-       for (i = 0; i < kstack_depth_to_print; i++) {
-               if (kstack_end(sp))
-                       break;
-               if (i && ((i % 8) == 0))
-                       printk("\n  ");
-               printk("%08lx ", *sp++);
-       }
-       printk("\n");
-       show_trace(task, stack);
-}
-
 void dump_stack(void)
 {
        show_stack(NULL, NULL);