0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "power8-pmu: " fmt
0010
0011 #include "isa207-common.h"
0012
0013
0014
0015
0016 #define EVENT(_name, _code) _name = _code,
0017
0018 enum {
0019 #include "power8-events-list.h"
0020 };
0021
0022 #undef EVENT
0023
0024
0025 #define POWER8_MMCRA_IFM1 0x0000000040000000UL
0026 #define POWER8_MMCRA_IFM2 0x0000000080000000UL
0027 #define POWER8_MMCRA_IFM3 0x00000000C0000000UL
0028 #define POWER8_MMCRA_BHRB_MASK 0x00000000C0000000UL
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 extern const struct attribute_group isa207_pmu_format_group;
0096
0097
0098 static const unsigned int event_alternatives[][MAX_ALT] = {
0099 { PM_MRK_ST_CMPL, PM_MRK_ST_CMPL_ALT },
0100 { PM_BR_MRK_2PATH, PM_BR_MRK_2PATH_ALT },
0101 { PM_L3_CO_MEPF, PM_L3_CO_MEPF_ALT },
0102 { PM_MRK_DATA_FROM_L2MISS, PM_MRK_DATA_FROM_L2MISS_ALT },
0103 { PM_CMPLU_STALL_ALT, PM_CMPLU_STALL },
0104 { PM_BR_2PATH, PM_BR_2PATH_ALT },
0105 { PM_INST_DISP, PM_INST_DISP_ALT },
0106 { PM_RUN_CYC_ALT, PM_RUN_CYC },
0107 { PM_MRK_FILT_MATCH, PM_MRK_FILT_MATCH_ALT },
0108 { PM_LD_MISS_L1, PM_LD_MISS_L1_ALT },
0109 { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
0110 };
0111
0112 static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[])
0113 {
0114 int num_alt = 0;
0115
0116 num_alt = isa207_get_alternatives(event, alt,
0117 ARRAY_SIZE(event_alternatives), flags,
0118 event_alternatives);
0119
0120 return num_alt;
0121 }
0122
0123 GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC);
0124 GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_GCT_NOSLOT_CYC);
0125 GENERIC_EVENT_ATTR(stalled-cycles-backend, PM_CMPLU_STALL);
0126 GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL);
0127 GENERIC_EVENT_ATTR(branch-instructions, PM_BRU_FIN);
0128 GENERIC_EVENT_ATTR(branch-misses, PM_BR_MPRED_CMPL);
0129 GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1);
0130 GENERIC_EVENT_ATTR(cache-misses, PM_LD_MISS_L1);
0131 GENERIC_EVENT_ATTR(mem_access, MEM_ACCESS);
0132
0133 CACHE_EVENT_ATTR(L1-dcache-load-misses, PM_LD_MISS_L1);
0134 CACHE_EVENT_ATTR(L1-dcache-loads, PM_LD_REF_L1);
0135
0136 CACHE_EVENT_ATTR(L1-dcache-prefetches, PM_L1_PREF);
0137 CACHE_EVENT_ATTR(L1-dcache-store-misses, PM_ST_MISS_L1);
0138 CACHE_EVENT_ATTR(L1-icache-load-misses, PM_L1_ICACHE_MISS);
0139 CACHE_EVENT_ATTR(L1-icache-loads, PM_INST_FROM_L1);
0140 CACHE_EVENT_ATTR(L1-icache-prefetches, PM_IC_PREF_WRITE);
0141
0142 CACHE_EVENT_ATTR(LLC-load-misses, PM_DATA_FROM_L3MISS);
0143 CACHE_EVENT_ATTR(LLC-loads, PM_DATA_FROM_L3);
0144 CACHE_EVENT_ATTR(LLC-prefetches, PM_L3_PREF_ALL);
0145 CACHE_EVENT_ATTR(LLC-store-misses, PM_L2_ST_MISS);
0146 CACHE_EVENT_ATTR(LLC-stores, PM_L2_ST);
0147
0148 CACHE_EVENT_ATTR(branch-load-misses, PM_BR_MPRED_CMPL);
0149 CACHE_EVENT_ATTR(branch-loads, PM_BRU_FIN);
0150 CACHE_EVENT_ATTR(dTLB-load-misses, PM_DTLB_MISS);
0151 CACHE_EVENT_ATTR(iTLB-load-misses, PM_ITLB_MISS);
0152
0153 static struct attribute *power8_events_attr[] = {
0154 GENERIC_EVENT_PTR(PM_CYC),
0155 GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC),
0156 GENERIC_EVENT_PTR(PM_CMPLU_STALL),
0157 GENERIC_EVENT_PTR(PM_INST_CMPL),
0158 GENERIC_EVENT_PTR(PM_BRU_FIN),
0159 GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
0160 GENERIC_EVENT_PTR(PM_LD_REF_L1),
0161 GENERIC_EVENT_PTR(PM_LD_MISS_L1),
0162 GENERIC_EVENT_PTR(MEM_ACCESS),
0163
0164 CACHE_EVENT_PTR(PM_LD_MISS_L1),
0165 CACHE_EVENT_PTR(PM_LD_REF_L1),
0166 CACHE_EVENT_PTR(PM_L1_PREF),
0167 CACHE_EVENT_PTR(PM_ST_MISS_L1),
0168 CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
0169 CACHE_EVENT_PTR(PM_INST_FROM_L1),
0170 CACHE_EVENT_PTR(PM_IC_PREF_WRITE),
0171 CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
0172 CACHE_EVENT_PTR(PM_DATA_FROM_L3),
0173 CACHE_EVENT_PTR(PM_L3_PREF_ALL),
0174 CACHE_EVENT_PTR(PM_L2_ST_MISS),
0175 CACHE_EVENT_PTR(PM_L2_ST),
0176
0177 CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
0178 CACHE_EVENT_PTR(PM_BRU_FIN),
0179
0180 CACHE_EVENT_PTR(PM_DTLB_MISS),
0181 CACHE_EVENT_PTR(PM_ITLB_MISS),
0182 NULL
0183 };
0184
0185 static const struct attribute_group power8_pmu_events_group = {
0186 .name = "events",
0187 .attrs = power8_events_attr,
0188 };
0189
0190 static struct attribute *power8_pmu_caps_attrs[] = {
0191 NULL
0192 };
0193
0194 static struct attribute_group power8_pmu_caps_group = {
0195 .name = "caps",
0196 .attrs = power8_pmu_caps_attrs,
0197 };
0198
0199 static const struct attribute_group *power8_pmu_attr_groups[] = {
0200 &isa207_pmu_format_group,
0201 &power8_pmu_events_group,
0202 &power8_pmu_caps_group,
0203 NULL,
0204 };
0205
0206 static int power8_generic_events[] = {
0207 [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
0208 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = PM_GCT_NOSLOT_CYC,
0209 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = PM_CMPLU_STALL,
0210 [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL,
0211 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BRU_FIN,
0212 [PERF_COUNT_HW_BRANCH_MISSES] = PM_BR_MPRED_CMPL,
0213 [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1,
0214 [PERF_COUNT_HW_CACHE_MISSES] = PM_LD_MISS_L1,
0215 };
0216
0217 static u64 power8_bhrb_filter_map(u64 branch_sample_type)
0218 {
0219 u64 pmu_bhrb_filter = 0;
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
0230 return pmu_bhrb_filter;
0231
0232
0233 if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
0234 return -1;
0235
0236 if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL)
0237 return -1;
0238
0239 if (branch_sample_type & PERF_SAMPLE_BRANCH_CALL)
0240 return -1;
0241
0242 if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
0243 pmu_bhrb_filter |= POWER8_MMCRA_IFM1;
0244 return pmu_bhrb_filter;
0245 }
0246
0247
0248 return -1;
0249 }
0250
0251 static void power8_config_bhrb(u64 pmu_bhrb_filter)
0252 {
0253 pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK;
0254
0255
0256 mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
0257 }
0258
0259 #define C(x) PERF_COUNT_HW_CACHE_##x
0260
0261
0262
0263
0264
0265
0266 static u64 power8_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0267 [ C(L1D) ] = {
0268 [ C(OP_READ) ] = {
0269 [ C(RESULT_ACCESS) ] = PM_LD_REF_L1,
0270 [ C(RESULT_MISS) ] = PM_LD_MISS_L1,
0271 },
0272 [ C(OP_WRITE) ] = {
0273 [ C(RESULT_ACCESS) ] = 0,
0274 [ C(RESULT_MISS) ] = PM_ST_MISS_L1,
0275 },
0276 [ C(OP_PREFETCH) ] = {
0277 [ C(RESULT_ACCESS) ] = PM_L1_PREF,
0278 [ C(RESULT_MISS) ] = 0,
0279 },
0280 },
0281 [ C(L1I) ] = {
0282 [ C(OP_READ) ] = {
0283 [ C(RESULT_ACCESS) ] = PM_INST_FROM_L1,
0284 [ C(RESULT_MISS) ] = PM_L1_ICACHE_MISS,
0285 },
0286 [ C(OP_WRITE) ] = {
0287 [ C(RESULT_ACCESS) ] = PM_L1_DEMAND_WRITE,
0288 [ C(RESULT_MISS) ] = -1,
0289 },
0290 [ C(OP_PREFETCH) ] = {
0291 [ C(RESULT_ACCESS) ] = PM_IC_PREF_WRITE,
0292 [ C(RESULT_MISS) ] = 0,
0293 },
0294 },
0295 [ C(LL) ] = {
0296 [ C(OP_READ) ] = {
0297 [ C(RESULT_ACCESS) ] = PM_DATA_FROM_L3,
0298 [ C(RESULT_MISS) ] = PM_DATA_FROM_L3MISS,
0299 },
0300 [ C(OP_WRITE) ] = {
0301 [ C(RESULT_ACCESS) ] = PM_L2_ST,
0302 [ C(RESULT_MISS) ] = PM_L2_ST_MISS,
0303 },
0304 [ C(OP_PREFETCH) ] = {
0305 [ C(RESULT_ACCESS) ] = PM_L3_PREF_ALL,
0306 [ C(RESULT_MISS) ] = 0,
0307 },
0308 },
0309 [ C(DTLB) ] = {
0310 [ C(OP_READ) ] = {
0311 [ C(RESULT_ACCESS) ] = 0,
0312 [ C(RESULT_MISS) ] = PM_DTLB_MISS,
0313 },
0314 [ C(OP_WRITE) ] = {
0315 [ C(RESULT_ACCESS) ] = -1,
0316 [ C(RESULT_MISS) ] = -1,
0317 },
0318 [ C(OP_PREFETCH) ] = {
0319 [ C(RESULT_ACCESS) ] = -1,
0320 [ C(RESULT_MISS) ] = -1,
0321 },
0322 },
0323 [ C(ITLB) ] = {
0324 [ C(OP_READ) ] = {
0325 [ C(RESULT_ACCESS) ] = 0,
0326 [ C(RESULT_MISS) ] = PM_ITLB_MISS,
0327 },
0328 [ C(OP_WRITE) ] = {
0329 [ C(RESULT_ACCESS) ] = -1,
0330 [ C(RESULT_MISS) ] = -1,
0331 },
0332 [ C(OP_PREFETCH) ] = {
0333 [ C(RESULT_ACCESS) ] = -1,
0334 [ C(RESULT_MISS) ] = -1,
0335 },
0336 },
0337 [ C(BPU) ] = {
0338 [ C(OP_READ) ] = {
0339 [ C(RESULT_ACCESS) ] = PM_BRU_FIN,
0340 [ C(RESULT_MISS) ] = PM_BR_MPRED_CMPL,
0341 },
0342 [ C(OP_WRITE) ] = {
0343 [ C(RESULT_ACCESS) ] = -1,
0344 [ C(RESULT_MISS) ] = -1,
0345 },
0346 [ C(OP_PREFETCH) ] = {
0347 [ C(RESULT_ACCESS) ] = -1,
0348 [ C(RESULT_MISS) ] = -1,
0349 },
0350 },
0351 [ C(NODE) ] = {
0352 [ C(OP_READ) ] = {
0353 [ C(RESULT_ACCESS) ] = -1,
0354 [ C(RESULT_MISS) ] = -1,
0355 },
0356 [ C(OP_WRITE) ] = {
0357 [ C(RESULT_ACCESS) ] = -1,
0358 [ C(RESULT_MISS) ] = -1,
0359 },
0360 [ C(OP_PREFETCH) ] = {
0361 [ C(RESULT_ACCESS) ] = -1,
0362 [ C(RESULT_MISS) ] = -1,
0363 },
0364 },
0365 };
0366
0367 #undef C
0368
0369 static struct power_pmu power8_pmu = {
0370 .name = "POWER8",
0371 .n_counter = MAX_PMU_COUNTERS,
0372 .max_alternatives = MAX_ALT + 1,
0373 .add_fields = ISA207_ADD_FIELDS,
0374 .test_adder = ISA207_TEST_ADDER,
0375 .compute_mmcr = isa207_compute_mmcr,
0376 .config_bhrb = power8_config_bhrb,
0377 .bhrb_filter_map = power8_bhrb_filter_map,
0378 .get_constraint = isa207_get_constraint,
0379 .get_alternatives = power8_get_alternatives,
0380 .get_mem_data_src = isa207_get_mem_data_src,
0381 .get_mem_weight = isa207_get_mem_weight,
0382 .disable_pmc = isa207_disable_pmc,
0383 .flags = PPMU_HAS_SIER | PPMU_ARCH_207S,
0384 .n_generic = ARRAY_SIZE(power8_generic_events),
0385 .generic_events = power8_generic_events,
0386 .cache_events = &power8_cache_events,
0387 .attr_groups = power8_pmu_attr_groups,
0388 .bhrb_nr = 32,
0389 };
0390
0391 int __init init_power8_pmu(void)
0392 {
0393 int rc;
0394 unsigned int pvr = mfspr(SPRN_PVR);
0395
0396 if (PVR_VER(pvr) != PVR_POWER8E && PVR_VER(pvr) != PVR_POWER8NVL &&
0397 PVR_VER(pvr) != PVR_POWER8)
0398 return -ENODEV;
0399
0400 rc = register_power_pmu(&power8_pmu);
0401 if (rc)
0402 return rc;
0403
0404
0405 cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
0406
0407 if (cpu_has_feature(CPU_FTR_PMAO_BUG))
0408 pr_info("PMAO restore workaround active.\n");
0409
0410 return 0;
0411 }