Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2654294b authored by James Hogan's avatar James Hogan
Browse files

MIPS: Unify perf counter register definitions



Unify definitions for MIPS performance counter register fields in
mipsregs.h rather than duplicating them in perf_events and oprofile.
This will allow future patches to use them to expose performance
counters to KVM guests.

Signed-off-by: default avatarJames Hogan <james.hogan@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Robert Richter <rric@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: oprofile-list@lists.sf.net
Patchwork: https://patchwork.linux-mips.org/patch/15212/


Signed-off-by: default avatarJames Hogan <james.hogan@imgtec.com>
parent 573deec0
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -685,6 +685,39 @@
#define MIPS_WATCHHI_W		(_ULCAST_(1) << 0)
#define MIPS_WATCHHI_IRW	(_ULCAST_(0x7) << 0)

/* PerfCnt control register definitions */
#define MIPS_PERFCTRL_EXL	(_ULCAST_(1) << 0)
#define MIPS_PERFCTRL_K		(_ULCAST_(1) << 1)
#define MIPS_PERFCTRL_S		(_ULCAST_(1) << 2)
#define MIPS_PERFCTRL_U		(_ULCAST_(1) << 3)
#define MIPS_PERFCTRL_IE	(_ULCAST_(1) << 4)
#define MIPS_PERFCTRL_EVENT_S	5
#define MIPS_PERFCTRL_EVENT	(_ULCAST_(0x3ff) << MIPS_PERFCTRL_EVENT_S)
#define MIPS_PERFCTRL_PCTD	(_ULCAST_(1) << 15)
#define MIPS_PERFCTRL_EC	(_ULCAST_(0x3) << 23)
#define MIPS_PERFCTRL_EC_R	(_ULCAST_(0) << 23)
#define MIPS_PERFCTRL_EC_RI	(_ULCAST_(1) << 23)
#define MIPS_PERFCTRL_EC_G	(_ULCAST_(2) << 23)
#define MIPS_PERFCTRL_EC_GRI	(_ULCAST_(3) << 23)
#define MIPS_PERFCTRL_W		(_ULCAST_(1) << 30)
#define MIPS_PERFCTRL_M		(_ULCAST_(1) << 31)

/* PerfCnt control register MT extensions used by MIPS cores */
#define MIPS_PERFCTRL_VPEID_S	16
#define MIPS_PERFCTRL_VPEID	(_ULCAST_(0xf) << MIPS_PERFCTRL_VPEID_S)
#define MIPS_PERFCTRL_TCID_S	22
#define MIPS_PERFCTRL_TCID	(_ULCAST_(0xff) << MIPS_PERFCTRL_TCID_S)
#define MIPS_PERFCTRL_MT_EN	(_ULCAST_(0x3) << 20)
#define MIPS_PERFCTRL_MT_EN_ALL	(_ULCAST_(0) << 20)
#define MIPS_PERFCTRL_MT_EN_VPE	(_ULCAST_(1) << 20)
#define MIPS_PERFCTRL_MT_EN_TC	(_ULCAST_(2) << 20)

/* PerfCnt control register MT extensions used by BMIPS5000 */
#define BRCM_PERFCTRL_TC	(_ULCAST_(1) << 30)

/* PerfCnt control register MT extensions used by Netlogic XLR */
#define XLR_PERFCTRL_ALLTHREADS	(_ULCAST_(1) << 13)

/* MAAR bit definitions */
#define MIPS_MAAR_ADDR		((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
#define MIPS_MAAR_ADDR_SHIFT	12
+23 −32
Original line number Diff line number Diff line
@@ -101,40 +101,31 @@ struct mips_pmu {

static struct mips_pmu mipspmu;

#define M_PERFCTL_EXL			(1	<<  0)
#define M_PERFCTL_KERNEL		(1	<<  1)
#define M_PERFCTL_SUPERVISOR		(1	<<  2)
#define M_PERFCTL_USER			(1	<<  3)
#define M_PERFCTL_INTERRUPT_ENABLE	(1	<<  4)
#define M_PERFCTL_EVENT(event)		(((event) & 0x3ff)  << 5)
#define M_PERFCTL_VPEID(vpe)		((vpe)	  << 16)
#define M_PERFCTL_EVENT(event)		(((event) << MIPS_PERFCTRL_EVENT_S) & \
					 MIPS_PERFCTRL_EVENT)
#define M_PERFCTL_VPEID(vpe)		((vpe)	  << MIPS_PERFCTRL_VPEID_S)

