sh: wire up perf alignment and emulation faults.
This plugs in the alignment and emulation fault reporting for perf sw events. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Родитель
5a30d7bfcd
Коммит
ace2dc7d12
|
@ -212,7 +212,7 @@ static inline reg_size_t register_align(void *val)
|
|||
}
|
||||
|
||||
int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
|
||||
struct mem_access *ma, int);
|
||||
struct mem_access *ma, int, unsigned long address);
|
||||
|
||||
static inline void trigger_address_error(void)
|
||||
{
|
||||
|
|
|
@ -291,7 +291,7 @@ int handle_trapped_io(struct pt_regs *regs, unsigned long address)
|
|||
}
|
||||
|
||||
tmp = handle_unaligned_access(instruction, regs,
|
||||
&trapped_io_access, 1);
|
||||
&trapped_io_access, 1, address);
|
||||
set_fs(oldfs);
|
||||
return tmp == 0;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* SuperH version: Copyright (C) 1999 Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf
|
||||
* Copyright (C) 2000 David Howells
|
||||
* Copyright (C) 2002 - 2007 Paul Mundt
|
||||
* Copyright (C) 2002 - 2010 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include <linux/limits.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/alignment.h>
|
||||
#include <asm/fpu.h>
|
||||
|
@ -369,7 +370,8 @@ static inline int handle_delayslot(struct pt_regs *regs,
|
|||
#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
|
||||
|
||||
int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
|
||||
struct mem_access *ma, int expected)
|
||||
struct mem_access *ma, int expected,
|
||||
unsigned long address)
|
||||
{
|
||||
u_int rm;
|
||||
int ret, index;
|
||||
|
@ -383,9 +385,18 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
|
|||
index = (instruction>>8)&15; /* 0x0F00 */
|
||||
rm = regs->regs[index];
|
||||
|
||||
/* shout about fixups */
|
||||
if (!expected)
|
||||
/*
|
||||
* Log the unexpected fixups, and then pass them on to perf.
|
||||
*
|
||||
* We intentionally don't report the expected cases to perf as
|
||||
* otherwise the trapped I/O case will skew the results too much
|
||||
* to be useful.
|
||||
*/
|
||||
if (!expected) {
|
||||
unaligned_fixups_notify(current, instruction, regs);
|
||||
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0,
|
||||
regs, address);
|
||||
}
|
||||
|
||||
ret = -EFAULT;
|
||||
switch (instruction&0xF000) {
|
||||
|
@ -574,7 +585,8 @@ fixup:
|
|||
|
||||
set_fs(USER_DS);
|
||||
tmp = handle_unaligned_access(instruction, regs,
|
||||
&user_mem_access, 0);
|
||||
&user_mem_access, 0,
|
||||
address);
|
||||
set_fs(oldfs);
|
||||
|
||||
if (tmp == 0)
|
||||
|
@ -607,8 +619,8 @@ uspace_segv:
|
|||
|
||||
unaligned_fixups_notify(current, instruction, regs);
|
||||
|
||||
handle_unaligned_access(instruction, regs,
|
||||
&user_mem_access, 0);
|
||||
handle_unaligned_access(instruction, regs, &user_mem_access,
|
||||
0, address);
|
||||
set_fs(oldfs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -433,6 +434,8 @@ static int misaligned_load(struct pt_regs *regs,
|
|||
return error;
|
||||
}
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
|
||||
|
||||
destreg = (opcode >> 4) & 0x3f;
|
||||
if (user_mode(regs)) {
|
||||
__u64 buffer;
|
||||
|
@ -509,6 +512,8 @@ static int misaligned_store(struct pt_regs *regs,
|
|||
return error;
|
||||
}
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
|
||||
|
||||
srcreg = (opcode >> 4) & 0x3f;
|
||||
if (user_mode(regs)) {
|
||||
__u64 buffer;
|
||||
|
@ -583,6 +588,8 @@ static int misaligned_fpu_load(struct pt_regs *regs,
|
|||
return error;
|
||||
}
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
|
||||
|
||||
destreg = (opcode >> 4) & 0x3f;
|
||||
if (user_mode(regs)) {
|
||||
__u64 buffer;
|
||||
|
@ -658,6 +665,8 @@ static int misaligned_fpu_store(struct pt_regs *regs,
|
|||
return error;
|
||||
}
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
|
||||
|
||||
srcreg = (opcode >> 4) & 0x3f;
|
||||
if (user_mode(regs)) {
|
||||
__u64 buffer;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -619,6 +620,8 @@ int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
|
|||
struct task_struct *tsk = current;
|
||||
struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
|
||||
|
||||
if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
|
||||
/* initialize once. */
|
||||
fpu_init(fpu);
|
||||
|
|
Загрузка…
Ссылка в новой задаче