]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
sh64: Convert to unwinder API.
authorPaul Mundt <lethal@linux-sh.org>
Thu, 24 May 2012 06:03:46 +0000 (15:03 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Thu, 24 May 2012 06:03:46 +0000 (15:03 +0900)
This switches over to use the sh unwinder API which brings it all in line
with the general sh routines (which we shuffle around at the same time),
and lets us kill off more sh64-specific cruft.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/include/asm/kdebug.h
arch/sh/kernel/cpu/sh5/unwind.c
arch/sh/kernel/dumpstack.c
arch/sh/kernel/traps_32.c
arch/sh/kernel/traps_64.c

index a6201f10c2730878ae987cec8c01142f96569561..8d6a831e7ba1501a54ce9292e110720b7ce38ee6 100644 (file)
@@ -10,6 +10,8 @@ enum die_val {
        DIE_SSTEP,
 };
 
+/* arch/sh/kernel/dumpstack.c */
 extern void printk_address(unsigned long address, int reliable);
+extern void dump_mem(const char *str, unsigned long bottom, unsigned long top);
 
 #endif /* __ASM_SH_KDEBUG_H */
index b205b25eaf45d6d6b0b791703ee83fe3f9e45f8b..10aed41757fc8247f9e1c271623907b31192607b 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/io.h>
+#include <asm/unwinder.h>
+#include <asm/stacktrace.h>
 
 static u8 regcache[63];
 
@@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
        return 0;
 }
 
-/* Don't put this on the stack since we'll want to call sh64_unwind
- * when we're close to underflowing the stack anyway. */
+/*
+ * Don't put this on the stack since we'll want to call in to
+ * sh64_unwinder_dump() when we're close to underflowing the stack
+ * anyway.
+ */
 static struct pt_regs here_regs;
 
 extern const char syscall_ret;
@@ -208,17 +213,19 @@ extern const char ret_from_syscall;
 extern const char ret_from_exception;
 extern const char ret_from_irq;
 
-static void sh64_unwind_inner(struct pt_regs *regs);
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+                             void *data, struct pt_regs *regs);
 
-static void unwind_nested (unsigned long pc, unsigned long fp)
+static inline void unwind_nested(const struct stacktrace_ops *ops, void *data,
+                                unsigned long pc, unsigned long fp)
 {
        if ((fp >= __MEMORY_START) &&
-           ((fp & 7) == 0)) {
-               sh64_unwind_inner((struct pt_regs *) fp);
-       }
+           ((fp & 7) == 0))
+               sh64_unwind_inner(ops, data, (struct pt_regs *)fp);
 }
 