#ifdef CONFIG_CPU_BMIPS5000
#define M_PERFCTL_MT_EN(filter)		0
#else /* !CONFIG_CPU_BMIPS5000 */
#define M_PERFCTL_MT_EN(filter)		((filter) << 20)
#define M_PERFCTL_MT_EN(filter)		(filter)
#endif /* CONFIG_CPU_BMIPS5000 */

#define	   M_TC_EN_ALL			M_PERFCTL_MT_EN(0)
#define	   M_TC_EN_VPE			M_PERFCTL_MT_EN(1)
#define	   M_TC_EN_TC			M_PERFCTL_MT_EN(2)
#define M_PERFCTL_TCID(tcid)		((tcid)	  << 22)
#define M_PERFCTL_WIDE			(1	<< 30)
#define M_PERFCTL_MORE			(1	<< 31)
#define M_PERFCTL_TC			(1	<< 30)
#define	   M_TC_EN_ALL			M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_ALL)
#define	   M_TC_EN_VPE			M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_VPE)
#define	   M_TC_EN_TC			M_PERFCTL_MT_EN(MIPS_PERFCTRL_MT_EN_TC)

#define M_PERFCTL_COUNT_EVENT_WHENEVER	(M_PERFCTL_EXL |		\
					M_PERFCTL_KERNEL |		\
					M_PERFCTL_USER |		\
					M_PERFCTL_SUPERVISOR |		\
					M_PERFCTL_INTERRUPT_ENABLE)
#define M_PERFCTL_COUNT_EVENT_WHENEVER	(MIPS_PERFCTRL_EXL |		\
					 MIPS_PERFCTRL_K |		\
					 MIPS_PERFCTRL_U |		\
					 MIPS_PERFCTRL_S |		\
					 MIPS_PERFCTRL_IE)

#ifdef CONFIG_MIPS_MT_SMP
#define M_PERFCTL_CONFIG_MASK		0x3fff801f
#else
#define M_PERFCTL_CONFIG_MASK		0x1f
#endif
#define M_PERFCTL_EVENT_MASK		0xfe0


#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
@@ -345,11 +336,11 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
	cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(evt->event_base & 0xff) |
		(evt->config_base & M_PERFCTL_CONFIG_MASK) |
		/* Make sure interrupt enabled. */
		M_PERFCTL_INTERRUPT_ENABLE;
		MIPS_PERFCTRL_IE;
	if (IS_ENABLED(CONFIG_CPU_BMIPS5000))
		/* enable the counter for the calling thread */
		cpuc->saved_ctrl[idx] |=
			(1 << (12 + vpe_id())) | M_PERFCTL_TC;
			(1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC;

	/*
	 * We do not actually let the counter run. Leave it until start().
@@ -754,11 +745,11 @@ static int __n_counters(void)
{
	if (!cpu_has_perf)
		return 0;
	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
	if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M))
		return 1;
	if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
	if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M))
		return 2;
	if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
	if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M))
		return 3;

	return 4;
@@ -1339,7 +1330,7 @@ static int __hw_perf_event_init(struct perf_event *event)
	 * We allow max flexibility on how each individual counter shared
	 * by the single CPU operates (the mode exclusion and the range).
	 */
	hwc->config_base = M_PERFCTL_INTERRUPT_ENABLE;
	hwc->config_base = MIPS_PERFCTRL_IE;

	/* Calculate range bits and validate it. */
	if (num_possible_cpus() > 1)
@@ -1350,14 +1341,14 @@ static int __hw_perf_event_init(struct perf_event *event)
		mutex_unlock(&raw_event_mutex);

	if (!attr->exclude_user)
		hwc->config_base |= M_PERFCTL_USER;
		hwc->config_base |= MIPS_PERFCTRL_U;
	if (!attr->exclude_kernel) {
		hwc->config_base |= M_PERFCTL_KERNEL;
		hwc->config_base |= MIPS_PERFCTRL_K;
		/* MIPS kernel mode: KSU == 00b || EXL == 1 || ERL == 1 */
		hwc->config_base |= M_PERFCTL_EXL;
		hwc->config_base |= MIPS_PERFCTRL_EXL;
	}
	if (!attr->exclude_hv)
		hwc->config_base |= M_PERFCTL_SUPERVISOR;
		hwc->config_base |= MIPS_PERFCTRL_S;

	hwc->config_base &= M_PERFCTL_CONFIG_MASK;
	/*
@@ -1830,7 +1821,7 @@ init_hw_perf_events(void)
	mipspmu.num_counters = counters;
	mipspmu.irq = irq;

	if (read_c0_perfctrl0() & M_PERFCTL_WIDE) {
	if (read_c0_perfctrl0() & MIPS_PERFCTRL_W) {
		mipspmu.max_period = (1ULL << 63) - 1;
		mipspmu.valid_count = (1ULL << 63) - 1;
		mipspmu.overflow = 1ULL << 63;
+13 −27
Original line number Diff line number Diff line
@@ -15,26 +15,12 @@

#include "op_impl.h"

#define M_PERFCTL_EXL			(1UL	  <<  0)
#define M_PERFCTL_KERNEL		(1UL	  <<  1)
#define M_PERFCTL_SUPERVISOR		(1UL	  <<  2)
#define M_PERFCTL_USER			(1UL	  <<  3)
#define M_PERFCTL_INTERRUPT_ENABLE	(1UL	  <<  4)
#define M_PERFCTL_EVENT(event)		(((event) & 0x3ff)  << 5)
#define M_PERFCTL_VPEID(vpe)		((vpe)	  << 16)
#define M_PERFCTL_MT_EN(filter)		((filter) << 20)
#define	   M_TC_EN_ALL			M_PERFCTL_MT_EN(0)
#define	   M_TC_EN_VPE			M_PERFCTL_MT_EN(1)
#define	   M_TC_EN_TC			M_PERFCTL_MT_EN(2)
#define M_PERFCTL_TCID(tcid)		((tcid)	  << 22)
#define M_PERFCTL_WIDE			(1UL	  << 30)
#define M_PERFCTL_MORE			(1UL	  << 31)
#define M_PERFCTL_EVENT(event)		(((event) << MIPS_PERFCTRL_EVENT_S) & \
					 MIPS_PERFCTRL_EVENT)
#define M_PERFCTL_VPEID(vpe)		((vpe)	  << MIPS_PERFCTRL_VPEID_S)

#define M_COUNTER_OVERFLOW		(1UL	  << 31)

/* Netlogic XLR specific, count events in all threads in a core */
#define M_PERFCTL_COUNT_ALL_THREADS	(1UL	  << 13)

static int (*save_perf_irq)(void);
static int perfcount_irq;

@@ -51,7 +37,7 @@ static int perfcount_irq;

#ifdef CONFIG_MIPS_MT_SMP
static int cpu_has_mipsmt_pertccounters;
#define WHAT		(M_TC_EN_VPE | \
#define WHAT		(MIPS_PERFCTRL_MT_EN_VPE | \
			 M_PERFCTL_VPEID(cpu_data[smp_processor_id()].vpe_id))
