Commit 7f788d2d authored by Deng-Cheng Zhu's avatar Deng-Cheng Zhu Committed by Ralf Baechle
Browse files

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: default avatarDeng-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: default avatarDavid Daney <ddaney@caviumnetworks.com>
Reviewed-by: default avatarMatt Fleming <matt@console-pimps.org>
Patchwork: https://patchwork.linux-mips.org/patch/1686/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 6dbd9728
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+15 −3
Original line number Diff line number Diff line
@@ -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 ... */
}
+7 −0
Original line number Diff line number Diff line
@@ -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?
+3 −0
Original line number Diff line number Diff line
@@ -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:{
+9 −2
Original line number Diff line number Diff line
@@ -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;