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:
		
							parent
							
								
									5a30d7bfcd
								
							
						
					
					
						commit
						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); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user