diff options
Diffstat (limited to 'arch/arm/kernel/traps.c')
-rw-r--r-- | arch/arm/kernel/traps.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 24095601359..f05e66b0f86 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <linux/personality.h> | 18 | #include <linux/personality.h> |
19 | #include <linux/ptrace.h> | ||
20 | #include <linux/kallsyms.h> | 19 | #include <linux/kallsyms.h> |
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
22 | #include <linux/init.h> | 21 | #include <linux/init.h> |
@@ -45,7 +44,18 @@ static int __init user_debug_setup(char *str) | |||
45 | __setup("user_debug=", user_debug_setup); | 44 | __setup("user_debug=", user_debug_setup); |
46 | #endif | 45 | #endif |
47 | 46 | ||
48 | void dump_backtrace_entry(unsigned long where, unsigned long from) | 47 | static void dump_mem(const char *str, unsigned long bottom, unsigned long top); |
48 | |||
49 | static inline int in_exception_text(unsigned long ptr) | ||
50 | { | ||
51 | extern char __exception_text_start[]; | ||
52 | extern char __exception_text_end[]; | ||
53 | |||
54 | return ptr >= (unsigned long)&__exception_text_start && | ||
55 | ptr < (unsigned long)&__exception_text_end; | ||
56 | } | ||
57 | |||
58 | void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) | ||
49 | { | 59 | { |
50 | #ifdef CONFIG_KALLSYMS | 60 | #ifdef CONFIG_KALLSYMS |
51 | printk("[<%08lx>] ", where); | 61 | printk("[<%08lx>] ", where); |
@@ -55,6 +65,9 @@ void dump_backtrace_entry(unsigned long where, unsigned long from) | |||
55 | #else | 65 | #else |
56 | printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); | 66 | printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); |
57 | #endif | 67 | #endif |
68 | |||
69 | if (in_exception_text(where)) | ||
70 | dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); | ||
58 | } | 71 | } |
59 | 72 | ||
60 | /* | 73 | /* |
@@ -266,13 +279,14 @@ void unregister_undef_hook(struct undef_hook *hook) | |||
266 | spin_unlock_irqrestore(&undef_lock, flags); | 279 | spin_unlock_irqrestore(&undef_lock, flags); |
267 | } | 280 | } |
268 | 281 | ||
269 | asmlinkage void do_undefinstr(struct pt_regs *regs) | 282 | asmlinkage void __exception do_undefinstr(struct pt_regs *regs) |
270 | { | 283 | { |
271 | unsigned int correction = thumb_mode(regs) ? 2 : 4; | 284 | unsigned int correction = thumb_mode(regs) ? 2 : 4; |
272 | unsigned int instr; | 285 | unsigned int instr; |
273 | struct undef_hook *hook; | 286 | struct undef_hook *hook; |
274 | siginfo_t info; | 287 | siginfo_t info; |
275 | void __user *pc; | 288 | void __user *pc; |
289 | unsigned long flags; | ||
276 | 290 | ||
277 | /* | 291 | /* |
278 | * According to the ARM ARM, PC is 2 or 4 bytes ahead, | 292 | * According to the ARM ARM, PC is 2 or 4 bytes ahead, |
@@ -291,7 +305,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) | |||
291 | get_user(instr, (u32 __user *)pc); | 305 | get_user(instr, (u32 __user *)pc); |
292 | } | 306 | } |
293 | 307 | ||
294 | spin_lock_irq(&undef_lock); | 308 | spin_lock_irqsave(&undef_lock, flags); |
295 | list_for_each_entry(hook, &undef_hook, node) { | 309 | list_for_each_entry(hook, &undef_hook, node) { |
296 | if ((instr & hook->instr_mask) == hook->instr_val && | 310 | if ((instr & hook->instr_mask) == hook->instr_val && |
297 | (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { | 311 | (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { |
@@ -301,7 +315,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs) | |||
301 | } | 315 | } |
302 | } | 316 | } |
303 | } | 317 | } |
304 | spin_unlock_irq(&undef_lock); | 318 | spin_unlock_irqrestore(&undef_lock, flags); |
305 | 319 | ||
306 | #ifdef CONFIG_DEBUG_USER | 320 | #ifdef CONFIG_DEBUG_USER |
307 | if (user_debug & UDBG_UNDEFINED) { | 321 | if (user_debug & UDBG_UNDEFINED) { |