aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/traps_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/traps_32.c')
-rw-r--r--arch/sh/kernel/traps_32.c29
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
371int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, 372int 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
807void *set_exception_table_vec(unsigned int vec, void *handler) 822void *set_exception_table_vec(unsigned int vec, void *handler)