aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/traps.c')
-rw-r--r--arch/arm/kernel/traps.c24
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
48void dump_backtrace_entry(unsigned long where, unsigned long from) 47static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
48
49static 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
58void 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
269asmlinkage void do_undefinstr(struct pt_regs *regs) 282asmlinkage 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) {