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 0x7
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_UNIT_MSKS (PM_UNIT_MSK << PM_UNIT_SH)
0024 #define PM_LLAV 0x8000
0025 #define PM_LLA 0x4000
0026 #define PM_BYTE_SH 12
0027 #define PM_BYTE_MSK 3
0028 #define PM_SUBUNIT_SH 8
0029 #define PM_SUBUNIT_MSK 7
0030 #define PM_SUBUNIT_MSKS (PM_SUBUNIT_MSK << PM_SUBUNIT_SH)
0031 #define PM_PMCSEL_MSK 0xff
0032 #define PM_BUSEVENT_MSK 0xf3700
0033
0034
0035
0036
0037 #define MMCR1_TTM0SEL_SH 60
0038 #define MMCR1_TTMSEL_SH(n) (MMCR1_TTM0SEL_SH - (n) * 4)
0039 #define MMCR1_TTMSEL_MSK 0xf
0040 #define MMCR1_TTMSEL(m, n) (((m) >> MMCR1_TTMSEL_SH(n)) & MMCR1_TTMSEL_MSK)
0041 #define MMCR1_NESTSEL_SH 45
0042 #define MMCR1_NESTSEL_MSK 0x7
0043 #define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK)
0044 #define MMCR1_PMC1_LLA (1ul << 44)
0045 #define MMCR1_PMC1_LLA_VALUE (1ul << 39)
0046 #define MMCR1_PMC1_ADDR_SEL (1ul << 35)
0047 #define MMCR1_PMC1SEL_SH 24
0048 #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8)
0049 #define MMCR1_PMCSEL_MSK 0xff
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 static unsigned char direct_event_is_marked[0x60 >> 1] = {
0064 0,
0065 0,
0066 0,
0067 0x07,
0068 0x04,
0069 0x06,
0070 0,
0071 0,
0072 0x02,
0073 0x08,
0074 0,
0075 0,
0076 0x0c,
0077 0x0f,
0078 0x01,
0079 0,
0080 0,
0081 0,
0082 0,
0083 0,
0084 0x15,
0085 0,
0086 0,
0087 0,
0088 0x4f,
0089 0x7f,
0090 0x4f,
0091 0x5f,
0092 0x6f,
0093 0x4f,
0094 0,
0095 0x08,
0096 0x1f,
0097 0x1f,
0098 0x1f,
0099 0x1f,
0100 0x1f,
0101 0x1f,
0102 0x1f,
0103 0x1f,
0104 0,
0105 0x05,
0106 0x1c,
0107 0x02,
0108 0,
0109 0,
0110 0,
0111 0,
0112 };
0113
0114
0115
0116
0117
0118 static u32 marked_bus_events[16] = {
0119 0x01000000,
0120 0x00010000,
0121 0, 0, 0, 0,
0122 0x00000088,
0123 0x000000c0,
0124 0x04010000,
0125 0xff010000u,
0126 0,
0127 0x00000010,
0128 0,
0129 0x00000022,
0130 0, 0
0131 };
0132
0133
0134
0135
0136
0137 static int power6_marked_instr_event(u64 event)
0138 {
0139 int pmc, psel, ptype;
0140 int bit, byte, unit;
0141 u32 mask;
0142
0143 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0144 psel = (event & PM_PMCSEL_MSK) >> 1;
0145 if (pmc >= 5)
0146 return 0;
0147
0148 bit = -1;
0149 if (psel < sizeof(direct_event_is_marked)) {
0150 ptype = direct_event_is_marked[psel];
0151 if (pmc == 0 || !(ptype & (1 << (pmc - 1))))
0152 return 0;
0153 ptype >>= 4;
0154 if (ptype == 0)
0155 return 1;
0156 if (ptype == 1)
0157 bit = 0;
0158 else
0159 bit = ptype ^ (pmc - 1);
0160 } else if ((psel & 0x48) == 0x40)
0161 bit = psel & 7;
0162
0163 if (!(event & PM_BUSEVENT_MSK) || bit == -1)
0164 return 0;
0165
0166 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
0167 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
0168 mask = marked_bus_events[unit];
0169 return (mask >> (byte * 8 + bit)) & 1;
0170 }
0171
0172
0173
0174
0175 static int p6_compute_mmcr(u64 event[], int n_ev,
0176 unsigned int hwc[], struct mmcr_regs *mmcr, struct perf_event *pevents[],
0177 u32 flags __maybe_unused)
0178 {
0179 unsigned long mmcr1 = 0;
0180 unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
0181 int i;
0182 unsigned int pmc, ev, b, u, s, psel;
0183 unsigned int ttmset = 0;
0184 unsigned int pmc_inuse = 0;
0185
0186 if (n_ev > 6)
0187 return -1;
0188 for (i = 0; i < n_ev; ++i) {
0189 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
0190 if (pmc) {
0191 if (pmc_inuse & (1 << (pmc - 1)))
0192 return -1;
0193 pmc_inuse |= 1 << (pmc - 1);
0194 }
0195 }
0196 for (i = 0; i < n_ev; ++i) {
0197 ev = event[i];
0198 pmc = (ev >> PM_PMC_SH) & PM_PMC_MSK;
0199 if (pmc) {
0200 --pmc;
0201 } else {
0202
0203 for (pmc = 0; pmc < 4; ++pmc)
0204 if (!(pmc_inuse & (1 << pmc)))
0205 break;
0206 if (pmc >= 4)
0207 return -1;
0208 pmc_inuse |= 1 << pmc;
0209 }
0210 hwc[i] = pmc;
0211 psel = ev & PM_PMCSEL_MSK;
0212 if (ev & PM_BUSEVENT_MSK) {
0213
0214 b = (ev >> PM_BYTE_SH) & PM_BYTE_MSK;
0215 u = (ev >> PM_UNIT_SH) & PM_UNIT_MSK;
0216
0217 if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u)
0218 return -1;
0219 mmcr1 |= (unsigned long)u << MMCR1_TTMSEL_SH(b);
0220 ttmset |= 1 << b;
0221 if (u == 5) {
0222
0223 s = (ev >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK;
0224 if ((ttmset & 0x10) &&
0225 MMCR1_NESTSEL(mmcr1) != s)
0226 return -1;
0227 ttmset |= 0x10;
0228 mmcr1 |= (unsigned long)s << MMCR1_NESTSEL_SH;
0229 }
0230 if (0x30 <= psel && psel <= 0x3d) {
0231
0232 if (b >= 2)
0233 mmcr1 |= MMCR1_PMC1_ADDR_SEL >> pmc;
0234 }
0235
0236 if (pmc >= 2 && (psel & 0x90) == 0x80)
0237 psel ^= 0x20;
0238 }
0239 if (ev & PM_LLA) {
0240 mmcr1 |= MMCR1_PMC1_LLA >> pmc;
0241 if (ev & PM_LLAV)
0242 mmcr1 |= MMCR1_PMC1_LLA_VALUE >> pmc;
0243 }
0244 if (power6_marked_instr_event(event[i]))
0245 mmcra |= MMCRA_SAMPLE_ENABLE;
0246 if (pmc < 4)
0247 mmcr1 |= (unsigned long)psel << MMCR1_PMCSEL_SH(pmc);
0248 }
0249 mmcr->mmcr0 = 0;
0250 if (pmc_inuse & 1)
0251 mmcr->mmcr0 = MMCR0_PMC1CE;
0252 if (pmc_inuse & 0xe)
0253 mmcr->mmcr0 |= MMCR0_PMCjCE;
0254 mmcr->mmcr1 = mmcr1;
0255 mmcr->mmcra = mmcra;
0256 return 0;
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269 static int p6_get_constraint(u64 event, unsigned long *maskp,
0270 unsigned long *valp, u64 event_config1 __maybe_unused)
0271 {
0272 int pmc, byte, sh, subunit;
0273 unsigned long mask = 0, value = 0;
0274
0275 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0276 if (pmc) {
0277 if (pmc > 4 && !(event == 0x500009 || event == 0x600005))
0278 return -1;
0279 sh = (pmc - 1) * 2;
0280 mask |= 2 << sh;
0281 value |= 1 << sh;
0282 }
0283 if (event & PM_BUSEVENT_MSK) {
0284 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
0285 sh = byte * 4 + (16 - PM_UNIT_SH);
0286 mask |= PM_UNIT_MSKS << sh;
0287 value |= (unsigned long)(event & PM_UNIT_MSKS) << sh;
0288 if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) {
0289 subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK;
0290 mask |= (unsigned long)PM_SUBUNIT_MSK << 32;
0291 value |= (unsigned long)subunit << 32;
0292 }
0293 }
0294 if (pmc <= 4) {
0295 mask |= 0x8000;
0296 value |= 0x1000;
0297 }
0298 *maskp = mask;
0299 *valp = value;
0300 return 0;
0301 }
0302
0303 static int p6_limited_pmc_event(u64 event)
0304 {
0305 int pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0306
0307 return pmc == 5 || pmc == 6;
0308 }
0309
0310 #define MAX_ALT 4
0311
0312 static const unsigned int event_alternatives[][MAX_ALT] = {
0313 { 0x0130e8, 0x2000f6, 0x3000fc },
0314 { 0x080080, 0x10000d, 0x30000c, 0x4000f0 },
0315 { 0x080088, 0x200054, 0x3000f0 },
0316 { 0x10000a, 0x2000f4, 0x600005 },
0317 { 0x10000b, 0x2000f5 },
0318 { 0x10000e, 0x400010 },
0319 { 0x100010, 0x4000f8 },
0320 { 0x10001a, 0x200010 },
0321 { 0x100026, 0x3000f8 },
0322 { 0x100054, 0x2000f0 },
0323 { 0x100056, 0x2000fc },
0324 { 0x1000f0, 0x40000a },
0325 { 0x1000f8, 0x200008 },
0326 { 0x1000fc, 0x400006 },
0327 { 0x20000e, 0x400007 },
0328 { 0x200012, 0x300012 },
0329 { 0x2000f2, 0x3000f2 },
0330 { 0x2000f8, 0x300010 },
0331 { 0x2000fe, 0x300056 },
0332 { 0x2d0030, 0x30001a },
0333 { 0x30000a, 0x400018 },
0334 { 0x3000f6, 0x40000e },
0335 { 0x3000fe, 0x400056 },
0336 };
0337
0338
0339
0340
0341
0342 static int find_alternatives_list(u64 event)
0343 {
0344 int i, j;
0345 unsigned int alt;
0346
0347 for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
0348 if (event < event_alternatives[i][0])
0349 return -1;
0350 for (j = 0; j < MAX_ALT; ++j) {
0351 alt = event_alternatives[i][j];
0352 if (!alt || event < alt)
0353 break;
0354 if (event == alt)
0355 return i;
0356 }
0357 }
0358 return -1;
0359 }
0360
0361 static int p6_get_alternatives(u64 event, unsigned int flags, u64 alt[])
0362 {
0363 int i, j, nlim;
0364 unsigned int psel, pmc;
0365 unsigned int nalt = 1;
0366 u64 aevent;
0367
0368 alt[0] = event;
0369 nlim = p6_limited_pmc_event(event);
0370
0371
0372 i = find_alternatives_list(event);
0373 if (i >= 0) {
0374
0375 for (j = 0; j < MAX_ALT; ++j) {
0376 aevent = event_alternatives[i][j];
0377 if (!aevent)
0378 break;
0379 if (aevent != event)
0380 alt[nalt++] = aevent;
0381 nlim += p6_limited_pmc_event(aevent);
0382 }
0383
0384 } else {
0385
0386
0387 psel = event & (PM_PMCSEL_MSK & ~1);
0388 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0389 if (pmc && (psel == 0x32 || psel == 0x34))
0390 alt[nalt++] = ((event ^ 0x6) & ~PM_PMC_MSKS) |
0391 ((5 - pmc) << PM_PMC_SH);
0392
0393
0394 if (pmc && (psel == 0x38 || psel == 0x3a))
0395 alt[nalt++] = ((event ^ 0x2) & ~PM_PMC_MSKS) |
0396 ((pmc > 2? pmc - 2: pmc + 2) << PM_PMC_SH);
0397 }
0398
0399 if (flags & PPMU_ONLY_COUNT_RUN) {
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410 j = nalt;
0411 for (i = 0; i < nalt; ++i) {
0412 switch (alt[i]) {
0413 case 0x1e:
0414 alt[j++] = 0x600005;
0415 ++nlim;
0416 break;
0417 case 0x10000a:
0418 alt[j++] = 0x1e;
0419 break;
0420 case 2:
0421 alt[j++] = 0x500009;
0422 ++nlim;
0423 break;
0424 case 0x500009:
0425 alt[j++] = 2;
0426 break;
0427 case 0x10000e:
0428 alt[j++] = 0x4000f4;
0429 break;
0430 case 0x4000f4:
0431 alt[j++] = 0x10000e;
0432 break;
0433 }
0434 }
0435 nalt = j;
0436 }
0437
0438 if (!(flags & PPMU_LIMITED_PMC_OK) && nlim) {
0439
0440 j = 0;
0441 for (i = 0; i < nalt; ++i) {
0442 if (!p6_limited_pmc_event(alt[i])) {
0443 alt[j] = alt[i];
0444 ++j;
0445 }
0446 }
0447 nalt = j;
0448 } else if ((flags & PPMU_LIMITED_PMC_REQD) && nlim < nalt) {
0449
0450 j = 0;
0451 for (i = 0; i < nalt; ++i) {
0452 if (p6_limited_pmc_event(alt[i])) {
0453 alt[j] = alt[i];
0454 ++j;
0455 }
0456 }
0457 nalt = j;
0458 }
0459
0460 return nalt;
0461 }
0462
0463 static void p6_disable_pmc(unsigned int pmc, struct mmcr_regs *mmcr)
0464 {
0465
0466 if (pmc <= 3)
0467 mmcr->mmcr1 &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc));
0468 }
0469
0470 static int power6_generic_events[] = {
0471 [PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
0472 [PERF_COUNT_HW_INSTRUCTIONS] = 2,
0473 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x280030,
0474 [PERF_COUNT_HW_CACHE_MISSES] = 0x30000c,
0475 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x410a0,
0476 [PERF_COUNT_HW_BRANCH_MISSES] = 0x400052,
0477 };
0478
0479 #define C(x) PERF_COUNT_HW_CACHE_##x
0480
0481
0482
0483
0484
0485
0486
0487 static u64 power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0488 [C(L1D)] = {
0489 [C(OP_READ)] = { 0x280030, 0x80080 },
0490 [C(OP_WRITE)] = { 0x180032, 0x80088 },
0491 [C(OP_PREFETCH)] = { 0x810a4, 0 },
0492 },
0493 [C(L1I)] = {
0494 [C(OP_READ)] = { 0, 0x100056 },
0495 [C(OP_WRITE)] = { -1, -1 },
0496 [C(OP_PREFETCH)] = { 0x4008c, 0 },
0497 },
0498 [C(LL)] = {
0499 [C(OP_READ)] = { 0x150730, 0x250532 },
0500 [C(OP_WRITE)] = { 0x250432, 0x150432 },
0501 [C(OP_PREFETCH)] = { 0x810a6, 0 },
0502 },
0503 [C(DTLB)] = {
0504 [C(OP_READ)] = { 0, 0x20000e },
0505 [C(OP_WRITE)] = { -1, -1 },
0506 [C(OP_PREFETCH)] = { -1, -1 },
0507 },
0508 [C(ITLB)] = {
0509 [C(OP_READ)] = { 0, 0x420ce },
0510 [C(OP_WRITE)] = { -1, -1 },
0511 [C(OP_PREFETCH)] = { -1, -1 },
0512 },
0513 [C(BPU)] = {
0514 [C(OP_READ)] = { 0x430e6, 0x400052 },
0515 [C(OP_WRITE)] = { -1, -1 },
0516 [C(OP_PREFETCH)] = { -1, -1 },
0517 },
0518 [C(NODE)] = {
0519 [C(OP_READ)] = { -1, -1 },
0520 [C(OP_WRITE)] = { -1, -1 },
0521 [C(OP_PREFETCH)] = { -1, -1 },
0522 },
0523 };
0524
0525 static struct power_pmu power6_pmu = {
0526 .name = "POWER6",
0527 .n_counter = 6,
0528 .max_alternatives = MAX_ALT,
0529 .add_fields = 0x1555,
0530 .test_adder = 0x3000,
0531 .compute_mmcr = p6_compute_mmcr,
0532 .get_constraint = p6_get_constraint,
0533 .get_alternatives = p6_get_alternatives,
0534 .disable_pmc = p6_disable_pmc,
0535 .limited_pmc_event = p6_limited_pmc_event,
0536 .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR,
0537 .n_generic = ARRAY_SIZE(power6_generic_events),
0538 .generic_events = power6_generic_events,
0539 .cache_events = &power6_cache_events,
0540 };
0541
0542 int __init init_power6_pmu(void)
0543 {
0544 unsigned int pvr = mfspr(SPRN_PVR);
0545
0546 if (PVR_VER(pvr) != PVR_POWER6)
0547 return -ENODEV;
0548
0549 return register_power_pmu(&power6_pmu);
0550 }