-static void sh64_unwind_inner(struct pt_regs *regs)
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+                             void *data, struct pt_regs *regs)
 {
        unsigned long pc, fp;
        int ofs = 0;
@@ -232,29 +239,29 @@ static void sh64_unwind_inner(struct pt_regs *regs)
                int cond;
                unsigned long next_fp, next_pc;
 
-               if (pc == ((unsigned long) &syscall_ret & ~1)) {
+               if (pc == ((unsigned long)&syscall_ret & ~1)) {
                        printk("SYSCALL\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
-               if (pc == ((unsigned long) &ret_from_syscall & ~1)) {
+               if (pc == ((unsigned long)&ret_from_syscall & ~1)) {
                        printk("SYSCALL (PREEMPTED)\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
                /* In this case, the PC is discovered by lookup_prev_stack_frame but
                   it has 4 taken off it to look like the 'caller' */
-               if (pc == ((unsigned long) &ret_from_exception & ~1)) {
+               if (pc == ((unsigned long)&ret_from_exception & ~1)) {
                        printk("EXCEPTION\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
-               if (pc == ((unsigned long) &ret_from_irq & ~1)) {
+               if (pc == ((unsigned long)&ret_from_irq & ~1)) {
                        printk("IRQ\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
@@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs)
 
                pc -= ofs;
 
-               printk("[<%08lx>] ", pc);
-               print_symbol("%s\n", pc);
+               ops->address(data, pc, 1);
 
                if (first_pass) {
                        /* If the innermost frame is a leaf function, it's
@@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)
        }
 
        printk("\n");
-
 }
 
-void sh64_unwind(struct pt_regs *regs)
+static void sh64_unwinder_dump(struct task_struct *task,
+                              struct pt_regs *regs,
+                              unsigned long *sp,
+                              const struct stacktrace_ops *ops,
+                              void *data)
 {
        if (!regs) {
                /*
@@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs)
                );
        }
 
-       printk("\nCall Trace:\n");
-       sh64_unwind_inner(regs);
+       sh64_unwind_inner(ops, data, regs);
 }
 
+static struct unwinder sh64_unwinder = {
+       .name   = "sh64-unwinder",
+       .dump   = sh64_unwinder_dump,
+       .rating = 150,
+};
+
+static int __init sh64_unwinder_init(void)
+{
+       return unwinder_register(&sh64_unwinder);
+}
+early_initcall(sh64_unwinder_init);
index 694158b9a50f5655aba0c2bf50551261d13b554b..7617dc4129ac05acf7ade8e12f4791cda212d732 100644 (file)
@@ -2,13 +2,48 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
  *  Copyright (C) 2009  Matt Fleming
+ *  Copyright (C) 2002 - 2012  Paul Mundt
+ *
+ * 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/kallsyms.h>
 #include <linux/ftrace.h>
 #include <linux/debug_locks.h>
+#include <linux/kdebug.h>
+#include <linux/export.h>
+#include <linux/uaccess.h>
 #include <asm/unwinder.h>
 #include <asm/stacktrace.h>
 
+void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+{
+       unsigned long p;
+       int i;
+
+       printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+
+       for (p = bottom & ~31; p < top; ) {
+               printk("%04lx: ", p & 0xffff);
+
+               for (i = 0; i < 8; i++, p += 4) {
+                       unsigned int val;
+
+                       if (p < bottom || p >= top)
+                               printk("         ");
+                       else {
+                               if (__get_user(val, (unsigned int __user *)p)) {
+                                       printk("\n");
+                                       return;
+                               }
+                               printk("%08x ", val);
+                       }
+               }
+               printk("\n");
+       }
+}
+
 void printk_address(unsigned long address, int reliable)
 {
        printk(" [<%p>] %s%pS\n", (void *) address,
@@ -106,3 +141,26 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
 
        debug_show_held_locks(tsk);
 }
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+       unsigned long stack;
+
+       if (!tsk)
+               tsk = current;
+       if (tsk == current)
+               sp = (unsigned long *)current_stack_pointer;
+       else
+               sp = (unsigned long *)tsk->thread.sp;
+
+       stack = (unsigned long)sp;
+       dump_mem("Stack: ", stack, THREAD_SIZE +
+                (unsigned long)task_stack_page(tsk));
+       show_trace(tsk, sp, NULL);
+}
+
+void dump_stack(void)
+{
+       show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
index a37175deb73fdfa672c604ddab07297c41559981..b8f5a51841ec09533d017532d6e694d0e366b20d 100644 (file)
 #define TRAP_ILLEGAL_SLOT_INST 13
 #endif
 
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
-{
-       unsigned long p;
-       int i;
-
-       printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
-
-       for (p = bottom & ~31; p < top; ) {
-               printk("%04lx: ", p & 0xffff);
-
-               for (i = 0; i < 8; i++, p += 4) {
-                       unsigned int val;
-
-                       if (p < bottom || p >= top)
-                               printk("         ");
-                       else {
-                               if (__get_user(val, (unsigned int __user *)p)) {
-                                       printk("\n");
-                                       return;
-                               }
-                               printk("%08x ", val);
-                       }
-               }
-               printk("\n");
-       }
-}
-
 static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -900,26 +873,3 @@ void __init trap_init(void)
        set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
 #endif
 }
-
-void show_stack(struct task_struct *tsk, unsigned long *sp)
-{
-       unsigned long stack;
-
-       if (!tsk)
-               tsk = current;
-       if (tsk == current)
-               sp = (unsigned long *)current_stack_pointer;
-       else
-               sp = (unsigned long *)tsk->thread.sp;
-
-       stack = (unsigned long)sp;
-       dump_mem("Stack: ", stack, THREAD_SIZE +
-                (unsigned long)task_stack_page(tsk));
-       show_trace(tsk, sp, NULL);
-}
-
-void dump_stack(void)
-{
-       show_stack(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
index 8dae93ed8aff77586c50df0f6830e23f48f13c75..ba95d63e623d887cad3922e7420331b3db29d43c 100644 (file)
@@ -253,32 +253,6 @@ int do_unknown_trapa(unsigned long scId, struct pt_regs *regs)
        return -ENOSYS;
 }
 
-void show_stack(struct task_struct *tsk, unsigned long *sp)
-{
-#ifdef CONFIG_KALLSYMS
-       extern void sh64_unwind(struct pt_regs *regs);
-       struct pt_regs *regs;
-
-       regs = tsk ? tsk->thread.kregs : NULL;
-
-       sh64_unwind(regs);
-#else
-       printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n");
-#endif
-}
-
-void show_task(unsigned long *sp)
-{
-       show_stack(NULL, sp);
-}
-
-void dump_stack(void)
-{
-       show_task(NULL);
-}
-/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */
-EXPORT_SYMBOL(dump_stack);
-
 static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
                unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
 {