MIPS: add support for software performance events
Software events are required as part of the measurable stuff by the Linux performance counter subsystem. Here is the list of events added by this patch: PERF_COUNT_SW_PAGE_FAULTS PERF_COUNT_SW_PAGE_FAULTS_MIN PERF_COUNT_SW_PAGE_FAULTS_MAJ PERF_COUNT_SW_ALIGNMENT_FAULTS PERF_COUNT_SW_EMULATION_FAULTS Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@gmail.com> To: linux-mips@linux-mips.org Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org Cc: mingo@elte.hu Cc: acme@redhat.com Cc: jamie.iles@picochip.com Acked-by: David Daney <ddaney@caviumnetworks.com> Reviewed-by: Matt Fleming <matt@console-pimps.org> Patchwork: https://patchwork.linux-mips.org/patch/1686/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
6dbd972850
commit
7f788d2d53
|
@ -4,6 +4,8 @@ config MIPS
|
|||
select HAVE_GENERIC_DMA_COHERENT
|
||||
select HAVE_IDE
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_PERF_EVENTS
|
||||
select PERF_USE_VMALLOC
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/notifier.h>
|
||||
#include <linux/kdb.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/branch.h>
|
||||
|
@ -576,10 +577,16 @@ static inline int simulate_sc(struct pt_regs *regs, unsigned int opcode)
|
|||
*/
|
||||
static int simulate_llsc(struct pt_regs *regs, unsigned int opcode)
|
||||
{
|
||||
if ((opcode & OPCODE) == LL)
|
||||
if ((opcode & OPCODE) == LL) {
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
|
||||
1, 0, regs, 0);
|
||||
return simulate_ll(regs, opcode);
|
||||
if ((opcode & OPCODE) == SC)
|
||||
}
|
||||
if ((opcode & OPCODE) == SC) {
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
|
||||
1, 0, regs, 0);
|
||||
return simulate_sc(regs, opcode);
|
||||
}
|
||||
|
||||
return -1; /* Must be something else ... */
|
||||
}
|
||||
|
@ -595,6 +602,8 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
|
|||
if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) {
|
||||
int rd = (opcode & RD) >> 11;
|
||||
int rt = (opcode & RT) >> 16;
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
|
||||
1, 0, regs, 0);
|
||||
switch (rd) {
|
||||
case 0: /* CPU number */
|
||||
regs->regs[rt] = smp_processor_id();
|
||||
|
@ -630,8 +639,11 @@ static int simulate_rdhwr(struct pt_regs *regs, unsigned int opcode)
|
|||
|
||||
static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
|
||||
{
|
||||
if ((opcode & OPCODE) == SPEC0 && (opcode & FUNC) == SYNC)
|
||||
if ((opcode & OPCODE) == SPEC0 && (opcode & FUNC) == SYNC) {
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
|
||||
1, 0, regs, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1; /* Must be something else ... */
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@
|
|||
#include <linux/smp.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/branch.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
@ -109,6 +111,9 @@ static void emulate_load_store_insn(struct pt_regs *regs,
|
|||
unsigned long value;
|
||||
unsigned int res;
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
|
||||
1, 0, regs, 0);
|
||||
|
||||
/*
|
||||
* This load never faults.
|
||||
*/
|
||||
|
@ -511,6 +516,8 @@ asmlinkage void do_ade(struct pt_regs *regs)
|
|||
unsigned int __user *pc;
|
||||
mm_segment_t seg;
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
|
||||
1, 0, regs, regs->cp0_badvaddr);
|
||||
/*
|
||||
* Did we catch a fault trying to load an instruction?
|
||||
* Or are we running in MIPS16 mode?
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/inst.h>
|
||||
#include <asm/bootinfo.h>
|
||||
|
@ -258,6 +259,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
|
|||
}
|
||||
|
||||
emul:
|
||||
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS,
|
||||
1, 0, xcp, 0);
|
||||
MIPS_FPU_EMU_INC_STATS(emulated);
|
||||
switch (MIPSInst_OPCODE(ir)) {
|
||||
case ldc1_op:{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/smp.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/branch.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
@ -144,6 +145,7 @@ good_area:
|
|||
* the fault.
|
||||
*/
|
||||
fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
|
||||
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
|
||||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
|
@ -151,10 +153,15 @@ good_area:
|
|||
goto do_sigbus;
|
||||
BUG();
|
||||
}
|
||||
if (fault & VM_FAULT_MAJOR)
|
||||
if (fault & VM_FAULT_MAJOR) {
|
||||
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
|
||||
1, 0, regs, address);
|
||||
tsk->maj_flt++;
|
||||
else
|
||||
} else {
|
||||
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
|
||||
1, 0, regs, address);
|
||||
tsk->min_flt++;
|
||||
}
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue