This source file includes following definitions.
- power5_get_constraint
- find_alternative
- find_alternative_bdecode
- power5_get_alternatives
- power5_marked_instr_event
- power5_compute_mmcr
- power5_disable_pmc
- init_power5_pmu
1
2
3
4
5
6
7 #include <linux/kernel.h>
8 #include <linux/perf_event.h>
9 #include <linux/string.h>
10 #include <asm/reg.h>
11 #include <asm/cputable.h>
12
13
14
15
16 #define PM_PMC_SH 20
17 #define PM_PMC_MSK 0xf
18 #define PM_PMC_MSKS (PM_PMC_MSK << PM_PMC_SH)
19 #define PM_UNIT_SH 16
20 #define PM_UNIT_MSK 0xf
21 #define PM_BYTE_SH 12
22 #define PM_BYTE_MSK 7
23 #define PM_GRS_SH 8
24 #define PM_GRS_MSK 7
25 #define PM_BUSEVENT_MSK 0x80
26 #define PM_PMCSEL_MSK 0x7f
27
28
29 #define PM_FPU 0
30 #define PM_ISU0 1
31 #define PM_IFU 2
32 #define PM_ISU1 3
33 #define PM_IDU 4
34 #define PM_ISU0_ALT 6
35 #define PM_GRS 7
36 #define PM_LSU0 8
37 #define PM_LSU1 0xc
38 #define PM_LASTUNIT 0xc
39
40
41
42
43 #define MMCR1_TTM0SEL_SH 62
44 #define MMCR1_TTM1SEL_SH 60
45 #define MMCR1_TTM2SEL_SH 58
46 #define MMCR1_TTM3SEL_SH 56
47 #define MMCR1_TTMSEL_MSK 3
48 #define MMCR1_TD_CP_DBG0SEL_SH 54
49 #define MMCR1_TD_CP_DBG1SEL_SH 52
50 #define MMCR1_TD_CP_DBG2SEL_SH 50
51 #define MMCR1_TD_CP_DBG3SEL_SH 48
52 #define MMCR1_GRS_L2SEL_SH 46
53 #define MMCR1_GRS_L2SEL_MSK 3
54 #define MMCR1_GRS_L3SEL_SH 44
55 #define MMCR1_GRS_L3SEL_MSK 3
56 #define MMCR1_GRS_MCSEL_SH 41
57 #define MMCR1_GRS_MCSEL_MSK 7
58 #define MMCR1_GRS_FABSEL_SH 39
59 #define MMCR1_GRS_FABSEL_MSK 3
60 #define MMCR1_PMC1_ADDER_SEL_SH 35
61 #define MMCR1_PMC2_ADDER_SEL_SH 34
62 #define MMCR1_PMC3_ADDER_SEL_SH 33
63 #define MMCR1_PMC4_ADDER_SEL_SH 32
64 #define MMCR1_PMC1SEL_SH 25
65 #define MMCR1_PMC2SEL_SH 17
66 #define MMCR1_PMC3SEL_SH 9
67 #define MMCR1_PMC4SEL_SH 1
68 #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8)
69 #define MMCR1_PMCSEL_MSK 0x7f
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 static const int grsel_shift[8] = {
121 MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH,
122 MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH,
123 MMCR1_GRS_MCSEL_SH, MMCR1_GRS_FABSEL_SH
124 };
125
126
127 static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
128 [PM_FPU] = { 0xc0002000000000ul, 0x00001000000000ul },
129 [PM_ISU0] = { 0x00002000000000ul, 0x00000800000000ul },
130 [PM_ISU1] = { 0xc0002000000000ul, 0xc0001000000000ul },
131 [PM_IFU] = { 0xc0002000000000ul, 0x80001000000000ul },
132 [PM_IDU] = { 0x30002000000000ul, 0x00000400000000ul },
133 [PM_GRS] = { 0x30002000000000ul, 0x30000400000000ul },
134 };
135
136 static int power5_get_constraint(u64 event, unsigned long *maskp,
137 unsigned long *valp)
138 {
139 int pmc, byte, unit, sh;
140 int bit, fmask;
141 unsigned long mask = 0, value = 0;
142 int grp = -1;
143
144 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
145 if (pmc) {
146 if (pmc > 6)
147 return -1;
148 sh = (pmc - 1) * 2;
149 mask |= 2 << sh;
150 value |= 1 << sh;
151 if (pmc <= 4)
152 grp = (pmc - 1) >> 1;
153 else if (event != 0x500009 && event != 0x600005)
154 return -1;
155 }
156 if (event & PM_BUSEVENT_MSK) {
157 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
158 if (unit > PM_LASTUNIT)
159 return -1;
160 if (unit == PM_ISU0_ALT)
161 unit = PM_ISU0;
162 mask |= unit_cons[unit][0];
163 value |= unit_cons[unit][1];
164 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
165 if (byte >= 4) {
166 if (unit != PM_LSU1)
167 return -1;
168
169 ++unit;
170 byte &= 3;
171 }
172 if (unit == PM_GRS) {
173 bit = event & 7;
174 fmask = (bit == 6)? 7: 3;
175 sh = grsel_shift[bit];
176 mask |= (unsigned long)fmask << sh;
177 value |= (unsigned long)((event >> PM_GRS_SH) & fmask)
178 << sh;
179 }
180
181
182
183
184 if (!pmc)
185 grp = byte & 1;
186
187 mask |= 0xfUL << (24 - 4 * byte);
188 value |= (unsigned long)unit << (24 - 4 * byte);
189 }
190 if (grp == 0) {
191
192 mask |= 0x200000000ul;
193 value |= 0x080000000ul;
194 } else if (grp == 1) {
195
196 mask |= 0x40000000ul;
197 value |= 0x10000000ul;
198 }
199 if (pmc < 5) {
200
201 mask |= 0x8000000000000ul;
202 value |= 0x1000000000000ul;
203 }
204 *maskp = mask;
205 *valp = value;
206 return 0;
207 }
208
209 #define MAX_ALT 3
210
211 static const unsigned int event_alternatives[][MAX_ALT] = {
212 { 0x120e4, 0x400002 },
213 { 0x410c7, 0x441084 },
214 { 0x100005, 0x600005 },
215 { 0x100009, 0x200009, 0x500009 },
216 { 0x300009, 0x400009 },
217 };
218
219
220
221
222
223 static int find_alternative(u64 event)
224 {
225 int i, j;
226
227 for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
228 if (event < event_alternatives[i][0])
229 break;
230 for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
231 if (event == event_alternatives[i][j])
232 return i;
233 }
234 return -1;
235 }
236
237 static const unsigned char bytedecode_alternatives[4][4] = {
238 { 0x21, 0x23, 0x25, 0x27 },
239 { 0x07, 0x17, 0x0e, 0x1e },
240 { 0x20, 0x22, 0x24, 0x26 },
241 { 0x07, 0x17, 0x0e, 0x1e }
242 };
243
244
245
246
247
248
249 static s64 find_alternative_bdecode(u64 event)
250 {
251 int pmc, altpmc, pp, j;
252
253 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
254 if (pmc == 0 || pmc > 4)
255 return -1;
256 altpmc = 5 - pmc;
257 pp = event & PM_PMCSEL_MSK;
258 for (j = 0; j < 4; ++j) {
259 if (bytedecode_alternatives[pmc - 1][j] == pp) {
260 return (event & ~(PM_PMC_MSKS | PM_PMCSEL_MSK)) |
261 (altpmc << PM_PMC_SH) |
262 bytedecode_alternatives[altpmc - 1][j];
263 }
264 }
265 return -1;
266 }
267
268 static int power5_get_alternatives(u64 event, unsigned int flags, u64 alt[])
269 {
270 int i, j, nalt = 1;
271 s64 ae;
272
273 alt[0] = event;
274 nalt = 1;
275 i = find_alternative(event);
276 if (i >= 0) {
277 for (j = 0; j < MAX_ALT; ++j) {
278 ae = event_alternatives[i][j];
279 if (ae && ae != event)
280 alt[nalt++] = ae;
281 }
282 } else {
283 ae = find_alternative_bdecode(event);
284 if (ae > 0)
285 alt[nalt++] = ae;
286 }
287 return nalt;
288 }
289
290
291
292
293
294
295
296 static unsigned char direct_event_is_marked[0x28] = {
297 0,
298 0x1f,
299 0x2,
300 0xe,
301 0,
302 0x1c,
303 0x80,
304 0x80,
305 0, 0, 0,
306 0x18,
307 0,
308 0x80,
309 0x80,
310 0,
311 0,
312 0x14,
313 0,
314 0x10,
315 0x1f,
316 0x2,
317 0x80,
318 0x80,
319 0, 0, 0, 0, 0,
320 0x80,
321 0x80,
322 0,
323 0x80,
324 0x80,
325 0x80,
326 0x80,
327 0x80,
328 0x80,
329 0x80,
330 0x80,
331 };
332
333
334
335
336
337 static int power5_marked_instr_event(u64 event)
338 {
339 int pmc, psel;
340 int bit, byte, unit;
341 u32 mask;
342
343 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
344 psel = event & PM_PMCSEL_MSK;
345 if (pmc >= 5)
346 return 0;
347
348 bit = -1;
349 if (psel < sizeof(direct_event_is_marked)) {
350 if (direct_event_is_marked[psel] & (1 << pmc))
351 return 1;
352 if (direct_event_is_marked[psel] & 0x80)
353 bit = 4;
354 else if (psel == 0x08)
355 bit = pmc - 1;
356 else if (psel == 0x10)
357 bit = 4 - pmc;
358 else if (psel == 0x1b && (pmc == 1 || pmc == 3))
359 bit = 4;
360 } else if ((psel & 0x58) == 0x40)
361 bit = psel & 7;
362
363 if (!(event & PM_BUSEVENT_MSK))
364 return 0;
365
366 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
367 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
368 if (unit == PM_LSU0) {
369
370 mask = 0x5dff00;
371 } else if (unit == PM_LSU1 && byte >= 4) {
372 byte -= 4;
373
374 mask = 0x5f00c0aa;
375 } else
376 return 0;
377
378 return (mask >> (byte * 8 + bit)) & 1;
379 }
380
381 static int power5_compute_mmcr(u64 event[], int n_ev,
382 unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
383 {
384 unsigned long mmcr1 = 0;
385 unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
386 unsigned int pmc, unit, byte, psel;
387 unsigned int ttm, grp;
388 int i, isbus, bit, grsel;
389 unsigned int pmc_inuse = 0;
390 unsigned int pmc_grp_use[2];
391 unsigned char busbyte[4];
392 unsigned char unituse[16];
393 int ttmuse;
394
395 if (n_ev > 6)
396 return -1;
397
398
399 pmc_grp_use[0] = pmc_grp_use[1] = 0;
400 memset(busbyte, 0, sizeof(busbyte));
401 memset(unituse, 0, sizeof(unituse));
402 for (i = 0; i < n_ev; ++i) {
403 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
404 if (pmc) {
405 if (pmc > 6)
406 return -1;
407 if (pmc_inuse & (1 << (pmc - 1)))
408 return -1;
409 pmc_inuse |= 1 << (pmc - 1);
410
411 if (pmc <= 4)
412 ++pmc_grp_use[(pmc - 1) >> 1];
413 }
414 if (event[i] & PM_BUSEVENT_MSK) {
415 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
416 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
417 if (unit > PM_LASTUNIT)
418 return -1;
419 if (unit == PM_ISU0_ALT)
420 unit = PM_ISU0;
421 if (byte >= 4) {
422 if (unit != PM_LSU1)
423 return -1;
424 ++unit;
425 byte &= 3;
426 }
427 if (!pmc)
428 ++pmc_grp_use[byte & 1];
429 if (busbyte[byte] && busbyte[byte] != unit)
430 return -1;
431 busbyte[byte] = unit;
432 unituse[unit] = 1;
433 }
434 }
435 if (pmc_grp_use[0] > 2 || pmc_grp_use[1] > 2)
436 return -1;
437
438
439
440
441
442
443
444 if (unituse[PM_ISU0] &
445 (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_ISU1])) {
446 unituse[PM_ISU0_ALT] = 1;
447 unituse[PM_ISU0] = 0;
448 }
449
450 ttmuse = 0;
451 for (i = PM_FPU; i <= PM_ISU1; ++i) {
452 if (!unituse[i])
453 continue;
454 if (ttmuse++)
455 return -1;
456 mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH;
457 }
458 ttmuse = 0;
459 for (; i <= PM_GRS; ++i) {
460 if (!unituse[i])
461 continue;
462 if (ttmuse++)
463 return -1;
464 mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH;
465 }
466 if (ttmuse > 1)
467 return -1;
468
469
470 for (byte = 0; byte < 4; ++byte) {
471 unit = busbyte[byte];
472 if (!unit)
473 continue;
474 if (unit == PM_ISU0 && unituse[PM_ISU0_ALT]) {
475
476 unit = PM_ISU0_ALT;
477 } else if (unit == PM_LSU1 + 1) {
478
479 mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte);
480 }
481 ttm = unit >> 2;
482 mmcr1 |= (unsigned long)ttm
483 << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
484 }
485
486
487 for (i = 0; i < n_ev; ++i) {
488 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
489 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
490 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
491 psel = event[i] & PM_PMCSEL_MSK;
492 isbus = event[i] & PM_BUSEVENT_MSK;
493 if (!pmc) {
494
495 for (pmc = 0; pmc < 4; ++pmc) {
496 if (pmc_inuse & (1 << pmc))
497 continue;
498 grp = (pmc >> 1) & 1;
499 if (isbus) {
500 if (grp == (byte & 1))
501 break;
502 } else if (pmc_grp_use[grp] < 2) {
503 ++pmc_grp_use[grp];
504 break;
505 }
506 }
507 pmc_inuse |= 1 << pmc;
508 } else if (pmc <= 4) {
509
510 --pmc;
511 if ((psel == 8 || psel == 0x10) && isbus && (byte & 2))
512
513 mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
514 } else {
515
516 --pmc;
517 }
518 if (isbus && unit == PM_GRS) {
519 bit = psel & 7;
520 grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK;
521 mmcr1 |= (unsigned long)grsel << grsel_shift[bit];
522 }
523 if (power5_marked_instr_event(event[i]))
524 mmcra |= MMCRA_SAMPLE_ENABLE;
525 if (pmc <= 3)
526 mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc);
527 hwc[i] = pmc;
528 }
529
530
531 mmcr[0] = 0;
532 if (pmc_inuse & 1)
533 mmcr[0] = MMCR0_PMC1CE;
534 if (pmc_inuse & 0x3e)
535 mmcr[0] |= MMCR0_PMCjCE;
536 mmcr[1] = mmcr1;
537 mmcr[2] = mmcra;
538 return 0;
539 }
540
541 static void power5_disable_pmc(unsigned int pmc, unsigned long mmcr[])
542 {
543 if (pmc <= 3)
544 mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc));
545 }
546
547 static int power5_generic_events[] = {
548 [PERF_COUNT_HW_CPU_CYCLES] = 0xf,
549 [PERF_COUNT_HW_INSTRUCTIONS] = 0x100009,
550 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x4c1090,
551 [PERF_COUNT_HW_CACHE_MISSES] = 0x3c1088,
552 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x230e4,
553 [PERF_COUNT_HW_BRANCH_MISSES] = 0x230e5,
554 };
555
556 #define C(x) PERF_COUNT_HW_CACHE_##x
557
558
559
560
561
562
563 static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
564 [C(L1D)] = {
565 [C(OP_READ)] = { 0x4c1090, 0x3c1088 },
566 [C(OP_WRITE)] = { 0x3c1090, 0xc10c3 },
567 [C(OP_PREFETCH)] = { 0xc70e7, 0 },
568 },
569 [C(L1I)] = {
570 [C(OP_READ)] = { 0, 0 },
571 [C(OP_WRITE)] = { -1, -1 },
572 [C(OP_PREFETCH)] = { 0, 0 },
573 },
574 [C(LL)] = {
575 [C(OP_READ)] = { 0, 0x3c309b },
576 [C(OP_WRITE)] = { 0, 0 },
577 [C(OP_PREFETCH)] = { 0xc50c3, 0 },
578 },
579 [C(DTLB)] = {
580 [C(OP_READ)] = { 0x2c4090, 0x800c4 },
581 [C(OP_WRITE)] = { -1, -1 },
582 [C(OP_PREFETCH)] = { -1, -1 },
583 },
584 [C(ITLB)] = {
585 [C(OP_READ)] = { 0, 0x800c0 },
586 [C(OP_WRITE)] = { -1, -1 },
587 [C(OP_PREFETCH)] = { -1, -1 },
588 },
589 [C(BPU)] = {
590 [C(OP_READ)] = { 0x230e4, 0x230e5 },
591 [C(OP_WRITE)] = { -1, -1 },
592 [C(OP_PREFETCH)] = { -1, -1 },
593 },
594 [C(NODE)] = {
595 [C(OP_READ)] = { -1, -1 },
596 [C(OP_WRITE)] = { -1, -1 },
597 [C(OP_PREFETCH)] = { -1, -1 },
598 },
599 };
600
601 static struct power_pmu power5_pmu = {
602 .name = "POWER5",
603 .n_counter = 6,
604 .max_alternatives = MAX_ALT,
605 .add_fields = 0x7000090000555ul,
606 .test_adder = 0x3000490000000ul,
607 .compute_mmcr = power5_compute_mmcr,
608 .get_constraint = power5_get_constraint,
609 .get_alternatives = power5_get_alternatives,
610 .disable_pmc = power5_disable_pmc,
611 .n_generic = ARRAY_SIZE(power5_generic_events),
612 .generic_events = power5_generic_events,
613 .cache_events = &power5_cache_events,
614 .flags = PPMU_HAS_SSLOT,
615 };
616
617 int init_power5_pmu(void)
618 {
619 if (!cur_cpu_spec->oprofile_cpu_type ||
620 strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
621 return -ENODEV;
622
623 return register_power_pmu(&power5_pmu);
624 }