diff options
Diffstat (limited to 'arch/sh/kernel/traps_32.c')
-rw-r--r-- | arch/sh/kernel/traps_32.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index c3d86fa71ddf..3484c2f65aba 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * SuperH version: Copyright (C) 1999 Niibe Yutaka | 5 | * SuperH version: Copyright (C) 1999 Niibe Yutaka |
6 | * Copyright (C) 2000 Philipp Rumpf | 6 | * Copyright (C) 2000 Philipp Rumpf |
7 | * Copyright (C) 2000 David Howells | 7 | * Copyright (C) 2000 David Howells |
8 | * Copyright (C) 2002 - 2007 Paul Mundt | 8 | * Copyright (C) 2002 - 2010 Paul Mundt |
9 | * | 9 | * |
10 | * This file is subject to the terms and conditions of the GNU General Public | 10 | * This file is subject to the terms and conditions of the GNU General Public |
11 | * License. See the file "COPYING" in the main directory of this archive | 11 | * License. See the file "COPYING" in the main directory of this archive |
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/limits.h> | 26 | #include <linux/limits.h> |
27 | #include <linux/sysfs.h> | 27 | #include <linux/sysfs.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/perf_event.h> | ||
29 | #include <asm/system.h> | 30 | #include <asm/system.h> |
30 | #include <asm/alignment.h> | 31 | #include <asm/alignment.h> |
31 | #include <asm/fpu.h> | 32 | #include <asm/fpu.h> |
@@ -369,7 +370,8 @@ static inline int handle_delayslot(struct pt_regs *regs, | |||
369 | #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) | 370 | #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) |
370 | 371 | ||
371 | int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, | 372 | int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, |
372 | struct mem_access *ma, int expected) | 373 | struct mem_access *ma, int expected, |
374 | unsigned long address) | ||
373 | { | 375 | { |
374 | u_int rm; | 376 | u_int rm; |
375 | int ret, index; | 377 | int ret, index; |
@@ -383,9 +385,18 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, | |||
383 | index = (instruction>>8)&15; /* 0x0F00 */ | 385 | index = (instruction>>8)&15; /* 0x0F00 */ |
384 | rm = regs->regs[index]; | 386 | rm = regs->regs[index]; |
385 | 387 | ||
386 | /* shout about fixups */ | 388 | /* |
387 | if (!expected) | 389 | * Log the unexpected fixups, and then pass them on to perf. |
390 | * | ||
391 | * We intentionally don't report the expected cases to perf as | ||
392 | * otherwise the trapped I/O case will skew the results too much | ||
393 | * to be useful. | ||
394 | */ | ||
395 | if (!expected) { | ||
388 | unaligned_fixups_notify(current, instruction, regs); | 396 | unaligned_fixups_notify(current, instruction, regs); |
397 | perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, | ||
398 | regs, address); | ||
399 | } | ||
389 | 400 | ||
390 | ret = -EFAULT; | 401 | ret = -EFAULT; |
391 | switch (instruction&0xF000) { | 402 | switch (instruction&0xF000) { |
@@ -574,7 +585,8 @@ fixup: | |||
574 | 585 | ||
575 | set_fs(USER_DS); | 586 | set_fs(USER_DS); |
576 | tmp = handle_unaligned_access(instruction, regs, | 587 | tmp = handle_unaligned_access(instruction, regs, |
577 | &user_mem_access, 0); | 588 | &user_mem_access, 0, |
589 | address); | ||
578 | set_fs(oldfs); | 590 | set_fs(oldfs); |
579 | 591 | ||
580 | if (tmp == 0) | 592 | if (tmp == 0) |
@@ -607,8 +619,8 @@ uspace_segv: | |||
607 | 619 | ||
608 | unaligned_fixups_notify(current, instruction, regs); | 620 | unaligned_fixups_notify(current, instruction, regs); |
609 | 621 | ||
610 | handle_unaligned_access(instruction, regs, | 622 | handle_unaligned_access(instruction, regs, &user_mem_access, |
611 | &user_mem_access, 0); | 623 | 0, address); |
612 | set_fs(oldfs); | 624 | set_fs(oldfs); |
613 | } | 625 | } |
614 | } | 626 | } |
@@ -802,6 +814,9 @@ void __cpuinit per_cpu_trap_init(void) | |||
802 | : /* no output */ | 814 | : /* no output */ |
803 | : "r" (&vbr_base) | 815 | : "r" (&vbr_base) |
804 | : "memory"); | 816 | : "memory"); |
817 | |||
818 | /* disable exception blocking now when the vbr has been setup */ | ||
819 | clear_bl_bit(); | ||
805 | } | 820 | } |
806 | 821 | ||
807 | void *set_exception_table_vec(unsigned int vec, void *handler) | 822 | void *set_exception_table_vec(unsigned int vec, void *handler) |