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