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