0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/perf_event.h>
0009 #include <linux/string.h>
0010 #include <asm/reg.h>
0011 #include <asm/cputable.h>
0012
0013 #include "internal.h"
0014
0015
0016
0017
0018 #define PM_PMC_SH 20
0019 #define PM_PMC_MSK 0xf
0020 #define PM_PMC_MSKS (PM_PMC_MSK << PM_PMC_SH)
0021 #define PM_UNIT_SH 16
0022 #define PM_UNIT_MSK 0xf
0023 #define PM_BYTE_SH 12
0024 #define PM_BYTE_MSK 7
0025 #define PM_GRS_SH 8
0026 #define PM_GRS_MSK 7
0027 #define PM_BUSEVENT_MSK 0x80
0028 #define PM_PMCSEL_MSK 0x7f
0029
0030
0031 #define PM_FPU 0
0032 #define PM_ISU0 1
0033 #define PM_IFU 2
0034 #define PM_ISU1 3
0035 #define PM_IDU 4
0036 #define PM_ISU0_ALT 6
0037 #define PM_GRS 7
0038 #define PM_LSU0 8
0039 #define PM_LSU1 0xc
0040 #define PM_LASTUNIT 0xc
0041
0042
0043
0044
0045 #define MMCR1_TTM0SEL_SH 62
0046 #define MMCR1_TTM1SEL_SH 60
0047 #define MMCR1_TTM2SEL_SH 58
0048 #define MMCR1_TTM3SEL_SH 56
0049 #define MMCR1_TTMSEL_MSK 3
0050 #define MMCR1_TD_CP_DBG0SEL_SH 54
0051 #define MMCR1_TD_CP_DBG1SEL_SH 52
0052 #define MMCR1_TD_CP_DBG2SEL_SH 50
0053 #define MMCR1_TD_CP_DBG3SEL_SH 48
0054 #define MMCR1_GRS_L2SEL_SH 46
0055 #define MMCR1_GRS_L2SEL_MSK 3
0056 #define MMCR1_GRS_L3SEL_SH 44
0057 #define MMCR1_GRS_L3SEL_MSK 3
0058 #define MMCR1_GRS_MCSEL_SH 41
0059 #define MMCR1_GRS_MCSEL_MSK 7
0060 #define MMCR1_GRS_FABSEL_SH 39
0061 #define MMCR1_GRS_FABSEL_MSK 3
0062 #define MMCR1_PMC1_ADDER_SEL_SH 35
0063 #define MMCR1_PMC2_ADDER_SEL_SH 34
0064 #define MMCR1_PMC3_ADDER_SEL_SH 33
0065 #define MMCR1_PMC4_ADDER_SEL_SH 32
0066 #define MMCR1_PMC1SEL_SH 25
0067 #define MMCR1_PMC2SEL_SH 17
0068 #define MMCR1_PMC3SEL_SH 9
0069 #define MMCR1_PMC4SEL_SH 1
0070 #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8)
0071 #define MMCR1_PMCSEL_MSK 0x7f
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 static const int grsel_shift[8] = {
0119 MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH,
0120 MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH,
0121 MMCR1_GRS_MCSEL_SH, MMCR1_GRS_FABSEL_SH
0122 };
0123
0124
0125 static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
0126 [PM_FPU] = { 0x3200000000ul, 0x0100000000ul },
0127 [PM_ISU0] = { 0x0200000000ul, 0x0080000000ul },
0128 [PM_ISU1] = { 0x3200000000ul, 0x3100000000ul },
0129 [PM_IFU] = { 0x3200000000ul, 0x2100000000ul },
0130 [PM_IDU] = { 0x0e00000000ul, 0x0040000000ul },
0131 [PM_GRS] = { 0x0e00000000ul, 0x0c40000000ul },
0132 };
0133
0134 static int power5p_get_constraint(u64 event, unsigned long *maskp,
0135 unsigned long *valp, u64 event_config1 __maybe_unused)
0136 {
0137 int pmc, byte, unit, sh;
0138 int bit, fmask;
0139 unsigned long mask = 0, value = 0;
0140
0141 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0142 if (pmc) {
0143 if (pmc > 6)
0144 return -1;
0145 sh = (pmc - 1) * 2;
0146 mask |= 2 << sh;
0147 value |= 1 << sh;
0148 if (pmc >= 5 && !(event == 0x500009 || event == 0x600005))
0149 return -1;
0150 }
0151 if (event & PM_BUSEVENT_MSK) {
0152 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
0153 if (unit > PM_LASTUNIT)
0154 return -1;
0155 if (unit == PM_ISU0_ALT)
0156 unit = PM_ISU0;
0157 mask |= unit_cons[unit][0];
0158 value |= unit_cons[unit][1];
0159 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
0160 if (byte >= 4) {
0161 if (unit != PM_LSU1)
0162 return -1;
0163
0164 ++unit;
0165 byte &= 3;
0166 }
0167 if (unit == PM_GRS) {
0168 bit = event & 7;
0169 fmask = (bit == 6)? 7: 3;
0170 sh = grsel_shift[bit];
0171 mask |= (unsigned long)fmask << sh;
0172 value |= (unsigned long)((event >> PM_GRS_SH) & fmask)
0173 << sh;
0174 }
0175
0176 mask |= 0xfUL << (24 - 4 * byte);
0177 value |= (unsigned long)unit << (24 - 4 * byte);
0178 }
0179 if (pmc < 5) {
0180
0181 mask |= 0x8000000000000ul;
0182 value |= 0x1000000000000ul;
0183 }
0184 *maskp = mask;
0185 *valp = value;
0186 return 0;
0187 }
0188
0189 static int power5p_limited_pmc_event(u64 event)
0190 {
0191 int pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0192
0193 return pmc == 5 || pmc == 6;
0194 }
0195
0196 #define MAX_ALT 3
0197
0198 static const unsigned int event_alternatives[][MAX_ALT] = {
0199 { 0x100c0, 0x40001f },
0200 { 0x120e4, 0x400002 },
0201 { 0x230e2, 0x323087 },
0202 { 0x230e3, 0x223087, 0x3230a0 },
0203 { 0x410c7, 0x441084 },
0204 { 0x800c4, 0xc20e0 },
0205 { 0xc50c6, 0xc60e0 },
0206 { 0x100005, 0x600005 },
0207 { 0x100009, 0x200009 },
0208 { 0x200015, 0x300015 },
0209 { 0x300009, 0x400009 },
0210 };
0211
0212
0213
0214
0215
0216 static int find_alternative(unsigned int event)
0217 {
0218 int i, j;
0219
0220 for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
0221 if (event < event_alternatives[i][0])
0222 break;
0223 for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
0224 if (event == event_alternatives[i][j])
0225 return i;
0226 }
0227 return -1;
0228 }
0229
0230 static const unsigned char bytedecode_alternatives[4][4] = {
0231 { 0x21, 0x23, 0x25, 0x27 },
0232 { 0x07, 0x17, 0x0e, 0x1e },
0233 { 0x20, 0x22, 0x24, 0x26 },
0234 { 0x07, 0x17, 0x0e, 0x1e }
0235 };
0236
0237
0238
0239
0240
0241
0242
0243 static s64 find_alternative_bdecode(u64 event)
0244 {
0245 int pmc, altpmc, pp, j;
0246
0247 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0248 if (pmc == 0 || pmc > 4)
0249 return -1;
0250 altpmc = 5 - pmc;
0251 pp = event & PM_PMCSEL_MSK;
0252 for (j = 0; j < 4; ++j) {
0253 if (bytedecode_alternatives[pmc - 1][j] == pp) {
0254 return (event & ~(PM_PMC_MSKS | PM_PMCSEL_MSK)) |
0255 (altpmc << PM_PMC_SH) |
0256 bytedecode_alternatives[altpmc - 1][j];
0257 }
0258 }
0259
0260
0261 if (pmc == 1 && (pp == 0x0d || pp == 0x0e))
0262 return event + (2 << PM_PMC_SH) + (0x2e - 0x0d);
0263 if (pmc == 3 && (pp == 0x2e || pp == 0x2f))
0264 return event - (2 << PM_PMC_SH) - (0x2e - 0x0d);
0265
0266
0267 if (pp == 0x10 || pp == 0x28)
0268 return ((event ^ (0x10 ^ 0x28)) & ~PM_PMC_MSKS) |
0269 (altpmc << PM_PMC_SH);
0270
0271 return -1;
0272 }
0273
0274 static int power5p_get_alternatives(u64 event, unsigned int flags, u64 alt[])
0275 {
0276 int i, j, nalt = 1;
0277 int nlim;
0278 s64 ae;
0279
0280 alt[0] = event;
0281 nalt = 1;
0282 nlim = power5p_limited_pmc_event(event);
0283 i = find_alternative(event);
0284 if (i >= 0) {
0285 for (j = 0; j < MAX_ALT; ++j) {
0286 ae = event_alternatives[i][j];
0287 if (ae && ae != event)
0288 alt[nalt++] = ae;
0289 nlim += power5p_limited_pmc_event(ae);
0290 }
0291 } else {
0292 ae = find_alternative_bdecode(event);
0293 if (ae > 0)
0294 alt[nalt++] = ae;
0295 }
0296
0297 if (flags & PPMU_ONLY_COUNT_RUN) {
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308 j = nalt;
0309 for (i = 0; i < nalt; ++i) {
0310 switch (alt[i]) {
0311 case 0xf:
0312 alt[j++] = 0x600005;
0313 ++nlim;
0314 break;
0315 case 0x600005:
0316 alt[j++] = 0xf;
0317 break;
0318 case 0x100009:
0319 alt[j++] = 0x500009;
0320 ++nlim;
0321 break;
0322 case 0x500009:
0323 alt[j++] = 0x100009;
0324 alt[j++] = 0x200009;
0325 break;
0326 }
0327 }
0328 nalt = j;
0329 }
0330
0331 if (!(flags & PPMU_LIMITED_PMC_OK) && nlim) {
0332
0333 j = 0;
0334 for (i = 0; i < nalt; ++i) {
0335 if (!power5p_limited_pmc_event(alt[i])) {
0336 alt[j] = alt[i];
0337 ++j;
0338 }
0339 }
0340 nalt = j;
0341 } else if ((flags & PPMU_LIMITED_PMC_REQD) && nlim < nalt) {
0342
0343 j = 0;
0344 for (i = 0; i < nalt; ++i) {
0345 if (power5p_limited_pmc_event(alt[i])) {
0346 alt[j] = alt[i];
0347 ++j;
0348 }
0349 }
0350 nalt = j;
0351 }
0352
0353 return nalt;
0354 }
0355
0356
0357
0358
0359
0360
0361
0362 static unsigned char direct_event_is_marked[0x28] = {
0363 0,
0364 0x1f,
0365 0x2,
0366 0xe,
0367 0,
0368 0x1c,
0369 0x80,
0370 0x80,
0371 0, 0, 0,
0372 0x18,
0373 0,
0374 0x80,
0375 0x80,
0376 0,
0377 0,
0378 0x14,
0379 0,
0380 0x10,
0381 0x1f,
0382 0x2,
0383 0x80,
0384 0x80,
0385 0, 0, 0, 0, 0,
0386 0x80,
0387 0x80,
0388 0,
0389 0x80,
0390 0x80,
0391 0x80,
0392 0x80,
0393 0x80,
0394 0x80,
0395 0x80,
0396 0x80,
0397 };
0398
0399
0400
0401
0402
0403 static int power5p_marked_instr_event(u64 event)
0404 {
0405 int pmc, psel;
0406 int bit, byte, unit;
0407 u32 mask;
0408
0409 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0410 psel = event & PM_PMCSEL_MSK;
0411 if (pmc >= 5)
0412 return 0;
0413
0414 bit = -1;
0415 if (psel < sizeof(direct_event_is_marked)) {
0416 if (direct_event_is_marked[psel] & (1 << pmc))
0417 return 1;
0418 if (direct_event_is_marked[psel] & 0x80)
0419 bit = 4;
0420 else if (psel == 0x08)
0421 bit = pmc - 1;
0422 else if (psel == 0x10)
0423 bit = 4 - pmc;
0424 else if (psel == 0x1b && (pmc == 1 || pmc == 3))
0425 bit = 4;
0426 } else if ((psel & 0x48) == 0x40) {
0427 bit = psel & 7;
0428 } else if (psel == 0x28) {
0429 bit = pmc - 1;
0430 } else if (pmc == 3 && (psel == 0x2e || psel == 0x2f)) {
0431 bit = 4;
0432 }
0433
0434 if (!(event & PM_BUSEVENT_MSK) || bit == -1)
0435 return 0;
0436
0437 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
0438 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
0439 if (unit == PM_LSU0) {
0440
0441 mask = 0x5dff00;
0442 } else if (unit == PM_LSU1 && byte >= 4) {
0443 byte -= 4;
0444
0445 mask = 0x5f11c000;
0446 } else
0447 return 0;
0448
0449 return (mask >> (byte * 8 + bit)) & 1;
0450 }
0451
0452 static int power5p_compute_mmcr(u64 event[], int n_ev,
0453 unsigned int hwc[], struct mmcr_regs *mmcr,
0454 struct perf_event *pevents[],
0455 u32 flags __maybe_unused)
0456 {
0457 unsigned long mmcr1 = 0;
0458 unsigned long mmcra = 0;
0459 unsigned int pmc, unit, byte, psel;
0460 unsigned int ttm;
0461 int i, isbus, bit, grsel;
0462 unsigned int pmc_inuse = 0;
0463 unsigned char busbyte[4];
0464 unsigned char unituse[16];
0465 int ttmuse;
0466
0467 if (n_ev > 6)
0468 return -1;
0469
0470
0471 memset(busbyte, 0, sizeof(busbyte));
0472 memset(unituse, 0, sizeof(unituse));
0473 for (i = 0; i < n_ev; ++i) {
0474 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
0475 if (pmc) {
0476 if (pmc > 6)
0477 return -1;
0478 if (pmc_inuse & (1 << (pmc - 1)))
0479 return -1;
0480 pmc_inuse |= 1 << (pmc - 1);
0481 }
0482 if (event[i] & PM_BUSEVENT_MSK) {
0483 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
0484 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
0485 if (unit > PM_LASTUNIT)
0486 return -1;
0487 if (unit == PM_ISU0_ALT)
0488 unit = PM_ISU0;
0489 if (byte >= 4) {
0490 if (unit != PM_LSU1)
0491 return -1;
0492 ++unit;
0493 byte &= 3;
0494 }
0495 if (busbyte[byte] && busbyte[byte] != unit)
0496 return -1;
0497 busbyte[byte] = unit;
0498 unituse[unit] = 1;
0499 }
0500 }
0501
0502
0503
0504
0505
0506
0507
0508 if (unituse[PM_ISU0] &
0509 (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_ISU1])) {
0510 unituse[PM_ISU0_ALT] = 1;
0511 unituse[PM_ISU0] = 0;
0512 }
0513
0514 ttmuse = 0;
0515 for (i = PM_FPU; i <= PM_ISU1; ++i) {
0516 if (!unituse[i])
0517 continue;
0518 if (ttmuse++)
0519 return -1;
0520 mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH;
0521 }
0522 ttmuse = 0;
0523 for (; i <= PM_GRS; ++i) {
0524 if (!unituse[i])
0525 continue;
0526 if (ttmuse++)
0527 return -1;
0528 mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH;
0529 }
0530 if (ttmuse > 1)
0531 return -1;
0532
0533
0534 for (byte = 0; byte < 4; ++byte) {
0535 unit = busbyte[byte];
0536 if (!unit)
0537 continue;
0538 if (unit == PM_ISU0 && unituse[PM_ISU0_ALT]) {
0539
0540 unit = PM_ISU0_ALT;
0541 } else if (unit == PM_LSU1 + 1) {
0542
0543 mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte);
0544 }
0545 ttm = unit >> 2;
0546 mmcr1 |= (unsigned long)ttm
0547 << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
0548 }
0549
0550
0551 for (i = 0; i < n_ev; ++i) {
0552 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
0553 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
0554 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
0555 psel = event[i] & PM_PMCSEL_MSK;
0556 isbus = event[i] & PM_BUSEVENT_MSK;
0557 if (!pmc) {
0558
0559 for (pmc = 0; pmc < 4; ++pmc) {
0560 if (!(pmc_inuse & (1 << pmc)))
0561 break;
0562 }
0563 if (pmc >= 4)
0564 return -1;
0565 pmc_inuse |= 1 << pmc;
0566 } else if (pmc <= 4) {
0567
0568 --pmc;
0569 if (isbus && (byte & 2) &&
0570 (psel == 8 || psel == 0x10 || psel == 0x28))
0571
0572 mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
0573 } else {
0574
0575 --pmc;
0576 }
0577 if (isbus && unit == PM_GRS) {
0578 bit = psel & 7;
0579 grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK;
0580 mmcr1 |= (unsigned long)grsel << grsel_shift[bit];
0581 }
0582 if (power5p_marked_instr_event(event[i]))
0583 mmcra |= MMCRA_SAMPLE_ENABLE;
0584 if ((psel & 0x58) == 0x40 && (byte & 1) != ((pmc >> 1) & 1))
0585
0586 psel |= 0x10;
0587 if (pmc <= 3)
0588 mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc);
0589 hwc[i] = pmc;
0590 }
0591
0592
0593 mmcr->mmcr0 = 0;
0594 if (pmc_inuse & 1)
0595 mmcr->mmcr0 = MMCR0_PMC1CE;
0596 if (pmc_inuse & 0x3e)
0597 mmcr->mmcr0 |= MMCR0_PMCjCE;
0598 mmcr->mmcr1 = mmcr1;
0599 mmcr->mmcra = mmcra;
0600 return 0;
0601 }
0602
0603 static void power5p_disable_pmc(unsigned int pmc, struct mmcr_regs *mmcr)
0604 {
0605 if (pmc <= 3)
0606 mmcr->mmcr1 &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc));
0607 }
0608
0609 static int power5p_generic_events[] = {
0610 [PERF_COUNT_HW_CPU_CYCLES] = 0xf,
0611 [PERF_COUNT_HW_INSTRUCTIONS] = 0x100009,
0612 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x1c10a8,
0613 [PERF_COUNT_HW_CACHE_MISSES] = 0x3c1088,
0614 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x230e4,
0615 [PERF_COUNT_HW_BRANCH_MISSES] = 0x230e5,
0616 };
0617
0618 #define C(x) PERF_COUNT_HW_CACHE_##x
0619
0620
0621
0622
0623
0624
0625 static u64 power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0626 [C(L1D)] = {
0627 [C(OP_READ)] = { 0x1c10a8, 0x3c1088 },
0628 [C(OP_WRITE)] = { 0x2c10a8, 0xc10c3 },
0629 [C(OP_PREFETCH)] = { 0xc70e7, -1 },
0630 },
0631 [C(L1I)] = {
0632 [C(OP_READ)] = { 0, 0 },
0633 [C(OP_WRITE)] = { -1, -1 },
0634 [C(OP_PREFETCH)] = { 0, 0 },
0635 },
0636 [C(LL)] = {
0637 [C(OP_READ)] = { 0, 0 },
0638 [C(OP_WRITE)] = { 0, 0 },
0639 [C(OP_PREFETCH)] = { 0xc50c3, 0 },
0640 },
0641 [C(DTLB)] = {
0642 [C(OP_READ)] = { 0xc20e4, 0x800c4 },
0643 [C(OP_WRITE)] = { -1, -1 },
0644 [C(OP_PREFETCH)] = { -1, -1 },
0645 },
0646 [C(ITLB)] = {
0647 [C(OP_READ)] = { 0, 0x800c0 },
0648 [C(OP_WRITE)] = { -1, -1 },
0649 [C(OP_PREFETCH)] = { -1, -1 },
0650 },
0651 [C(BPU)] = {
0652 [C(OP_READ)] = { 0x230e4, 0x230e5 },
0653 [C(OP_WRITE)] = { -1, -1 },
0654 [C(OP_PREFETCH)] = { -1, -1 },
0655 },
0656 [C(NODE)] = {
0657 [C(OP_READ)] = { -1, -1 },
0658 [C(OP_WRITE)] = { -1, -1 },
0659 [C(OP_PREFETCH)] = { -1, -1 },
0660 },
0661 };
0662
0663 static struct power_pmu power5p_pmu = {
0664 .name = "POWER5+/++",
0665 .n_counter = 6,
0666 .max_alternatives = MAX_ALT,
0667 .add_fields = 0x7000000000055ul,
0668 .test_adder = 0x3000040000000ul,
0669 .compute_mmcr = power5p_compute_mmcr,
0670 .get_constraint = power5p_get_constraint,
0671 .get_alternatives = power5p_get_alternatives,
0672 .disable_pmc = power5p_disable_pmc,
0673 .limited_pmc_event = power5p_limited_pmc_event,
0674 .flags = PPMU_LIMITED_PMC5_6 | PPMU_HAS_SSLOT,
0675 .n_generic = ARRAY_SIZE(power5p_generic_events),
0676 .generic_events = power5p_generic_events,
0677 .cache_events = &power5p_cache_events,
0678 };
0679
0680 int __init init_power5p_pmu(void)
0681 {
0682 unsigned int pvr = mfspr(SPRN_PVR);
0683
0684 if (PVR_VER(pvr) != PVR_POWER5p)
0685 return -ENODEV;
0686
0687 return register_power_pmu(&power5p_pmu);
0688 }