aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/kernel/perf_event_mipsxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/perf_event_mipsxx.c')
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c461
1 files changed, 283 insertions, 178 deletions
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index e3b897acfbc..4f2d9dece7a 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -28,6 +28,8 @@
#include <asm/time.h> /* For perf_irq */
#define MIPS_MAX_HWEVENTS 4
+#define MIPS_TCS_PER_COUNTER 2
+#define MIPS_CPUID_TO_COUNTER_MASK (MIPS_TCS_PER_COUNTER - 1)
struct cpu_hw_events {
/* Array of events on this cpu. */
@@ -78,7 +80,6 @@ struct mips_perf_event {
static struct mips_perf_event raw_event;
static DEFINE_MUTEX(raw_event_mutex);
-#define UNSUPPORTED_PERF_EVENT_ID 0xffffffff
#define C(x) PERF_COUNT_HW_CACHE_##x
struct mips_pmu {
@@ -102,20 +103,27 @@ static struct mips_pmu mipspmu;
#define M_CONFIG1_PC (1 << 4)
-#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_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_VPEID(vpe) ((vpe) << 16)
+
+#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_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)
+#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_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \
M_PERFCTL_KERNEL | \
@@ -131,21 +139,21 @@ static struct mips_pmu mipspmu;
#define M_PERFCTL_EVENT_MASK 0xfe0
-#ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
static int cpu_has_mipsmt_pertccounters;
static DEFINE_RWLOCK(pmuint_rwlock);
+#if defined(CONFIG_CPU_BMIPS5000)
+#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
+ 0 : (smp_processor_id() & MIPS_CPUID_TO_COUNTER_MASK))
+#else
/*
* FIXME: For VSMP, vpe_id() is redefined for Perf-events, because
* cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs.
*/
-#if defined(CONFIG_HW_PERF_EVENTS)
-#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
- 0 : smp_processor_id())
-#else
#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
- 0 : cpu_data[smp_processor_id()].vpe_id)
+ 0 : smp_processor_id())
#endif
/* Copied from op_model_mipsxx.c */
@@ -162,15 +170,10 @@ static unsigned int counters_total_to_per_cpu(unsigned int counters)
return counters >> vpe_shift();
}
-static unsigned int counters_per_cpu_to_total(unsigned int counters)
-{
- return counters << vpe_shift();
-}
-
-#else /* !CONFIG_MIPS_MT_SMP */
+#else /* !CONFIG_MIPS_PERF_SHARED_TC_COUNTERS */
#define vpe_id() 0
-#endif /* CONFIG_MIPS_MT_SMP */
+#endif /* CONFIG_MIPS_PERF_SHARED_TC_COUNTERS */
static void resume_local_counters(void);
static void pause_local_counters(void);
@@ -345,6 +348,11 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
(evt->config_base & M_PERFCTL_CONFIG_MASK) |
/* Make sure interrupt enabled. */
M_PERFCTL_INTERRUPT_ENABLE;
+ if (IS_ENABLED(CONFIG_CPU_BMIPS5000))
+ /* enable the counter for the calling thread */
+ cpuc->saved_ctrl[idx] |=
+ (1 << (12 + vpe_id())) | M_PERFCTL_TC;
+
/*
* We do not actually let the counter run. Leave it until start().
*/
@@ -514,7 +522,7 @@ static void mipspmu_read(struct perf_event *event)
static void mipspmu_enable(struct pmu *pmu)
{
-#ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
write_unlock(&pmuint_rwlock);
#endif
resume_local_counters();
@@ -534,7 +542,7 @@ static void mipspmu_enable(struct pmu *pmu)
static void mipspmu_disable(struct pmu *pmu)
{
pause_local_counters();
-#ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
write_lock(&pmuint_rwlock);
#endif
}
@@ -606,6 +614,10 @@ static int mipspmu_event_init(struct perf_event *event)
{
int err = 0;
+ /* does not support taken branch sampling */
+ if (has_branch_stack(event))
+ return -EOPNOTSUPP;
+
switch (event->attr.type) {
case PERF_TYPE_RAW:
case PERF_TYPE_HARDWARE:
@@ -665,13 +677,10 @@ static unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev)
static const struct mips_perf_event *mipspmu_map_general_event(int idx)
{
- const struct mips_perf_event *pev;
-
- pev = ((*mipspmu.general_event_map)[idx].event_id ==
- UNSUPPORTED_PERF_EVENT_ID ? ERR_PTR(-EOPNOTSUPP) :
- &(*mipspmu.general_event_map)[idx]);
- return pev;
+ if ((*mipspmu.general_event_map)[idx].cntr_mask == 0)
+ return ERR_PTR(-EOPNOTSUPP);
+ return &(*mipspmu.general_event_map)[idx];
}
static const struct mips_perf_event *mipspmu_map_cache_event(u64 config)
@@ -696,7 +705,7 @@ static const struct mips_perf_event *mipspmu_map_cache_event(u64 config)
[cache_op]
[cache_result]);
- if (pev->event_id == UNSUPPORTED_PERF_EVENT_ID)
+ if (pev->cntr_mask == 0)
return ERR_PTR(-EOPNOTSUPP);
return pev;
@@ -796,41 +805,51 @@ static void reset_counters(void *arg)
}
}
-/* 24K/34K/1004K cores can share the same event map. */
+/* 24K/34K/1004K/interAptiv/loongson1 cores share the same event map. */
static const struct mips_perf_event mipsxxcore_event_map
[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD, P },
[PERF_COUNT_HW_INSTRUCTIONS] = { 0x01, CNTR_EVEN | CNTR_ODD, T },
- [PERF_COUNT_HW_CACHE_REFERENCES] = { UNSUPPORTED_PERF_EVENT_ID },
- [PERF_COUNT_HW_CACHE_MISSES] = { UNSUPPORTED_PERF_EVENT_ID },
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x02, CNTR_EVEN, T },
[PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
- [PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
};
-/* 74K core has different branch event code. */
-static const struct mips_perf_event mipsxx74Kcore_event_map
+/* 74K/proAptiv core has different branch event code. */
+static const struct mips_perf_event mipsxxcore_event_map2
[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD, P },
[PERF_COUNT_HW_INSTRUCTIONS] = { 0x01, CNTR_EVEN | CNTR_ODD, T },
- [PERF_COUNT_HW_CACHE_REFERENCES] = { UNSUPPORTED_PERF_EVENT_ID },
- [PERF_COUNT_HW_CACHE_MISSES] = { UNSUPPORTED_PERF_EVENT_ID },
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x27, CNTR_EVEN, T },
[PERF_COUNT_HW_BRANCH_MISSES] = { 0x27, CNTR_ODD, T },
- [PERF_COUNT_HW_BUS_CYCLES] = { UNSUPPORTED_PERF_EVENT_ID },
};
static const struct mips_perf_event octeon_event_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
[PERF_COUNT_HW_INSTRUCTIONS] = { 0x03, CNTR_ALL },
[PERF_COUNT_HW_CACHE_REFERENCES] = { 0x2b, CNTR_ALL },
- [PERF_COUNT_HW_CACHE_MISSES] = { 0x2e, CNTR_ALL },
+ [PERF_COUNT_HW_CACHE_MISSES] = { 0x2e, CNTR_ALL },
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x08, CNTR_ALL },
[PERF_COUNT_HW_BRANCH_MISSES] = { 0x09, CNTR_ALL },
[PERF_COUNT_HW_BUS_CYCLES] = { 0x25, CNTR_ALL },
};
-/* 24K/34K/1004K cores can share the same cache event map. */
+static const struct mips_perf_event bmips5000_event_map
+ [PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD, T },
+ [PERF_COUNT_HW_INSTRUCTIONS] = { 0x01, CNTR_EVEN | CNTR_ODD, T },
+ [PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
+};
+
+static const struct mips_perf_event xlp_event_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = { 0x01, CNTR_ALL },
+ [PERF_COUNT_HW_INSTRUCTIONS] = { 0x18, CNTR_ALL }, /* PAPI_TOT_INS */
+ [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
+ [PERF_COUNT_HW_CACHE_MISSES] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x1b, CNTR_ALL }, /* PAPI_BR_CN */
+ [PERF_COUNT_HW_BRANCH_MISSES] = { 0x1c, CNTR_ALL }, /* PAPI_BR_MSP */
+};
+
+/* 24K/34K/1004K/interAptiv/loongson1 cores share the same cache event map. */
static const struct mips_perf_event mipsxxcore_cache_map
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -850,10 +869,6 @@ static const struct mips_perf_event mipsxxcore_cache_map
[C(RESULT_ACCESS)] = { 0x0a, CNTR_EVEN, T },
[C(RESULT_MISS)] = { 0x0b, CNTR_EVEN | CNTR_ODD, T },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
[C(L1I)] = {
[C(OP_READ)] = {
@@ -870,7 +885,6 @@ static const struct mips_perf_event mipsxxcore_cache_map
* Note that MIPS has only "hit" events countable for
* the prefetch operation.
*/
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(LL)] = {
@@ -882,10 +896,6 @@ static const struct mips_perf_event mipsxxcore_cache_map
[C(RESULT_ACCESS)] = { 0x15, CNTR_ODD, P },
[C(RESULT_MISS)] = { 0x16, CNTR_EVEN, P },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
[C(DTLB)] = {
[C(OP_READ)] = {
@@ -896,10 +906,6 @@ static const struct mips_perf_event mipsxxcore_cache_map
[C(RESULT_ACCESS)] = { 0x06, CNTR_EVEN, T },
[C(RESULT_MISS)] = { 0x06, CNTR_ODD, T },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
[C(ITLB)] = {
[C(OP_READ)] = {
@@ -910,10 +916,6 @@ static const struct mips_perf_event mipsxxcore_cache_map
[C(RESULT_ACCESS)] = { 0x05, CNTR_EVEN, T },
[C(RESULT_MISS)] = { 0x05, CNTR_ODD, T },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
[C(BPU)] = {
/* Using the same code for *HW_BRANCH* */
@@ -925,29 +927,11 @@ static const struct mips_perf_event mipsxxcore_cache_map
[C(RESULT_ACCESS)] = { 0x02, CNTR_EVEN, T },
[C(RESULT_MISS)] = { 0x02, CNTR_ODD, T },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
-},
-[C(NODE)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
};
-/* 74K core has completely different cache event map. */
-static const struct mips_perf_event mipsxx74Kcore_cache_map
+/* 74K/proAptiv core has completely different cache event map. */
+static const struct mips_perf_event mipsxxcore_cache_map2
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
@@ -966,10 +950,6 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
[C(RESULT_ACCESS)] = { 0x17, CNTR_ODD, T },
[C(RESULT_MISS)] = { 0x18, CNTR_ODD, T },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
[C(L1I)] = {
[C(OP_READ)] = {
@@ -986,38 +966,23 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
* Note that MIPS has only "hit" events countable for
* the prefetch operation.
*/
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(LL)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x1c, CNTR_ODD, P },
- [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN | CNTR_ODD, P },
+ [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN, P },
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { 0x1c, CNTR_ODD, P },
- [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN | CNTR_ODD, P },
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
-},
-[C(DTLB)] = {
- /* 74K core does not have specific DTLB events. */
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_MISS)] = { 0x1d, CNTR_EVEN, P },
},
},
+/*
+ * 74K core does not have specific DTLB events. proAptiv core has
+ * "speculative" DTLB events which are numbered 0x63 (even/odd) and
+ * not included here. One can use raw events if really needed.
+ */
[C(ITLB)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x04, CNTR_EVEN, T },
@@ -1027,10 +992,6 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
[C(RESULT_ACCESS)] = { 0x04, CNTR_EVEN, T },
[C(RESULT_MISS)] = { 0x04, CNTR_ODD, T },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
[C(BPU)] = {
/* Using the same code for *HW_BRANCH* */
@@ -1042,23 +1003,64 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
[C(RESULT_ACCESS)] = { 0x27, CNTR_EVEN, T },
[C(RESULT_MISS)] = { 0x27, CNTR_ODD, T },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+},
+};
+
+/* BMIPS5000 */
+static const struct mips_perf_event bmips5000_cache_map
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+ /*
+ * Like some other architectures (e.g. ARM), the performance
+ * counters don't differentiate between read and write
+ * accesses/misses, so this isn't strictly correct, but it's the
+ * best we can do. Writes and reads get combined.
+ */
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { 12, CNTR_EVEN, T },
+ [C(RESULT_MISS)] = { 12, CNTR_ODD, T },
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = { 12, CNTR_EVEN, T },
+ [C(RESULT_MISS)] = { 12, CNTR_ODD, T },
},
},
-[C(NODE)] = {
+[C(L1I)] = {
[C(OP_READ)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_ACCESS)] = { 10, CNTR_EVEN, T },
+ [C(RESULT_MISS)] = { 10, CNTR_ODD, T },
},
[C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_ACCESS)] = { 10, CNTR_EVEN, T },
+ [C(RESULT_MISS)] = { 10, CNTR_ODD, T },
},
[C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_ACCESS)] = { 23, CNTR_EVEN, T },
+ /*
+ * Note that MIPS has only "hit" events countable for
+ * the prefetch operation.
+ */
+ },
+},
+[C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { 28, CNTR_EVEN, P },
+ [C(RESULT_MISS)] = { 28, CNTR_ODD, P },
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = { 28, CNTR_EVEN, P },
+ [C(RESULT_MISS)] = { 28, CNTR_ODD, P },
+ },
+},
+[C(BPU)] = {
+ /* Using the same code for *HW_BRANCH* */
+ [C(OP_READ)] = {
+ [C(RESULT_MISS)] = { 0x02, CNTR_ODD, T },
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_MISS)] = { 0x02, CNTR_ODD, T },
},
},
};
@@ -1075,39 +1077,14 @@ static const struct mips_perf_event octeon_cache_map
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)] = { 0x30, CNTR_ALL },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(L1I)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = { 0x18, CNTR_ALL },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = { 0x19, CNTR_ALL },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
-},
-[C(LL)] = {
- [C(OP_READ)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
},
},
[C(DTLB)] = {
@@ -1116,45 +1093,72 @@ static const struct mips_perf_event octeon_cache_map
* read and write.
*/
[C(OP_READ)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x35, CNTR_ALL },
},
[C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x35, CNTR_ALL },
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
- },
},
[C(ITLB)] = {
[C(OP_READ)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
[C(RESULT_MISS)] = { 0x37, CNTR_ALL },
},
+},
+};
+
+static const struct mips_perf_event xlp_cache_map
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { 0x31, CNTR_ALL }, /* PAPI_L1_DCR */
+ [C(RESULT_MISS)] = { 0x30, CNTR_ALL }, /* PAPI_L1_LDM */
+ },
[C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_ACCESS)] = { 0x2f, CNTR_ALL }, /* PAPI_L1_DCW */
+ [C(RESULT_MISS)] = { 0x2e, CNTR_ALL }, /* PAPI_L1_STM */
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+},
+[C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = { 0x04, CNTR_ALL }, /* PAPI_L1_ICA */
+ [C(RESULT_MISS)] = { 0x07, CNTR_ALL }, /* PAPI_L1_ICM */
},
},
-[C(BPU)] = {
- /* Using the same code for *HW_BRANCH* */
+[C(LL)] = {
[C(OP_READ)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_ACCESS)] = { 0x35, CNTR_ALL }, /* PAPI_L2_DCR */
+ [C(RESULT_MISS)] = { 0x37, CNTR_ALL }, /* PAPI_L2_LDM */
},
[C(OP_WRITE)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+ [C(RESULT_ACCESS)] = { 0x34, CNTR_ALL }, /* PAPI_L2_DCA */
+ [C(RESULT_MISS)] = { 0x36, CNTR_ALL }, /* PAPI_L2_DCM */
},
- [C(OP_PREFETCH)] = {
- [C(RESULT_ACCESS)] = { UNSUPPORTED_PERF_EVENT_ID },
- [C(RESULT_MISS)] = { UNSUPPORTED_PERF_EVENT_ID },
+},
+[C(DTLB)] = {
+ /*
+ * Only general DTLB misses are counted use the same event for
+ * read and write.
+ */
+ [C(OP_READ)] = {
+ [C(RESULT_MISS)] = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_MISS)] = { 0x2d, CNTR_ALL }, /* PAPI_TLB_DM */
+ },
+},
+[C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_MISS)] = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_MISS)] = { 0x08, CNTR_ALL }, /* PAPI_TLB_IM */
+ },
+},
+[C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_MISS)] = { 0x25, CNTR_ALL },
},
},
};
@@ -1305,7 +1309,7 @@ static int mipsxx_pmu_handle_shared_irq(void)
int handled = IRQ_NONE;
struct pt_regs *regs;
- if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26)))
+ if (cpu_has_perf_cntr_intr_bit && !(read_c0_cause() & CAUSEF_PCI))
return handled;
/*
* First we pause the local counters, so that when we are locked
@@ -1315,13 +1319,13 @@ static int mipsxx_pmu_handle_shared_irq(void)
* See also mipsxx_pmu_start().
*/
pause_local_counters();
-#ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
read_lock(&pmuint_rwlock);
#endif
regs = get_irq_regs();
- perf_sample_data_init(&data, 0);
+ perf_sample_data_init(&data, 0, 0);
switch (counters) {
#define HANDLE_COUNTER(n) \
@@ -1347,7 +1351,7 @@ static int mipsxx_pmu_handle_shared_irq(void)
if (handled == IRQ_HANDLED)
irq_work_run();
-#ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
read_unlock(&pmuint_rwlock);
#endif
resume_local_counters();
@@ -1372,13 +1376,17 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
(b) == 25 || (b) == 39 || (r) == 44 || (r) == 174 || \
(r) == 176 || ((b) >= 50 && (b) <= 55) || \
((b) >= 64 && (b) <= 67))
-#define IS_RANGE_V_34K_EVENT(r) ((r) == 47)
+#define IS_RANGE_V_34K_EVENT(r) ((r) == 47)
#endif
/* 74K */
#define IS_BOTH_COUNTERS_74K_EVENT(b) \
((b) == 0 || (b) == 1)
+/* proAptiv */
+#define IS_BOTH_COUNTERS_PROAPTIV_EVENT(b) \
+ ((b) == 0 || (b) == 1)
+
/* 1004K */
#define IS_BOTH_COUNTERS_1004K_EVENT(b) \
((b) == 0 || (b) == 1 || (b) == 11)
@@ -1392,6 +1400,25 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
#define IS_RANGE_V_1004K_EVENT(r) ((r) == 47)
#endif
+/* interAptiv */
+#define IS_BOTH_COUNTERS_INTERAPTIV_EVENT(b) \
+ ((b) == 0 || (b) == 1 || (b) == 11)
+#ifdef CONFIG_MIPS_MT_SMP
+/* The P/V/T info is not provided for "(b) == 38" in SUM, assume P. */
+#define IS_RANGE_P_INTERAPTIV_EVENT(r, b) \
+ ((b) == 0 || (r) == 18 || (b) == 21 || (b) == 22 || \
+ (b) == 25 || (b) == 36 || (b) == 38 || (b) == 39 || \
+ (r) == 44 || (r) == 174 || (r) == 176 || ((b) >= 50 && \
+ (b) <= 59) || (r) == 188 || (b) == 61 || (b) == 62 || \
+ ((b) >= 64 && (b) <= 67))
+#define IS_RANGE_V_INTERAPTIV_EVENT(r) ((r) == 47 || (r) == 175)
+#endif
+
+/* BMIPS5000 */
+#define IS_BOTH_COUNTERS_BMIPS5000_EVENT(b) \
+ ((b) == 0 || (b) == 1)
+
+
/*
* User can use 0-255 raw events, where 0-127 for the events of even
* counters, and 128-255 for odd counters. Note that bit 7 is used to
@@ -1438,6 +1465,7 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
#endif
break;
case CPU_74K:
+ case CPU_1074K:
if (IS_BOTH_COUNTERS_74K_EVENT(base_id))
raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
else
@@ -1447,6 +1475,16 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
raw_event.range = P;
#endif
break;
+ case CPU_PROAPTIV:
+ if (IS_BOTH_COUNTERS_PROAPTIV_EVENT(base_id))
+ raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+ else
+ raw_event.cntr_mask =
+ raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+ raw_event.range = P;
+#endif
+ break;
case CPU_1004K:
if (IS_BOTH_COUNTERS_1004K_EVENT(base_id))
raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
@@ -1462,6 +1500,27 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
raw_event.range = T;
#endif
break;
+ case CPU_INTERAPTIV:
+ if (IS_BOTH_COUNTERS_INTERAPTIV_EVENT(base_id))
+ raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+ else
+ raw_event.cntr_mask =
+ raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+ if (IS_RANGE_P_INTERAPTIV_EVENT(raw_id, base_id))
+ raw_event.range = P;
+ else if (unlikely(IS_RANGE_V_INTERAPTIV_EVENT(raw_id)))
+ raw_event.range = V;
+ else
+ raw_event.range = T;
+#endif
+ break;
+ case CPU_BMIPS5000:
+ if (IS_BOTH_COUNTERS_BMIPS5000_EVENT(base_id))
+ raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+ else
+ raw_event.cntr_mask =
+ raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
}
return &raw_event;
@@ -1500,6 +1559,20 @@ static const struct mips_perf_event *octeon_pmu_map_raw_event(u64 config)
return &raw_event;
}
+static const struct mips_perf_event *xlp_pmu_map_raw_event(u64 config)
+{
+ unsigned int raw_id = config & 0xff;
+
+ /* Only 1-63 are defined */
+ if ((raw_id < 0x01) || (raw_id > 0x3f))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ raw_event.cntr_mask = CNTR_ALL;
+ raw_event.event_id = raw_id;
+
+ return &raw_event;
+}
+
static int __init
init_hw_perf_events(void)
{
@@ -1514,7 +1587,7 @@ init_hw_perf_events(void)
return -ENODEV;
}
-#ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
cpu_has_mipsmt_pertccounters = read_c0_config7() & (1<<19);
if (!cpu_has_mipsmt_pertccounters)
counters = counters_total_to_per_cpu(counters);
@@ -1528,7 +1601,8 @@ init_hw_perf_events(void)
irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
} else {
#endif
- if (cp0_perfcount_irq >= 0)
+ if ((cp0_perfcount_irq >= 0) &&
+ (cp0_compare_irq != cp0_perfcount_irq))
irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
else
irq = -1;
@@ -1551,14 +1625,34 @@ init_hw_perf_events(void)
break;
case CPU_74K:
mipspmu.name = "mips/74K";
- mipspmu.general_event_map = &mipsxx74Kcore_event_map;
- mipspmu.cache_event_map = &mipsxx74Kcore_cache_map;
+ mipspmu.general_event_map = &mipsxxcore_event_map2;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+ break;
+ case CPU_PROAPTIV:
+ mipspmu.name = "mips/proAptiv";
+ mipspmu.general_event_map = &mipsxxcore_event_map2;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map2;
break;
case CPU_1004K:
mipspmu.name = "mips/1004K";
mipspmu.general_event_map = &mipsxxcore_event_map;
mipspmu.cache_event_map = &mipsxxcore_cache_map;
break;
+ case CPU_1074K:
+ mipspmu.name = "mips/1074K";
+ mipspmu.general_event_map = &mipsxxcore_event_map;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map;
+ break;
+ case CPU_INTERAPTIV:
+ mipspmu.name = "mips/interAptiv";
+ mipspmu.general_event_map = &mipsxxcore_event_map;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map;
+ break;
+ case CPU_LOONGSON1:
+ mipspmu.name = "mips/loongson1";
+ mipspmu.general_event_map = &mipsxxcore_event_map;
+ mipspmu.cache_event_map = &mipsxxcore_cache_map;
+ break;
case CPU_CAVIUM_OCTEON:
case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2:
@@ -1567,6 +1661,17 @@ init_hw_perf_events(void)
mipspmu.cache_event_map = &octeon_cache_map;
mipspmu.map_raw_event = octeon_pmu_map_raw_event;
break;
+ case CPU_BMIPS5000:
+ mipspmu.name = "BMIPS5000";
+ mipspmu.general_event_map = &bmips5000_event_map;
+ mipspmu.cache_event_map = &bmips5000_cache_map;
+ break;
+ case CPU_XLP:
+ mipspmu.name = "xlp";
+ mipspmu.general_event_map = &xlp_event_map;
+ mipspmu.cache_event_map = &xlp_cache_map;
+ mipspmu.map_raw_event = xlp_pmu_map_raw_event;
+ break;
default:
pr_cont("Either hardware does not support performance "
"counters, or not yet implemented.\n");