]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'sh/multi-unwinders' into sh-latest
authorPaul Mundt <lethal@linux-sh.org>
Wed, 13 Jun 2012 03:12:14 +0000 (12:12 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 13 Jun 2012 03:12:14 +0000 (12:12 +0900)
arch/sh/Kconfig
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 31d9db7913e4352a10680f76f2aaa8a5e800eef5..a24595d83ad6c48c5685faed4d59ecb00d410c41 100644 (file)
@@ -60,6 +60,7 @@ config SUPERH32
 
 config SUPERH64
        def_bool ARCH = "sh64"
+       select KALLSYMS
 
 config ARCH_DEFCONFIG
        string
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)
 {