diff options
Diffstat (limited to 'arch/arm/kernel/traps.c')
-rw-r--r-- | arch/arm/kernel/traps.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 6807cb1e76d..4ef9f0d04e5 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | 27 | ||
28 | #include <asm/atomic.h> | 28 | #include <linux/atomic.h> |
29 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
30 | #include <asm/system.h> | 30 | #include <asm/system.h> |
31 | #include <asm/unistd.h> | 31 | #include <asm/unistd.h> |
@@ -355,9 +355,24 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) | |||
355 | pc = (void __user *)instruction_pointer(regs); | 355 | pc = (void __user *)instruction_pointer(regs); |
356 | 356 | ||
357 | if (processor_mode(regs) == SVC_MODE) { | 357 | if (processor_mode(regs) == SVC_MODE) { |
358 | instr = *(u32 *) pc; | 358 | #ifdef CONFIG_THUMB2_KERNEL |
359 | if (thumb_mode(regs)) { | ||
360 | instr = ((u16 *)pc)[0]; | ||
361 | if (is_wide_instruction(instr)) { | ||
362 | instr <<= 16; | ||
363 | instr |= ((u16 *)pc)[1]; | ||
364 | } | ||
365 | } else | ||
366 | #endif | ||
367 | instr = *(u32 *) pc; | ||
359 | } else if (thumb_mode(regs)) { | 368 | } else if (thumb_mode(regs)) { |
360 | get_user(instr, (u16 __user *)pc); | 369 | get_user(instr, (u16 __user *)pc); |
370 | if (is_wide_instruction(instr)) { | ||
371 | unsigned int instr2; | ||
372 | get_user(instr2, (u16 __user *)pc+1); | ||
373 | instr <<= 16; | ||
374 | instr |= instr2; | ||
375 | } | ||
361 | } else { | 376 | } else { |
362 | get_user(instr, (u32 __user *)pc); | 377 | get_user(instr, (u32 __user *)pc); |
363 | } | 378 | } |
@@ -451,7 +466,9 @@ do_cache_op(unsigned long start, unsigned long end, int flags) | |||
451 | if (end > vma->vm_end) | 466 | if (end > vma->vm_end) |
452 | end = vma->vm_end; | 467 | end = vma->vm_end; |
453 | 468 | ||
454 | flush_cache_user_range(vma, start, end); | 469 | up_read(&mm->mmap_sem); |
470 | flush_cache_user_range(start, end); | ||
471 | return; | ||
455 | } | 472 | } |
456 | up_read(&mm->mmap_sem); | 473 | up_read(&mm->mmap_sem); |
457 | } | 474 | } |