aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/perf_event_mipsxx.c
diff options
context:
space:
mode:
authorAl Cooper <alcooperx@gmail.com>2012-07-13 16:44:54 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-10-11 05:04:34 -0400
commita7911a8fd16201a28110c99ecb3deed8aebb4fdc (patch)
treed097d7a28b525b207125a54d930e7d7bcc9916b6 /arch/mips/kernel/perf_event_mipsxx.c
parent399aaa2568ad90e229d73da8e95ae460d322a4f3 (diff)
MIPS: perf: Add perf functionality for BMIPS5000
Add hardware performance counter support to kernel "perf" code for BMIPS5000. The BMIPS5000 performance counters are similar to MIPS MTI cores, so the changes were mostly made in perf_event_mipsxx.c which is typically for MTI cores. Signed-off-by: Al Cooper <alcooperx@gmail.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/4109/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/perf_event_mipsxx.c')
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c103
1 files changed, 102 insertions, 1 deletions
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index cb213089ed2..a9b995dcf69 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -28,6 +28,8 @@
28#include <asm/time.h> /* For perf_irq */ 28#include <asm/time.h> /* For perf_irq */
29 29
30#define MIPS_MAX_HWEVENTS 4 30#define MIPS_MAX_HWEVENTS 4
31#define MIPS_TCS_PER_COUNTER 2
32#define MIPS_CPUID_TO_COUNTER_MASK (MIPS_TCS_PER_COUNTER - 1)
31 33
32struct cpu_hw_events { 34struct cpu_hw_events {
33 /* Array of events on this cpu. */ 35 /* Array of events on this cpu. */
@@ -108,13 +110,20 @@ static struct mips_pmu mipspmu;
108#define M_PERFCTL_INTERRUPT_ENABLE (1 << 4) 110#define M_PERFCTL_INTERRUPT_ENABLE (1 << 4)
109#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5) 111#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5)
110#define M_PERFCTL_VPEID(vpe) ((vpe) << 16) 112#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
113
114#ifdef CONFIG_CPU_BMIPS5000
115#define M_PERFCTL_MT_EN(filter) 0
116#else /* !CONFIG_CPU_BMIPS5000 */
111#define M_PERFCTL_MT_EN(filter) ((filter) << 20) 117#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
118#endif /* CONFIG_CPU_BMIPS5000 */
119
112#define M_TC_EN_ALL M_PERFCTL_MT_EN(0) 120#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
113#define M_TC_EN_VPE M_PERFCTL_MT_EN(1) 121#define M_TC_EN_VPE M_PERFCTL_MT_EN(1)
114#define M_TC_EN_TC M_PERFCTL_MT_EN(2) 122#define M_TC_EN_TC M_PERFCTL_MT_EN(2)
115#define M_PERFCTL_TCID(tcid) ((tcid) << 22) 123#define M_PERFCTL_TCID(tcid) ((tcid) << 22)
116#define M_PERFCTL_WIDE (1 << 30) 124#define M_PERFCTL_WIDE (1 << 30)
117#define M_PERFCTL_MORE (1 << 31) 125#define M_PERFCTL_MORE (1 << 31)
126#define M_PERFCTL_TC (1 << 30)
118 127
119#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \ 128#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \
120 M_PERFCTL_KERNEL | \ 129 M_PERFCTL_KERNEL | \
@@ -135,12 +144,17 @@ static int cpu_has_mipsmt_pertccounters;
135 144
136static DEFINE_RWLOCK(pmuint_rwlock); 145static DEFINE_RWLOCK(pmuint_rwlock);
137 146
147#if defined(CONFIG_CPU_BMIPS5000)
148#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
149 0 : (smp_processor_id() & MIPS_CPUID_TO_COUNTER_MASK))
150#else
138/* 151/*
139 * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because 152 * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because
140 * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs. 153 * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs.
141 */ 154 */
142#define vpe_id() (cpu_has_mipsmt_pertccounters ? \ 155#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
143 0 : smp_processor_id()) 156 0 : smp_processor_id())
157#endif
144 158
145/* Copied from op_model_mipsxx.c */ 159/* Copied from op_model_mipsxx.c */
146static unsigned int vpe_shift(void) 160static unsigned int vpe_shift(void)
@@ -334,6 +348,11 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
334 (evt->config_base & M_PERFCTL_CONFIG_MASK) | 348 (evt->config_base & M_PERFCTL_CONFIG_MASK) |
335 /* Make sure interrupt enabled. */ 349 /* Make sure interrupt enabled. */
336 M_PERFCTL_INTERRUPT_ENABLE; 350 M_PERFCTL_INTERRUPT_ENABLE;
351 if (IS_ENABLED(CONFIG_CPU_BMIPS5000))
352 /* enable the counter for the calling thread */
353 cpuc->saved_ctrl[idx] |=
354 (1 << (12 + vpe_id())) | M_PERFCTL_TC;
355
337 /* 356 /*
338 * We do not actually let the counter run. Leave it until start(). 357 * We do not actually let the counter run. Leave it until start().
339 */ 358 */
@@ -814,6 +833,13 @@ static const struct mips_perf_event octeon_event_map[PERF_COUNT_HW_MAX] = {
814 [PERF_COUNT_HW_BUS_CYCLES] = { 0x25, CNTR_ALL }, 833 [PERF_COUNT_HW_BUS_CYCLES] = { 0x25, CNTR_ALL },
815}; 834};
816 835
836static const struct mips_perf_event bmips5000_event_map
837 [PERF_COUNT_HW_MAX] = {
838 [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN | CNTR_ODD, T },
839 [PERF_COUNT_HW_INSTRUCTIONS] = { 0x01, CNTR_EVEN | CNTR_ODD, T },
840 [PERF_COUNT_HW_BRANCH_MISSES] = { 0x02, CNTR_ODD, T },
841};
842
817/* 24K/34K/1004K cores can share the same cache event map. */ 843/* 24K/34K/1004K cores can share the same cache event map. */
818static const struct mips_perf_event mipsxxcore_cache_map 844static const struct mips_perf_event mipsxxcore_cache_map
819 [PERF_COUNT_HW_CACHE_MAX] 845 [PERF_COUNT_HW_CACHE_MAX]
@@ -966,6 +992,65 @@ static const struct mips_perf_event mipsxx74Kcore_cache_map
966}, 992},
967}; 993};
968 994
995/* BMIPS5000 */
996static const struct mips_perf_event bmips5000_cache_map
997 [PERF_COUNT_HW_CACHE_MAX]
998 [PERF_COUNT_HW_CACHE_OP_MAX]
999 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
1000[C(L1D)] = {
1001 /*
1002 * Like some other architectures (e.g. ARM), the performance
1003 * counters don't differentiate between read and write
1004 * accesses/misses, so this isn't strictly correct, but it's the
1005 * best we can do. Writes and reads get combined.
1006 */
1007 [C(OP_READ)] = {
1008 [C(RESULT_ACCESS)] = { 12, CNTR_EVEN, T },
1009 [C(RESULT_MISS)] = { 12, CNTR_ODD, T },
1010 },
1011 [C(OP_WRITE)] = {
1012 [C(RESULT_ACCESS)] = { 12, CNTR_EVEN, T },
1013 [C(RESULT_MISS)] = { 12, CNTR_ODD, T },
1014 },
1015},
1016[C(L1I)] = {
1017 [C(OP_READ)] = {
1018 [C(RESULT_ACCESS)] = { 10, CNTR_EVEN, T },
1019 [C(RESULT_MISS)] = { 10, CNTR_ODD, T },
1020 },
1021 [C(OP_WRITE)] = {
1022 [C(RESULT_ACCESS)] = { 10, CNTR_EVEN, T },
1023 [C(RESULT_MISS)] = { 10, CNTR_ODD, T },
1024 },
1025 [C(OP_PREFETCH)] = {
1026 [C(RESULT_ACCESS)] = { 23, CNTR_EVEN, T },
1027 /*
1028 * Note that MIPS has only "hit" events countable for
1029 * the prefetch operation.
1030 */
1031 },
1032},
1033[C(LL)] = {
1034 [C(OP_READ)] = {
1035 [C(RESULT_ACCESS)] = { 28, CNTR_EVEN, P },
1036 [C(RESULT_MISS)] = { 28, CNTR_ODD, P },
1037 },
1038 [C(OP_WRITE)] = {
1039 [C(RESULT_ACCESS)] = { 28, CNTR_EVEN, P },
1040 [C(RESULT_MISS)] = { 28, CNTR_ODD, P },
1041 },
1042},
1043[C(BPU)] = {
1044 /* Using the same code for *HW_BRANCH* */
1045 [C(OP_READ)] = {
1046 [C(RESULT_MISS)] = { 0x02, CNTR_ODD, T },
1047 },
1048 [C(OP_WRITE)] = {
1049 [C(RESULT_MISS)] = { 0x02, CNTR_ODD, T },
1050 },
1051},
1052};
1053
969 1054
970static const struct mips_perf_event octeon_cache_map 1055static const struct mips_perf_event octeon_cache_map
971 [PERF_COUNT_HW_CACHE_MAX] 1056 [PERF_COUNT_HW_CACHE_MAX]
@@ -1240,6 +1325,11 @@ static irqreturn_t mipsxx_pmu_handle_irq(int irq, void *dev)
1240#define IS_RANGE_V_1004K_EVENT(r) ((r) == 47) 1325#define IS_RANGE_V_1004K_EVENT(r) ((r) == 47)
1241#endif 1326#endif
1242 1327
1328/* BMIPS5000 */
1329#define IS_BOTH_COUNTERS_BMIPS5000_EVENT(b) \
1330 ((b) == 0 || (b) == 1)
1331
1332
1243/* 1333/*
1244 * User can use 0-255 raw events, where 0-127 for the events of even 1334 * User can use 0-255 raw events, where 0-127 for the events of even
1245 * counters, and 128-255 for odd counters. Note that bit 7 is used to 1335 * counters, and 128-255 for odd counters. Note that bit 7 is used to
@@ -1310,6 +1400,12 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
1310 raw_event.range = T; 1400 raw_event.range = T;
1311#endif 1401#endif
1312 break; 1402 break;
1403 case CPU_BMIPS5000:
1404 if (IS_BOTH_COUNTERS_BMIPS5000_EVENT(base_id))
1405 raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
1406 else
1407 raw_event.cntr_mask =
1408 raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
1313 } 1409 }
1314 1410
1315 return &raw_event; 1411 return &raw_event;
@@ -1421,6 +1517,11 @@ init_hw_perf_events(void)
1421 mipspmu.cache_event_map = &octeon_cache_map; 1517 mipspmu.cache_event_map = &octeon_cache_map;
1422 mipspmu.map_raw_event = octeon_pmu_map_raw_event; 1518 mipspmu.map_raw_event = octeon_pmu_map_raw_event;
1423 break; 1519 break;
1520 case CPU_BMIPS5000:
1521 mipspmu.name = "BMIPS5000";
1522 mipspmu.general_event_map = &bmips5000_event_map;
1523 mipspmu.cache_event_map = &bmips5000_cache_map;
1524 break;
1424 default: 1525 default:
1425 pr_cont("Either hardware does not support performance " 1526 pr_cont("Either hardware does not support performance "
1426 "counters, or not yet implemented.\n"); 1527 "counters, or not yet implemented.\n");