diff options
| -rw-r--r-- | arch/mips/kernel/perf_event_mipsxx.c | 103 |
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 cb213089ed2b..a9b995dcf691 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 | ||
| 32 | struct cpu_hw_events { | 34 | struct 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 | ||
| 136 | static DEFINE_RWLOCK(pmuint_rwlock); | 145 | static 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 */ |
| 146 | static unsigned int vpe_shift(void) | 160 | static 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 | ||
| 836 | static 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. */ |
| 818 | static const struct mips_perf_event mipsxxcore_cache_map | 844 | static 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 */ | ||
| 996 | static 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 | ||
| 970 | static const struct mips_perf_event octeon_cache_map | 1055 | static 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"); |
