diff options
| author | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 19:03:13 +0000 | 
|---|---|---|
| committer | Wim Van Sebroeck <wim@iguana.be> | 2007-05-11 19:03:13 +0000 | 
| commit | 5c34202b8bf942da411b6599668a76b07449bbfd (patch) | |
| tree | 5719c361321eaddc8e4f1b0c8a7994f0e9a6fdd3 /arch/arm/kernel/traps.c | |
| parent | 0d4804b31f91cfbcff6d62af0bc09a893a1c8ae0 (diff) | |
| parent | 1f8a6b658a943b4f04a1fc7b3a420360202c86cd (diff) | |
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/arm/kernel/traps.c')
| -rw-r--r-- | arch/arm/kernel/traps.c | 38 | 
1 files changed, 26 insertions, 12 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 24095601359..10ff36e4e41 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -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));  }  /* @@ -232,8 +245,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)  	do_exit(SIGSEGV);  } -void notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, -		unsigned long err, unsigned long trap) +void arm_notify_die(const char *str, struct pt_regs *regs, +		struct siginfo *info, unsigned long err, unsigned long trap)  {  	if (user_mode(regs)) {  		current->thread.error_code = err; @@ -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) { @@ -316,7 +330,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)  	info.si_code  = ILL_ILLOPC;  	info.si_addr  = pc; -	notify_die("Oops - undefined instruction", regs, &info, 0, 6); +	arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);  }  asmlinkage void do_unexp_fiq (struct pt_regs *regs) @@ -370,7 +384,7 @@ static int bad_syscall(int n, struct pt_regs *regs)  	info.si_addr  = (void __user *)instruction_pointer(regs) -  			 (thumb_mode(regs) ? 2 : 4); -	notify_die("Oops - bad syscall", regs, &info, n, 0); +	arm_notify_die("Oops - bad syscall", regs, &info, n, 0);  	return regs->ARM_r0;  } @@ -414,7 +428,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)  		info.si_code  = SEGV_MAPERR;  		info.si_addr  = NULL; -		notify_die("branch through zero", regs, &info, 0, 0); +		arm_notify_die("branch through zero", regs, &info, 0, 0);  		return 0;  	case NR(breakpoint): /* SWI BREAK_POINT */ @@ -550,7 +564,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)  	info.si_addr  = (void __user *)instruction_pointer(regs) -  			 (thumb_mode(regs) ? 2 : 4); -	notify_die("Oops - bad syscall(2)", regs, &info, no, 0); +	arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0);  	return 0;  } @@ -624,7 +638,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)  	info.si_code  = ILL_ILLOPC;  	info.si_addr  = (void __user *)addr; -	notify_die("unknown data abort code", regs, &info, instr, 0); +	arm_notify_die("unknown data abort code", regs, &info, instr, 0);  }  void __attribute__((noreturn)) __bug(const char *file, int line)  | 
