diff options
Diffstat (limited to 'arch/mips/kernel/perf_event_mipsxx.c')
| -rw-r--r-- | arch/mips/kernel/perf_event_mipsxx.c | 461 |
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"); |
