This source file includes following definitions.
- p970_marked_instr_event
- p970_get_constraint
- p970_get_alternatives
- p970_compute_mmcr
- p970_disable_pmc
- init_ppc970_pmu
1
2
3
4
5
6
7 #include <linux/string.h>
8 #include <linux/perf_event.h>
9 #include <asm/reg.h>
10 #include <asm/cputable.h>
11
12
13
14
15 #define PM_PMC_SH 12
16 #define PM_PMC_MSK 0xf
17 #define PM_UNIT_SH 8
18 #define PM_UNIT_MSK 0xf
19 #define PM_SPCSEL_SH 6
20 #define PM_SPCSEL_MSK 3
21 #define PM_BYTE_SH 4
22 #define PM_BYTE_MSK 3
23 #define PM_PMCSEL_MSK 0xf
24
25
26 #define PM_NONE 0
27 #define PM_FPU 1
28 #define PM_VPU 2
29 #define PM_ISU 3
30 #define PM_IFU 4
31 #define PM_IDU 5
32 #define PM_STS 6
33 #define PM_LSU0 7
34 #define PM_LSU1U 8
35 #define PM_LSU1L 9
36 #define PM_LASTUNIT 9
37
38
39
40
41 #define MMCR0_PMC1SEL_SH 8
42 #define MMCR0_PMC2SEL_SH 1
43 #define MMCR_PMCSEL_MSK 0x1f
44
45
46
47
48 #define MMCR1_TTM0SEL_SH 62
49 #define MMCR1_TTM1SEL_SH 59
50 #define MMCR1_TTM3SEL_SH 53
51 #define MMCR1_TTMSEL_MSK 3
52 #define MMCR1_TD_CP_DBG0SEL_SH 50
53 #define MMCR1_TD_CP_DBG1SEL_SH 48
54 #define MMCR1_TD_CP_DBG2SEL_SH 46
55 #define MMCR1_TD_CP_DBG3SEL_SH 44
56 #define MMCR1_PMC1_ADDER_SEL_SH 39
57 #define MMCR1_PMC2_ADDER_SEL_SH 38
58 #define MMCR1_PMC6_ADDER_SEL_SH 37
59 #define MMCR1_PMC5_ADDER_SEL_SH 36
60 #define MMCR1_PMC8_ADDER_SEL_SH 35
61 #define MMCR1_PMC7_ADDER_SEL_SH 34
62 #define MMCR1_PMC3_ADDER_SEL_SH 33
63 #define MMCR1_PMC4_ADDER_SEL_SH 32
64 #define MMCR1_PMC3SEL_SH 27
65 #define MMCR1_PMC4SEL_SH 22
66 #define MMCR1_PMC5SEL_SH 17
67 #define MMCR1_PMC6SEL_SH 12
68 #define MMCR1_PMC7SEL_SH 7
69 #define MMCR1_PMC8SEL_SH 2
70
71 static short mmcr1_adder_bits[8] = {
72 MMCR1_PMC1_ADDER_SEL_SH,
73 MMCR1_PMC2_ADDER_SEL_SH,
74 MMCR1_PMC3_ADDER_SEL_SH,
75 MMCR1_PMC4_ADDER_SEL_SH,
76 MMCR1_PMC5_ADDER_SEL_SH,
77 MMCR1_PMC6_ADDER_SEL_SH,
78 MMCR1_PMC7_ADDER_SEL_SH,
79 MMCR1_PMC8_ADDER_SEL_SH
80 };
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 static unsigned char direct_marked_event[8] = {
128 (1<<2) | (1<<3),
129 (1<<3) | (1<<5),
130 (1<<3) | (1<<5),
131 (1<<4) | (1<<5),
132 (1<<4) | (1<<5),
133 (1<<3) | (1<<4) | (1<<5),
134
135 (1<<4) | (1<<5),
136 (1<<4)
137 };
138
139
140
141
142
143 static int p970_marked_instr_event(u64 event)
144 {
145 int pmc, psel, unit, byte, bit;
146 unsigned int mask;
147
148 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
149 psel = event & PM_PMCSEL_MSK;
150 if (pmc) {
151 if (direct_marked_event[pmc - 1] & (1 << psel))
152 return 1;
153 if (psel == 0)
154 bit = (pmc <= 4)? pmc - 1: 8 - pmc;
155 else if (psel == 7 || psel == 13)
156 bit = 4;
157 else
158 return 0;
159 } else
160 bit = psel;
161
162 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
163 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
164 mask = 0;
165 switch (unit) {
166 case PM_VPU:
167 mask = 0x4c;
168 break;
169 case PM_LSU0:
170
171 mask = 0x085dff00;
172 break;
173 case PM_LSU1L:
174 mask = 0x50 << 24;
175 break;
176 }
177 return (mask >> (byte * 8 + bit)) & 1;
178 }
179
180
181 static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
182 [PM_FPU] = { 0xc80000000000ull, 0x040000000000ull },
183 [PM_VPU] = { 0xc80000000000ull, 0xc40000000000ull },
184 [PM_ISU] = { 0x080000000000ull, 0x020000000000ull },
185 [PM_IFU] = { 0xc80000000000ull, 0x840000000000ull },
186 [PM_IDU] = { 0x380000000000ull, 0x010000000000ull },
187 [PM_STS] = { 0x380000000000ull, 0x310000000000ull },
188 };
189
190 static int p970_get_constraint(u64 event, unsigned long *maskp,
191 unsigned long *valp)
192 {
193 int pmc, byte, unit, sh, spcsel;
194 unsigned long mask = 0, value = 0;
195 int grp = -1;
196
197 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
198 if (pmc) {
199 if (pmc > 8)
200 return -1;
201 sh = (pmc - 1) * 2;
202 mask |= 2 << sh;
203 value |= 1 << sh;
204 grp = ((pmc - 1) >> 1) & 1;
205 }
206 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
207 if (unit) {
208 if (unit > PM_LASTUNIT)
209 return -1;
210 mask |= unit_cons[unit][0];
211 value |= unit_cons[unit][1];
212 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
213
214
215
216
217 if (!pmc)
218 grp = byte & 1;
219
220 mask |= 0xfULL << (28 - 4 * byte);
221 value |= (unsigned long)unit << (28 - 4 * byte);
222 }
223 if (grp == 0) {
224
225 mask |= 0x8000000000ull;
226 value |= 0x1000000000ull;
227 } else if (grp == 1) {
228
229 mask |= 0x800000000ull;
230 value |= 0x100000000ull;
231 }
232 spcsel = (event >> PM_SPCSEL_SH) & PM_SPCSEL_MSK;
233 if (spcsel) {
234 mask |= 3ull << 48;
235 value |= (unsigned long)spcsel << 48;
236 }
237 *maskp = mask;
238 *valp = value;
239 return 0;
240 }
241
242 static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[])
243 {
244 alt[0] = event;
245
246
247 if (event == 0x2002 || event == 0x3002) {
248 alt[1] = event ^ 0x1000;
249 return 2;
250 }
251
252 return 1;
253 }
254
255 static int p970_compute_mmcr(u64 event[], int n_ev,
256 unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
257 {
258 unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
259 unsigned int pmc, unit, byte, psel;
260 unsigned int ttm, grp;
261 unsigned int pmc_inuse = 0;
262 unsigned int pmc_grp_use[2];
263 unsigned char busbyte[4];
264 unsigned char unituse[16];
265 unsigned char unitmap[] = { 0, 0<<3, 3<<3, 1<<3, 2<<3, 0|4, 3|4 };
266 unsigned char ttmuse[2];
267 unsigned char pmcsel[8];
268 int i;
269 int spcsel;
270
271 if (n_ev > 8)
272 return -1;
273
274
275 pmc_grp_use[0] = pmc_grp_use[1] = 0;
276 memset(busbyte, 0, sizeof(busbyte));
277 memset(unituse, 0, sizeof(unituse));
278 for (i = 0; i < n_ev; ++i) {
279 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
280 if (pmc) {
281 if (pmc_inuse & (1 << (pmc - 1)))
282 return -1;
283 pmc_inuse |= 1 << (pmc - 1);
284
285 ++pmc_grp_use[((pmc - 1) >> 1) & 1];
286 }
287 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
288 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
289 if (unit) {
290 if (unit > PM_LASTUNIT)
291 return -1;
292 if (!pmc)
293 ++pmc_grp_use[byte & 1];
294 if (busbyte[byte] && busbyte[byte] != unit)
295 return -1;
296 busbyte[byte] = unit;
297 unituse[unit] = 1;
298 }
299 }
300 if (pmc_grp_use[0] > 4 || pmc_grp_use[1] > 4)
301 return -1;
302
303
304
305
306
307
308
309 if (unituse[PM_ISU] &
310 (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_VPU]))
311 unitmap[PM_ISU] = 2 | 4;
312
313 ttmuse[0] = ttmuse[1] = 0;
314 for (i = PM_FPU; i <= PM_STS; ++i) {
315 if (!unituse[i])
316 continue;
317 ttm = unitmap[i];
318 ++ttmuse[(ttm >> 2) & 1];
319 mmcr1 |= (unsigned long)(ttm & ~4) << MMCR1_TTM1SEL_SH;
320 }
321
322 if (ttmuse[0] > 1 || ttmuse[1] > 1)
323 return -1;
324
325
326 for (byte = 0; byte < 4; ++byte) {
327 unit = busbyte[byte];
328 if (!unit)
329 continue;
330 if (unit <= PM_STS)
331 ttm = (unitmap[unit] >> 2) & 1;
332 else if (unit == PM_LSU0)
333 ttm = 2;
334 else {
335 ttm = 3;
336 if (unit == PM_LSU1L && byte >= 2)
337 mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte);
338 }
339 mmcr1 |= (unsigned long)ttm
340 << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
341 }
342
343
344 memset(pmcsel, 0x8, sizeof(pmcsel));
345 for (i = 0; i < n_ev; ++i) {
346 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
347 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
348 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
349 psel = event[i] & PM_PMCSEL_MSK;
350 if (!pmc) {
351
352 if (unit)
353 psel |= 0x10 | ((byte & 2) << 2);
354 else
355 psel |= 8;
356 for (pmc = 0; pmc < 8; ++pmc) {
357 if (pmc_inuse & (1 << pmc))
358 continue;
359 grp = (pmc >> 1) & 1;
360 if (unit) {
361 if (grp == (byte & 1))
362 break;
363 } else if (pmc_grp_use[grp] < 4) {
364 ++pmc_grp_use[grp];
365 break;
366 }
367 }
368 pmc_inuse |= 1 << pmc;
369 } else {
370
371 --pmc;
372 if (psel == 0 && (byte & 2))
373
374 mmcr1 |= 1ull << mmcr1_adder_bits[pmc];
375 }
376 pmcsel[pmc] = psel;
377 hwc[i] = pmc;
378 spcsel = (event[i] >> PM_SPCSEL_SH) & PM_SPCSEL_MSK;
379 mmcr1 |= spcsel;
380 if (p970_marked_instr_event(event[i]))
381 mmcra |= MMCRA_SAMPLE_ENABLE;
382 }
383 for (pmc = 0; pmc < 2; ++pmc)
384 mmcr0 |= pmcsel[pmc] << (MMCR0_PMC1SEL_SH - 7 * pmc);
385 for (; pmc < 8; ++pmc)
386 mmcr1 |= (unsigned long)pmcsel[pmc]
387 << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2));
388 if (pmc_inuse & 1)
389 mmcr0 |= MMCR0_PMC1CE;
390 if (pmc_inuse & 0xfe)
391 mmcr0 |= MMCR0_PMCjCE;
392
393 mmcra |= 0x2000;
394
395
396 mmcr[0] = mmcr0;
397 mmcr[1] = mmcr1;
398 mmcr[2] = mmcra;
399 return 0;
400 }
401
402 static void p970_disable_pmc(unsigned int pmc, unsigned long mmcr[])
403 {
404 int shift, i;
405
406 if (pmc <= 1) {
407 shift = MMCR0_PMC1SEL_SH - 7 * pmc;
408 i = 0;
409 } else {
410 shift = MMCR1_PMC3SEL_SH - 5 * (pmc - 2);
411 i = 1;
412 }
413
414
415
416 mmcr[i] = (mmcr[i] & ~(0x1fUL << shift)) | (0x08UL << shift);
417 }
418
419 static int ppc970_generic_events[] = {
420 [PERF_COUNT_HW_CPU_CYCLES] = 7,
421 [PERF_COUNT_HW_INSTRUCTIONS] = 1,
422 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x8810,
423 [PERF_COUNT_HW_CACHE_MISSES] = 0x3810,
424 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x431,
425 [PERF_COUNT_HW_BRANCH_MISSES] = 0x327,
426 };
427
428 #define C(x) PERF_COUNT_HW_CACHE_##x
429
430
431
432
433
434
435 static int ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
436 [C(L1D)] = {
437 [C(OP_READ)] = { 0x8810, 0x3810 },
438 [C(OP_WRITE)] = { 0x7810, 0x813 },
439 [C(OP_PREFETCH)] = { 0x731, 0 },
440 },
441 [C(L1I)] = {
442 [C(OP_READ)] = { 0, 0 },
443 [C(OP_WRITE)] = { -1, -1 },
444 [C(OP_PREFETCH)] = { 0, 0 },
445 },
446 [C(LL)] = {
447 [C(OP_READ)] = { 0, 0 },
448 [C(OP_WRITE)] = { 0, 0 },
449 [C(OP_PREFETCH)] = { 0x733, 0 },
450 },
451 [C(DTLB)] = {
452 [C(OP_READ)] = { 0, 0x704 },
453 [C(OP_WRITE)] = { -1, -1 },
454 [C(OP_PREFETCH)] = { -1, -1 },
455 },
456 [C(ITLB)] = {
457 [C(OP_READ)] = { 0, 0x700 },
458 [C(OP_WRITE)] = { -1, -1 },
459 [C(OP_PREFETCH)] = { -1, -1 },
460 },
461 [C(BPU)] = {
462 [C(OP_READ)] = { 0x431, 0x327 },
463 [C(OP_WRITE)] = { -1, -1 },
464 [C(OP_PREFETCH)] = { -1, -1 },
465 },
466 [C(NODE)] = {
467 [C(OP_READ)] = { -1, -1 },
468 [C(OP_WRITE)] = { -1, -1 },
469 [C(OP_PREFETCH)] = { -1, -1 },
470 },
471 };
472
473 static struct power_pmu ppc970_pmu = {
474 .name = "PPC970/FX/MP",
475 .n_counter = 8,
476 .max_alternatives = 2,
477 .add_fields = 0x001100005555ull,
478 .test_adder = 0x013300000000ull,
479 .compute_mmcr = p970_compute_mmcr,
480 .get_constraint = p970_get_constraint,
481 .get_alternatives = p970_get_alternatives,
482 .disable_pmc = p970_disable_pmc,
483 .n_generic = ARRAY_SIZE(ppc970_generic_events),
484 .generic_events = ppc970_generic_events,
485 .cache_events = &ppc970_cache_events,
486 .flags = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
487 };
488
489 int init_ppc970_pmu(void)
490 {
491 if (!cur_cpu_spec->oprofile_cpu_type ||
492 (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970")
493 && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970MP")))
494 return -ENODEV;
495
496 return register_power_pmu(&ppc970_pmu);
497 }