#define vpe_id()	(cpu_has_mipsmt_pertccounters ? \
			0 : cpu_data[smp_processor_id()].vpe_id)
@@ -161,15 +147,15 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
			continue;

		reg.control[i] = M_PERFCTL_EVENT(ctr[i].event) |
				 M_PERFCTL_INTERRUPT_ENABLE;
				 MIPS_PERFCTRL_IE;
		if (ctr[i].kernel)
			reg.control[i] |= M_PERFCTL_KERNEL;
			reg.control[i] |= MIPS_PERFCTRL_K;
		if (ctr[i].user)
			reg.control[i] |= M_PERFCTL_USER;
			reg.control[i] |= MIPS_PERFCTRL_U;
		if (ctr[i].exl)
			reg.control[i] |= M_PERFCTL_EXL;
			reg.control[i] |= MIPS_PERFCTRL_EXL;
		if (boot_cpu_type() == CPU_XLR)
			reg.control[i] |= M_PERFCTL_COUNT_ALL_THREADS;
			reg.control[i] |= XLR_PERFCTRL_ALLTHREADS;
		reg.counter[i] = 0x80000000 - ctr[i].count;
	}
}
@@ -254,7 +240,7 @@ static int mipsxx_perfcount_handler(void)
	case n + 1:							\
		control = r_c0_perfctrl ## n();				\
		counter = r_c0_perfcntr ## n();				\
		if ((control & M_PERFCTL_INTERRUPT_ENABLE) &&		\
		if ((control & MIPS_PERFCTRL_IE) &&			\
		    (counter & M_COUNTER_OVERFLOW)) {			\
			oprofile_add_sample(get_irq_regs(), n);		\
			w_c0_perfcntr ## n(reg.counter[n]);		\
@@ -273,11 +259,11 @@ static inline int __n_counters(void)
{
	if (!cpu_has_perf)
		return 0;
	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
	if (!(read_c0_perfctrl0() & MIPS_PERFCTRL_M))
		return 1;
	if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
	if (!(read_c0_perfctrl1() & MIPS_PERFCTRL_M))
		return 2;
	if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
	if (!(read_c0_perfctrl2() & MIPS_PERFCTRL_M))
		return 3;

	return 4;