diff options
Diffstat (limited to 'arch/arm/kernel/traps.c')
| -rw-r--r-- | arch/arm/kernel/traps.c | 47 | 
1 files changed, 31 insertions, 16 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 8fcda140358..abd2fc06773 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -34,8 +34,15 @@  #include <asm/unwind.h>  #include <asm/tls.h>  #include <asm/system_misc.h> - -static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; +#include <asm/opcodes.h> + +static const char *handler[]= { +	"prefetch abort", +	"data abort", +	"address exception", +	"interrupt", +	"undefined instruction", +};  void *vectors_page; @@ -55,7 +62,7 @@ static void dump_mem(const char *, const char *, unsigned long, unsigned long);  void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)  {  #ifdef CONFIG_KALLSYMS -	printk("[<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); +	printk("[<%08lx>] (%ps) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from);  #else  	printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);  #endif @@ -341,15 +348,17 @@ void arm_notify_die(const char *str, struct pt_regs *regs,  int is_valid_bugaddr(unsigned long pc)  {  #ifdef CONFIG_THUMB2_KERNEL -	unsigned short bkpt; +	u16 bkpt; +	u16 insn = __opcode_to_mem_thumb16(BUG_INSTR_VALUE);  #else -	unsigned long bkpt; +	u32 bkpt; +	u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE);  #endif  	if (probe_kernel_address((unsigned *)pc, bkpt))  		return 0; -	return bkpt == BUG_INSTR_VALUE; +	return bkpt == insn;  }  #endif @@ -402,26 +411,30 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)  	if (processor_mode(regs) == SVC_MODE) {  #ifdef CONFIG_THUMB2_KERNEL  		if (thumb_mode(regs)) { -			instr = ((u16 *)pc)[0]; +			instr = __mem_to_opcode_thumb16(((u16 *)pc)[0]);  			if (is_wide_instruction(instr)) { -				instr <<= 16; -				instr |= ((u16 *)pc)[1]; +				u16 inst2; +				inst2 = __mem_to_opcode_thumb16(((u16 *)pc)[1]); +				instr = __opcode_thumb32_compose(instr, inst2);  			}  		} else  #endif -			instr = *(u32 *) pc; +			instr = __mem_to_opcode_arm(*(u32 *) pc);  	} else if (thumb_mode(regs)) {  		if (get_user(instr, (u16 __user *)pc))  			goto die_sig; +		instr = __mem_to_opcode_thumb16(instr);  		if (is_wide_instruction(instr)) {  			unsigned int instr2;  			if (get_user(instr2, (u16 __user *)pc+1))  				goto die_sig; -			instr <<= 16; -			instr |= instr2; +			instr2 = __mem_to_opcode_thumb16(instr2); +			instr = __opcode_thumb32_compose(instr, instr2);  		} -	} else if (get_user(instr, (u32 __user *)pc)) { -		goto die_sig; +	} else { +		if (get_user(instr, (u32 __user *)pc)) +			goto die_sig; +		instr = __mem_to_opcode_arm(instr);  	}  	if (call_undef_hook(regs, instr) == 0) @@ -432,6 +445,7 @@ die_sig:  	if (user_debug & UDBG_UNDEFINED) {  		printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",  			current->comm, task_pid_nr(current), pc); +		__show_regs(regs);  		dump_instr(KERN_INFO, regs);  	}  #endif @@ -503,9 +517,10 @@ static inline int  __do_cache_op(unsigned long start, unsigned long end)  {  	int ret; -	unsigned long chunk = PAGE_SIZE;  	do { +		unsigned long chunk = min(PAGE_SIZE, end - start); +  		if (signal_pending(current)) {  			struct thread_info *ti = current_thread_info(); @@ -850,7 +865,7 @@ static void __init kuser_init(void *vectors)  		memcpy(vectors + 0xfe0, vectors + 0xfe8, 4);  }  #else -static void __init kuser_init(void *vectors) +static inline void __init kuser_init(void *vectors)  {  }  #endif  | 
