]> err.no Git - linux-2.6/blobdiff - arch/arm/kernel/traps.c
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / arch / arm / kernel / traps.c
index 24095601359b94e04b9d8b83b2b9ab70cb9a2135..f05e66b0f868df49fcd4e6ca4faeaf7b26c32fe2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/signal.h>
 #include <linux/spinlock.h>
 #include <linux/personality.h>
-#include <linux/ptrace.h>
 #include <linux/kallsyms.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -45,7 +44,18 @@ static int __init user_debug_setup(char *str)
 __setup("user_debug=", user_debug_setup);
 #endif
 
-void dump_backtrace_entry(unsigned long where, unsigned long from)
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
+
+static inline int in_exception_text(unsigned long ptr)
+{
+       extern char __exception_text_start[];
+       extern char __exception_text_end[];
+
+       return ptr >= (unsigned long)&__exception_text_start &&
+              ptr < (unsigned long)&__exception_text_end;
+}
+
+void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
 {
 #ifdef CONFIG_KALLSYMS
        printk("[<%08lx>] ", where);
@@ -55,6 +65,9 @@ void dump_backtrace_entry(unsigned long where, unsigned long from)
 #else
        printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
 #endif
+
+       if (in_exception_text(where))
+               dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
 }
 
 /*
@@ -266,13 +279,14 @@ void unregister_undef_hook(struct undef_hook *hook)
        spin_unlock_irqrestore(&undef_lock, flags);
 }
 
-asmlinkage void do_undefinstr(struct pt_regs *regs)
+asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 {
        unsigned int correction = thumb_mode(regs) ? 2 : 4;
        unsigned int instr;
        struct undef_hook *hook;
        siginfo_t info;
        void __user *pc;
+       unsigned long flags;
 
        /*
         * According to the ARM ARM, PC is 2 or 4 bytes ahead,
@@ -291,7 +305,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
                get_user(instr, (u32 __user *)pc);
        }
 
-       spin_lock_irq(&undef_lock);
+       spin_lock_irqsave(&undef_lock, flags);
        list_for_each_entry(hook, &undef_hook, node) {
                if ((instr & hook->instr_mask) == hook->instr_val &&
                    (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) {
@@ -301,7 +315,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
                        }
                }
        }
-       spin_unlock_irq(&undef_lock);
+       spin_unlock_irqrestore(&undef_lock, flags);
 
 #ifdef CONFIG_DEBUG_USER
        if (user_debug & UDBG_UNDEFINED) {