11 #include <linux/kernel.h>
12 #include <linux/perf_event.h>
13 #include <linux/string.h>
15 #include <asm/cputable.h>
21 #define PM_PMC_MSK 0xf
23 #define PM_UNIT_MSK 0xf
25 #define PM_LOWER_MSK 1
26 #define PM_LOWER_MSKS 0x40
29 #define PM_PMCSEL_MSK 7
48 #define MMCR0_PMC1SEL_SH 8
49 #define MMCR0_PMC2SEL_SH 1
50 #define MMCR_PMCSEL_MSK 0x1f
55 #define MMCR1_TTM0SEL_SH 62
56 #define MMCR1_TTC0SEL_SH 61
57 #define MMCR1_TTM1SEL_SH 59
58 #define MMCR1_TTC1SEL_SH 58
59 #define MMCR1_TTM2SEL_SH 56
60 #define MMCR1_TTC2SEL_SH 55
61 #define MMCR1_TTM3SEL_SH 53
62 #define MMCR1_TTC3SEL_SH 52
63 #define MMCR1_TTMSEL_MSK 3
64 #define MMCR1_TD_CP_DBG0SEL_SH 50
65 #define MMCR1_TD_CP_DBG1SEL_SH 48
66 #define MMCR1_TD_CP_DBG2SEL_SH 46
67 #define MMCR1_TD_CP_DBG3SEL_SH 44
68 #define MMCR1_DEBUG0SEL_SH 43
69 #define MMCR1_DEBUG1SEL_SH 42
70 #define MMCR1_DEBUG2SEL_SH 41
71 #define MMCR1_DEBUG3SEL_SH 40
72 #define MMCR1_PMC1_ADDER_SEL_SH 39
73 #define MMCR1_PMC2_ADDER_SEL_SH 38
74 #define MMCR1_PMC6_ADDER_SEL_SH 37
75 #define MMCR1_PMC5_ADDER_SEL_SH 36
76 #define MMCR1_PMC8_ADDER_SEL_SH 35
77 #define MMCR1_PMC7_ADDER_SEL_SH 34
78 #define MMCR1_PMC3_ADDER_SEL_SH 33
79 #define MMCR1_PMC4_ADDER_SEL_SH 32
80 #define MMCR1_PMC3SEL_SH 27
81 #define MMCR1_PMC4SEL_SH 22
82 #define MMCR1_PMC5SEL_SH 17
83 #define MMCR1_PMC6SEL_SH 12
84 #define MMCR1_PMC7SEL_SH 7
85 #define MMCR1_PMC8SEL_SH 2
87 static short mmcr1_adder_bits[8] = {
101 #define MMCRA_PMC8SEL0_SH 17
183 static struct unitinfo {
187 } p4_unitinfo[16] = {
188 [
PM_FPU] = { 0x44000000000000ul, 0x88000000000000ul,
PM_FPU, 0 },
189 [
PM_ISU1] = { 0x20080000000000ul, 0x88000000000000ul,
PM_ISU1, 0 },
191 { 0x20080000000000ul, 0x88000000000000ul,
PM_ISU1, 0 },
192 [
PM_IFU] = { 0x02200000000000ul, 0x08820000000000ul,
PM_IFU, 41 },
194 { 0x02200000000000ul, 0x08820000000000ul,
PM_IFU, 41 },
195 [
PM_IDU0] = { 0x10100000000000ul, 0x80840000000000ul,
PM_IDU0, 1 },
196 [
PM_ISU2] = { 0x10140000000000ul, 0x80840000000000ul,
PM_ISU2, 0 },
197 [
PM_LSU0] = { 0x01400000000000ul, 0x08800000000000ul,
PM_LSU0, 0 },
198 [
PM_LSU1] = { 0x00000000000000ul, 0x00010000000000ul,
PM_LSU1, 40 },
199 [
PM_GPS] = { 0x00000000000000ul, 0x00000000000000ul,
PM_GPS, 0 }
202 static unsigned char direct_marked_event[8] = {
208 (1<<3) | (1<<4) | (1<<5),
218 static int p4_marked_instr_event(
u64 event)
226 if (direct_marked_event[pmc - 1] & (1 << psel))
229 bit = (pmc <= 4)? pmc - 1: 8 - pmc;
251 return (mask >> (byte * 8 + bit)) & 1;
254 static int p4_get_constraint(
u64 event,
unsigned long *maskp,
258 unsigned long mask = 0,
value = 0;
268 grp = ((pmc - 1) >> 1) & 1;
282 if (!p4_unitinfo[unit].unit)
284 mask |= p4_unitinfo[
unit].mask;
286 sh = p4_unitinfo[
unit].lowerbit;
289 else if (lower != sh)
291 unit = p4_unitinfo[
unit].unit;
294 mask |= 0xfULL << (28 - 4 *
byte);
295 value |= (
unsigned long)unit << (28 - 4 * byte);
299 mask |= 0x8000000000ull;
300 value |= 0x1000000000ull;
303 mask |= 0x800000000ull;
304 value |= 0x100000000ull;
308 if (p4_marked_instr_event(event)) {
322 static unsigned int ppc_inst_cmpl[] = {
323 0x1001, 0x4001, 0x6001, 0x7001, 0x8001
326 static int p4_get_alternatives(
u64 event,
unsigned int flags,
u64 alt[])
334 if (event == 0x8003 || event == 0x0224) {
335 alt[1] =
event ^ (0x8003 ^ 0x0224);
340 if (event == 0x0c13 || event == 0x0c23) {
341 alt[1] =
event ^ (0x0c13 ^ 0x0c23);
347 if (event == ppc_inst_cmpl[i]) {
350 alt[na++] = ppc_inst_cmpl[
j];
358 static int p4_compute_mmcr(
u64 event[],
int n_ev,
359 unsigned int hwc[],
unsigned long mmcr[])
361 unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
362 unsigned int pmc,
unit,
byte, psel, lower;
363 unsigned int ttm, grp;
364 unsigned int pmc_inuse = 0;
365 unsigned int pmc_grp_use[2];
366 unsigned char busbyte[4];
367 unsigned char unituse[16];
368 unsigned int unitlower = 0;
375 pmc_grp_use[0] = pmc_grp_use[1] = 0;
376 memset(busbyte, 0,
sizeof(busbyte));
377 memset(unituse, 0,
sizeof(unituse));
378 for (i = 0; i < n_ev; ++
i) {
381 if (pmc_inuse & (1 << (pmc - 1)))
383 pmc_inuse |= 1 << (pmc - 1);
385 ++pmc_grp_use[((pmc - 1) >> 1) & 1];
392 ++pmc_grp_use[byte & 1];
393 if (unit == 6 || unit == 8)
395 unit = (unit >> 1) - 1;
396 if (busbyte[byte] && busbyte[byte] != unit)
400 if (unituse[unit] && lower != (unitlower & lower))
406 if (pmc_grp_use[0] > 4 || pmc_grp_use[1] > 4)
417 if (unituse[2] & (unituse[1] | (unituse[3] & unituse[9]))) {
421 if (unituse[3] & (unituse[1] | unituse[2])) {
424 unitlower = (unitlower & ~8) | ((unitlower & 8) << 5);
427 if (unituse[1] + unituse[2] + unituse[3] > 1 ||
428 unituse[4] + unituse[6] + unituse[7] > 1 ||
429 unituse[8] + unituse[9] > 1 ||
430 (unituse[5] | unituse[10] | unituse[11] |
431 unituse[13] | unituse[14]))
435 mmcr1 |= (
unsigned long)(unituse[3] * 2 + unituse[2])
437 mmcr1 |= (
unsigned long)(unituse[7] * 3 + unituse[6] * 2)
444 if (unitlower & 0xf0)
446 if (unitlower & 0xf00)
448 if (unitlower & 0x7000)
452 for (byte = 0; byte < 4; ++
byte) {
453 unit = busbyte[
byte];
464 mmcr1 |= (
unsigned long)ttm
470 for (i = 0; i < n_ev; ++
i) {
478 psel |= 0x10 | ((byte & 2) << 2);
479 for (pmc = 0; pmc < 8; ++pmc) {
480 if (pmc_inuse & (1 << pmc))
482 grp = (pmc >> 1) & 1;
484 if (grp == (byte & 1))
486 }
else if (pmc_grp_use[grp] < 4) {
491 pmc_inuse |= 1 << pmc;
495 if (psel == 0 && (byte & 2))
497 mmcr1 |= 1ull << mmcr1_adder_bits[pmc];
498 else if (psel == 6 && byte == 3)
500 mmcra |= MMCRA_SAMPLE_ENABLE;
510 if (p4_marked_instr_event(event[i]))
511 mmcra |= MMCRA_SAMPLE_ENABLE;
515 mmcr0 |= MMCR0_PMC1CE;
516 if (pmc_inuse & 0xfe)
517 mmcr0 |= MMCR0_PMCjCE;
528 static void p4_disable_pmc(
unsigned int pmc,
unsigned long mmcr[])
543 static int p4_generic_events[] = {
552 #define C(x) PERF_COUNT_HW_CACHE_##x
559 static int power4_cache_events[
C(
MAX)][
C(
OP_MAX)][
C(RESULT_MAX)] = {
563 [
C(OP_PREFETCH)] = { 0xc35, 0 },
568 [
C(OP_PREFETCH)] = { 0, 0 },
573 [
C(OP_PREFETCH)] = { 0xc34, 0 },
578 [
C(OP_PREFETCH)] = { -1, -1 },
583 [
C(OP_PREFETCH)] = { -1, -1 },
588 [
C(OP_PREFETCH)] = { -1, -1 },
593 [
C(OP_PREFETCH)] = { -1, -1 },
600 .max_alternatives = 5,
601 .add_fields = 0x0000001100005555ul,
602 .test_adder = 0x0011083300000000ul,
603 .compute_mmcr = p4_compute_mmcr,
604 .get_constraint = p4_get_constraint,
605 .get_alternatives = p4_get_alternatives,
606 .disable_pmc = p4_disable_pmc,
608 .generic_events = p4_generic_events,
609 .cache_events = &power4_cache_events,
613 static int __init init_power4_pmu(
void)