1
2
3
4
5
6
7
8
9
10
11
12
13#define pr_fmt(fmt) "power8-pmu: " fmt
14
15#include "isa207-common.h"
16
17
18
19
20#define EVENT(_name, _code) _name = _code,
21
22enum {
23#include "power8-events-list.h"
24};
25
26#undef EVENT
27
28
29#define POWER8_MMCRA_IFM1 0x0000000040000000UL
30#define POWER8_MMCRA_IFM2 0x0000000080000000UL
31#define POWER8_MMCRA_IFM3 0x00000000C0000000UL
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98extern struct attribute_group isa207_pmu_format_group;
99
100
101static const unsigned int event_alternatives[][MAX_ALT] = {
102 { PM_MRK_ST_CMPL, PM_MRK_ST_CMPL_ALT },
103 { PM_BR_MRK_2PATH, PM_BR_MRK_2PATH_ALT },
104 { PM_L3_CO_MEPF, PM_L3_CO_MEPF_ALT },
105 { PM_MRK_DATA_FROM_L2MISS, PM_MRK_DATA_FROM_L2MISS_ALT },
106 { PM_CMPLU_STALL_ALT, PM_CMPLU_STALL },
107 { PM_BR_2PATH, PM_BR_2PATH_ALT },
108 { PM_INST_DISP, PM_INST_DISP_ALT },
109 { PM_RUN_CYC_ALT, PM_RUN_CYC },
110 { PM_MRK_FILT_MATCH, PM_MRK_FILT_MATCH_ALT },
111 { PM_LD_MISS_L1, PM_LD_MISS_L1_ALT },
112 { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
113};
114
115static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[])
116{
117 int num_alt = 0;
118
119 num_alt = isa207_get_alternatives(event, alt,
120 ARRAY_SIZE(event_alternatives), flags,
121 event_alternatives);
122
123 return num_alt;
124}
125
126GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC);
127GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_GCT_NOSLOT_CYC);
128GENERIC_EVENT_ATTR(stalled-cycles-backend, PM_CMPLU_STALL);
129GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL);
130GENERIC_EVENT_ATTR(branch-instructions, PM_BRU_FIN);
131GENERIC_EVENT_ATTR(branch-misses, PM_BR_MPRED_CMPL);
132GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1);
133GENERIC_EVENT_ATTR(cache-misses, PM_LD_MISS_L1);
134GENERIC_EVENT_ATTR(mem_access, MEM_ACCESS);
135
136CACHE_EVENT_ATTR(L1-dcache-load-misses, PM_LD_MISS_L1);
137CACHE_EVENT_ATTR(L1-dcache-loads, PM_LD_REF_L1);
138
139CACHE_EVENT_ATTR(L1-dcache-prefetches, PM_L1_PREF);
140CACHE_EVENT_ATTR(L1-dcache-store-misses, PM_ST_MISS_L1);
141CACHE_EVENT_ATTR(L1-icache-load-misses, PM_L1_ICACHE_MISS);
142CACHE_EVENT_ATTR(L1-icache-loads, PM_INST_FROM_L1);
143CACHE_EVENT_ATTR(L1-icache-prefetches, PM_IC_PREF_WRITE);
144
145CACHE_EVENT_ATTR(LLC-load-misses, PM_DATA_FROM_L3MISS);
146CACHE_EVENT_ATTR(LLC-loads, PM_DATA_FROM_L3);
147CACHE_EVENT_ATTR(LLC-prefetches, PM_L3_PREF_ALL);
148CACHE_EVENT_ATTR(LLC-store-misses, PM_L2_ST_MISS);
149CACHE_EVENT_ATTR(LLC-stores, PM_L2_ST);
150
151CACHE_EVENT_ATTR(branch-load-misses, PM_BR_MPRED_CMPL);
152CACHE_EVENT_ATTR(branch-loads, PM_BRU_FIN);
153CACHE_EVENT_ATTR(dTLB-load-misses, PM_DTLB_MISS);
154CACHE_EVENT_ATTR(iTLB-load-misses, PM_ITLB_MISS);
155
156static struct attribute *power8_events_attr[] = {
157 GENERIC_EVENT_PTR(PM_CYC),
158 GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC),
159 GENERIC_EVENT_PTR(PM_CMPLU_STALL),
160 GENERIC_EVENT_PTR(PM_INST_CMPL),
161 GENERIC_EVENT_PTR(PM_BRU_FIN),
162 GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
163 GENERIC_EVENT_PTR(PM_LD_REF_L1),
164 GENERIC_EVENT_PTR(PM_LD_MISS_L1),
165 GENERIC_EVENT_PTR(MEM_ACCESS),
166
167 CACHE_EVENT_PTR(PM_LD_MISS_L1),
168 CACHE_EVENT_PTR(PM_LD_REF_L1),
169 CACHE_EVENT_PTR(PM_L1_PREF),
170 CACHE_EVENT_PTR(PM_ST_MISS_L1),
171 CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
172 CACHE_EVENT_PTR(PM_INST_FROM_L1),
173 CACHE_EVENT_PTR(PM_IC_PREF_WRITE),
174 CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
175 CACHE_EVENT_PTR(PM_DATA_FROM_L3),
176 CACHE_EVENT_PTR(PM_L3_PREF_ALL),
177 CACHE_EVENT_PTR(PM_L2_ST_MISS),
178 CACHE_EVENT_PTR(PM_L2_ST),
179
180 CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
181 CACHE_EVENT_PTR(PM_BRU_FIN),
182
183 CACHE_EVENT_PTR(PM_DTLB_MISS),
184 CACHE_EVENT_PTR(PM_ITLB_MISS),
185 NULL
186};
187
188static struct attribute_group power8_pmu_events_group = {
189 .name = "events",
190 .attrs = power8_events_attr,
191};
192
193static const struct attribute_group *power8_pmu_attr_groups[] = {
194 &isa207_pmu_format_group,
195 &power8_pmu_events_group,
196 NULL,
197};
198
199static int power8_generic_events[] = {
200 [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
201 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = PM_GCT_NOSLOT_CYC,
202 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = PM_CMPLU_STALL,
203 [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL,
204 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BRU_FIN,
205 [PERF_COUNT_HW_BRANCH_MISSES] = PM_BR_MPRED_CMPL,
206 [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1,
207 [PERF_COUNT_HW_CACHE_MISSES] = PM_LD_MISS_L1,
208};
209
210static u64 power8_bhrb_filter_map(u64 branch_sample_type)
211{
212 u64 pmu_bhrb_filter = 0;
213
214
215
216
217
218
219
220
221
222 if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
223 return pmu_bhrb_filter;
224
225
226 if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
227 return -1;
228
229 if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL)
230 return -1;
231
232 if (branch_sample_type & PERF_SAMPLE_BRANCH_CALL)
233 return -1;
234
235 if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
236 pmu_bhrb_filter |= POWER8_MMCRA_IFM1;
237 return pmu_bhrb_filter;
238 }
239
240
241 return -1;
242}
243
244static void power8_config_bhrb(u64 pmu_bhrb_filter)
245{
246
247 mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
248}
249
250#define C(x) PERF_COUNT_HW_CACHE_##x
251
252
253
254
255
256
257static int power8_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
258 [ C(L1D) ] = {
259 [ C(OP_READ) ] = {
260 [ C(RESULT_ACCESS) ] = PM_LD_REF_L1,
261 [ C(RESULT_MISS) ] = PM_LD_MISS_L1,
262 },
263 [ C(OP_WRITE) ] = {
264 [ C(RESULT_ACCESS) ] = 0,
265 [ C(RESULT_MISS) ] = PM_ST_MISS_L1,
266 },
267 [ C(OP_PREFETCH) ] = {
268 [ C(RESULT_ACCESS) ] = PM_L1_PREF,
269 [ C(RESULT_MISS) ] = 0,
270 },
271 },
272 [ C(L1I) ] = {
273 [ C(OP_READ) ] = {
274 [ C(RESULT_ACCESS) ] = PM_INST_FROM_L1,
275 [ C(RESULT_MISS) ] = PM_L1_ICACHE_MISS,
276 },
277 [ C(OP_WRITE) ] = {
278 [ C(RESULT_ACCESS) ] = PM_L1_DEMAND_WRITE,
279 [ C(RESULT_MISS) ] = -1,
280 },
281 [ C(OP_PREFETCH) ] = {
282 [ C(RESULT_ACCESS) ] = PM_IC_PREF_WRITE,
283 [ C(RESULT_MISS) ] = 0,
284 },
285 },
286 [ C(LL) ] = {
287 [ C(OP_READ) ] = {
288 [ C(RESULT_ACCESS) ] = PM_DATA_FROM_L3,
289 [ C(RESULT_MISS) ] = PM_DATA_FROM_L3MISS,
290 },
291 [ C(OP_WRITE) ] = {
292 [ C(RESULT_ACCESS) ] = PM_L2_ST,
293 [ C(RESULT_MISS) ] = PM_L2_ST_MISS,
294 },
295 [ C(OP_PREFETCH) ] = {
296 [ C(RESULT_ACCESS) ] = PM_L3_PREF_ALL,
297 [ C(RESULT_MISS) ] = 0,
298 },
299 },
300 [ C(DTLB) ] = {
301 [ C(OP_READ) ] = {
302 [ C(RESULT_ACCESS) ] = 0,
303 [ C(RESULT_MISS) ] = PM_DTLB_MISS,
304 },
305 [ C(OP_WRITE) ] = {
306 [ C(RESULT_ACCESS) ] = -1,
307 [ C(RESULT_MISS) ] = -1,
308 },
309 [ C(OP_PREFETCH) ] = {
310 [ C(RESULT_ACCESS) ] = -1,
311 [ C(RESULT_MISS) ] = -1,
312 },
313 },
314 [ C(ITLB) ] = {
315 [ C(OP_READ) ] = {
316 [ C(RESULT_ACCESS) ] = 0,
317 [ C(RESULT_MISS) ] = PM_ITLB_MISS,
318 },
319 [ C(OP_WRITE) ] = {
320 [ C(RESULT_ACCESS) ] = -1,
321 [ C(RESULT_MISS) ] = -1,
322 },
323 [ C(OP_PREFETCH) ] = {
324 [ C(RESULT_ACCESS) ] = -1,
325 [ C(RESULT_MISS) ] = -1,
326 },
327 },
328 [ C(BPU) ] = {
329 [ C(OP_READ) ] = {
330 [ C(RESULT_ACCESS) ] = PM_BRU_FIN,
331 [ C(RESULT_MISS) ] = PM_BR_MPRED_CMPL,
332 },
333 [ C(OP_WRITE) ] = {
334 [ C(RESULT_ACCESS) ] = -1,
335 [ C(RESULT_MISS) ] = -1,
336 },
337 [ C(OP_PREFETCH) ] = {
338 [ C(RESULT_ACCESS) ] = -1,
339 [ C(RESULT_MISS) ] = -1,
340 },
341 },
342 [ C(NODE) ] = {
343 [ C(OP_READ) ] = {
344 [ C(RESULT_ACCESS) ] = -1,
345 [ C(RESULT_MISS) ] = -1,
346 },
347 [ C(OP_WRITE) ] = {
348 [ C(RESULT_ACCESS) ] = -1,
349 [ C(RESULT_MISS) ] = -1,
350 },
351 [ C(OP_PREFETCH) ] = {
352 [ C(RESULT_ACCESS) ] = -1,
353 [ C(RESULT_MISS) ] = -1,
354 },
355 },
356};
357
358#undef C
359
360static struct power_pmu power8_pmu = {
361 .name = "POWER8",
362 .n_counter = MAX_PMU_COUNTERS,
363 .max_alternatives = MAX_ALT + 1,
364 .add_fields = ISA207_ADD_FIELDS,
365 .test_adder = ISA207_TEST_ADDER,
366 .compute_mmcr = isa207_compute_mmcr,
367 .config_bhrb = power8_config_bhrb,
368 .bhrb_filter_map = power8_bhrb_filter_map,
369 .get_constraint = isa207_get_constraint,
370 .get_alternatives = power8_get_alternatives,
371 .get_mem_data_src = isa207_get_mem_data_src,
372 .get_mem_weight = isa207_get_mem_weight,
373 .disable_pmc = isa207_disable_pmc,
374 .flags = PPMU_HAS_SIER | PPMU_ARCH_207S,
375 .n_generic = ARRAY_SIZE(power8_generic_events),
376 .generic_events = power8_generic_events,
377 .cache_events = &power8_cache_events,
378 .attr_groups = power8_pmu_attr_groups,
379 .bhrb_nr = 32,
380};
381
382static int __init init_power8_pmu(void)
383{
384 int rc;
385
386 if (!cur_cpu_spec->oprofile_cpu_type ||
387 strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power8"))
388 return -ENODEV;
389
390 rc = register_power_pmu(&power8_pmu);
391 if (rc)
392 return rc;
393
394
395 cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
396
397 if (cpu_has_feature(CPU_FTR_PMAO_BUG))
398 pr_info("PMAO restore workaround active.\n");
399
400 return 0;
401}
402early_initcall(init_power8_pmu);
403