0001
0002
0003
0004
0005
0006
0007 #include <linux/string.h>
0008 #include <linux/perf_event.h>
0009 #include <asm/reg.h>
0010 #include <asm/cputable.h>
0011
0012 #include "internal.h"
0013
0014
0015
0016
0017 #define PM_PMC_SH 12
0018 #define PM_PMC_MSK 0xf
0019 #define PM_UNIT_SH 8
0020 #define PM_UNIT_MSK 0xf
0021 #define PM_SPCSEL_SH 6
0022 #define PM_SPCSEL_MSK 3
0023 #define PM_BYTE_SH 4
0024 #define PM_BYTE_MSK 3
0025 #define PM_PMCSEL_MSK 0xf
0026
0027
0028 #define PM_NONE 0
0029 #define PM_FPU 1
0030 #define PM_VPU 2
0031 #define PM_ISU 3
0032 #define PM_IFU 4
0033 #define PM_IDU 5
0034 #define PM_STS 6
0035 #define PM_LSU0 7
0036 #define PM_LSU1U 8
0037 #define PM_LSU1L 9
0038 #define PM_LASTUNIT 9
0039
0040
0041
0042
0043 #define MMCR0_PMC1SEL_SH 8
0044 #define MMCR0_PMC2SEL_SH 1
0045 #define MMCR_PMCSEL_MSK 0x1f
0046
0047
0048
0049
0050 #define MMCR1_TTM0SEL_SH 62
0051 #define MMCR1_TTM1SEL_SH 59
0052 #define MMCR1_TTM3SEL_SH 53
0053 #define MMCR1_TTMSEL_MSK 3
0054 #define MMCR1_TD_CP_DBG0SEL_SH 50
0055 #define MMCR1_TD_CP_DBG1SEL_SH 48
0056 #define MMCR1_TD_CP_DBG2SEL_SH 46
0057 #define MMCR1_TD_CP_DBG3SEL_SH 44
0058 #define MMCR1_PMC1_ADDER_SEL_SH 39
0059 #define MMCR1_PMC2_ADDER_SEL_SH 38
0060 #define MMCR1_PMC6_ADDER_SEL_SH 37
0061 #define MMCR1_PMC5_ADDER_SEL_SH 36
0062 #define MMCR1_PMC8_ADDER_SEL_SH 35
0063 #define MMCR1_PMC7_ADDER_SEL_SH 34
0064 #define MMCR1_PMC3_ADDER_SEL_SH 33
0065 #define MMCR1_PMC4_ADDER_SEL_SH 32
0066 #define MMCR1_PMC3SEL_SH 27
0067 #define MMCR1_PMC4SEL_SH 22
0068 #define MMCR1_PMC5SEL_SH 17
0069 #define MMCR1_PMC6SEL_SH 12
0070 #define MMCR1_PMC7SEL_SH 7
0071 #define MMCR1_PMC8SEL_SH 2
0072
0073 static short mmcr1_adder_bits[8] = {
0074 MMCR1_PMC1_ADDER_SEL_SH,
0075 MMCR1_PMC2_ADDER_SEL_SH,
0076 MMCR1_PMC3_ADDER_SEL_SH,
0077 MMCR1_PMC4_ADDER_SEL_SH,
0078 MMCR1_PMC5_ADDER_SEL_SH,
0079 MMCR1_PMC6_ADDER_SEL_SH,
0080 MMCR1_PMC7_ADDER_SEL_SH,
0081 MMCR1_PMC8_ADDER_SEL_SH
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
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 static unsigned char direct_marked_event[8] = {
0130 (1<<2) | (1<<3),
0131 (1<<3) | (1<<5),
0132 (1<<3) | (1<<5),
0133 (1<<4) | (1<<5),
0134 (1<<4) | (1<<5),
0135 (1<<3) | (1<<4) | (1<<5),
0136
0137 (1<<4) | (1<<5),
0138 (1<<4)
0139 };
0140
0141
0142
0143
0144
0145 static int p970_marked_instr_event(u64 event)
0146 {
0147 int pmc, psel, unit, byte, bit;
0148 unsigned int mask;
0149
0150 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0151 psel = event & PM_PMCSEL_MSK;
0152 if (pmc) {
0153 if (direct_marked_event[pmc - 1] & (1 << psel))
0154 return 1;
0155 if (psel == 0)
0156 bit = (pmc <= 4)? pmc - 1: 8 - pmc;
0157 else if (psel == 7 || psel == 13)
0158 bit = 4;
0159 else
0160 return 0;
0161 } else
0162 bit = psel;
0163
0164 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
0165 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
0166 mask = 0;
0167 switch (unit) {
0168 case PM_VPU:
0169 mask = 0x4c;
0170 break;
0171 case PM_LSU0:
0172
0173 mask = 0x085dff00;
0174 break;
0175 case PM_LSU1L:
0176 mask = 0x50 << 24;
0177 break;
0178 }
0179 return (mask >> (byte * 8 + bit)) & 1;
0180 }
0181
0182
0183 static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
0184 [PM_FPU] = { 0xc80000000000ull, 0x040000000000ull },
0185 [PM_VPU] = { 0xc80000000000ull, 0xc40000000000ull },
0186 [PM_ISU] = { 0x080000000000ull, 0x020000000000ull },
0187 [PM_IFU] = { 0xc80000000000ull, 0x840000000000ull },
0188 [PM_IDU] = { 0x380000000000ull, 0x010000000000ull },
0189 [PM_STS] = { 0x380000000000ull, 0x310000000000ull },
0190 };
0191
0192 static int p970_get_constraint(u64 event, unsigned long *maskp,
0193 unsigned long *valp, u64 event_config1 __maybe_unused)
0194 {
0195 int pmc, byte, unit, sh, spcsel;
0196 unsigned long mask = 0, value = 0;
0197 int grp = -1;
0198
0199 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
0200 if (pmc) {
0201 if (pmc > 8)
0202 return -1;
0203 sh = (pmc - 1) * 2;
0204 mask |= 2 << sh;
0205 value |= 1 << sh;
0206 grp = ((pmc - 1) >> 1) & 1;
0207 }
0208 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
0209 if (unit) {
0210 if (unit > PM_LASTUNIT)
0211 return -1;
0212 mask |= unit_cons[unit][0];
0213 value |= unit_cons[unit][1];
0214 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
0215
0216
0217
0218
0219 if (!pmc)
0220 grp = byte & 1;
0221
0222 mask |= 0xfULL << (28 - 4 * byte);
0223 value |= (unsigned long)unit << (28 - 4 * byte);
0224 }
0225 if (grp == 0) {
0226
0227 mask |= 0x8000000000ull;
0228 value |= 0x1000000000ull;
0229 } else if (grp == 1) {
0230
0231 mask |= 0x800000000ull;
0232 value |= 0x100000000ull;
0233 }
0234 spcsel = (event >> PM_SPCSEL_SH) & PM_SPCSEL_MSK;
0235 if (spcsel) {
0236 mask |= 3ull << 48;
0237 value |= (unsigned long)spcsel << 48;
0238 }
0239 *maskp = mask;
0240 *valp = value;
0241 return 0;
0242 }
0243
0244 static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[])
0245 {
0246 alt[0] = event;
0247
0248
0249 if (event == 0x2002 || event == 0x3002) {
0250 alt[1] = event ^ 0x1000;
0251 return 2;
0252 }
0253
0254 return 1;
0255 }
0256
0257 static int p970_compute_mmcr(u64 event[], int n_ev,
0258 unsigned int hwc[], struct mmcr_regs *mmcr,
0259 struct perf_event *pevents[],
0260 u32 flags __maybe_unused)
0261 {
0262 unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0;
0263 unsigned int pmc, unit, byte, psel;
0264 unsigned int ttm, grp;
0265 unsigned int pmc_inuse = 0;
0266 unsigned int pmc_grp_use[2];
0267 unsigned char busbyte[4];
0268 unsigned char unituse[16];
0269 unsigned char unitmap[] = { 0, 0<<3, 3<<3, 1<<3, 2<<3, 0|4, 3|4 };
0270 unsigned char ttmuse[2];
0271 unsigned char pmcsel[8];
0272 int i;
0273 int spcsel;
0274
0275 if (n_ev > 8)
0276 return -1;
0277
0278
0279 pmc_grp_use[0] = pmc_grp_use[1] = 0;
0280 memset(busbyte, 0, sizeof(busbyte));
0281 memset(unituse, 0, sizeof(unituse));
0282 for (i = 0; i < n_ev; ++i) {
0283 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
0284 if (pmc) {
0285 if (pmc_inuse & (1 << (pmc - 1)))
0286 return -1;
0287 pmc_inuse |= 1 << (pmc - 1);
0288
0289 ++pmc_grp_use[((pmc - 1) >> 1) & 1];
0290 }
0291 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
0292 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
0293 if (unit) {
0294 if (unit > PM_LASTUNIT)
0295 return -1;
0296 if (!pmc)
0297 ++pmc_grp_use[byte & 1];
0298 if (busbyte[byte] && busbyte[byte] != unit)
0299 return -1;
0300 busbyte[byte] = unit;
0301 unituse[unit] = 1;
0302 }
0303 }
0304 if (pmc_grp_use[0] > 4 || pmc_grp_use[1] > 4)
0305 return -1;
0306
0307
0308
0309
0310
0311
0312
0313 if (unituse[PM_ISU] &
0314 (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_VPU]))
0315 unitmap[PM_ISU] = 2 | 4;
0316
0317 ttmuse[0] = ttmuse[1] = 0;
0318 for (i = PM_FPU; i <= PM_STS; ++i) {
0319 if (!unituse[i])
0320 continue;
0321 ttm = unitmap[i];
0322 ++ttmuse[(ttm >> 2) & 1];
0323 mmcr1 |= (unsigned long)(ttm & ~4) << MMCR1_TTM1SEL_SH;
0324 }
0325
0326 if (ttmuse[0] > 1 || ttmuse[1] > 1)
0327 return -1;
0328
0329
0330 for (byte = 0; byte < 4; ++byte) {
0331 unit = busbyte[byte];
0332 if (!unit)
0333 continue;
0334 if (unit <= PM_STS)
0335 ttm = (unitmap[unit] >> 2) & 1;
0336 else if (unit == PM_LSU0)
0337 ttm = 2;
0338 else {
0339 ttm = 3;
0340 if (unit == PM_LSU1L && byte >= 2)
0341 mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte);
0342 }
0343 mmcr1 |= (unsigned long)ttm
0344 << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
0345 }
0346
0347
0348 memset(pmcsel, 0x8, sizeof(pmcsel));
0349 for (i = 0; i < n_ev; ++i) {
0350 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
0351 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
0352 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
0353 psel = event[i] & PM_PMCSEL_MSK;
0354 if (!pmc) {
0355
0356 if (unit)
0357 psel |= 0x10 | ((byte & 2) << 2);
0358 else
0359 psel |= 8;
0360 for (pmc = 0; pmc < 8; ++pmc) {
0361 if (pmc_inuse & (1 << pmc))
0362 continue;
0363 grp = (pmc >> 1) & 1;
0364 if (unit) {
0365 if (grp == (byte & 1))
0366 break;
0367 } else if (pmc_grp_use[grp] < 4) {
0368 ++pmc_grp_use[grp];
0369 break;
0370 }
0371 }
0372 pmc_inuse |= 1 << pmc;
0373 } else {
0374
0375 --pmc;
0376 if (psel == 0 && (byte & 2))
0377
0378 mmcr1 |= 1ull << mmcr1_adder_bits[pmc];
0379 }
0380 pmcsel[pmc] = psel;
0381 hwc[i] = pmc;
0382 spcsel = (event[i] >> PM_SPCSEL_SH) & PM_SPCSEL_MSK;
0383 mmcr1 |= spcsel;
0384 if (p970_marked_instr_event(event[i]))
0385 mmcra |= MMCRA_SAMPLE_ENABLE;
0386 }
0387 for (pmc = 0; pmc < 2; ++pmc)
0388 mmcr0 |= pmcsel[pmc] << (MMCR0_PMC1SEL_SH - 7 * pmc);
0389 for (; pmc < 8; ++pmc)
0390 mmcr1 |= (unsigned long)pmcsel[pmc]
0391 << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2));
0392 if (pmc_inuse & 1)
0393 mmcr0 |= MMCR0_PMC1CE;
0394 if (pmc_inuse & 0xfe)
0395 mmcr0 |= MMCR0_PMCjCE;
0396
0397 mmcra |= 0x2000;
0398
0399
0400 mmcr->mmcr0 = mmcr0;
0401 mmcr->mmcr1 = mmcr1;
0402 mmcr->mmcra = mmcra;
0403 return 0;
0404 }
0405
0406 static void p970_disable_pmc(unsigned int pmc, struct mmcr_regs *mmcr)
0407 {
0408 int shift;
0409
0410
0411
0412
0413 if (pmc <= 1) {
0414 shift = MMCR0_PMC1SEL_SH - 7 * pmc;
0415 mmcr->mmcr0 = (mmcr->mmcr0 & ~(0x1fUL << shift)) | (0x08UL << shift);
0416 } else {
0417 shift = MMCR1_PMC3SEL_SH - 5 * (pmc - 2);
0418 mmcr->mmcr1 = (mmcr->mmcr1 & ~(0x1fUL << shift)) | (0x08UL << shift);
0419 }
0420 }
0421
0422 static int ppc970_generic_events[] = {
0423 [PERF_COUNT_HW_CPU_CYCLES] = 7,
0424 [PERF_COUNT_HW_INSTRUCTIONS] = 1,
0425 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x8810,
0426 [PERF_COUNT_HW_CACHE_MISSES] = 0x3810,
0427 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x431,
0428 [PERF_COUNT_HW_BRANCH_MISSES] = 0x327,
0429 };
0430
0431 #define C(x) PERF_COUNT_HW_CACHE_##x
0432
0433
0434
0435
0436
0437
0438 static u64 ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0439 [C(L1D)] = {
0440 [C(OP_READ)] = { 0x8810, 0x3810 },
0441 [C(OP_WRITE)] = { 0x7810, 0x813 },
0442 [C(OP_PREFETCH)] = { 0x731, 0 },
0443 },
0444 [C(L1I)] = {
0445 [C(OP_READ)] = { 0, 0 },
0446 [C(OP_WRITE)] = { -1, -1 },
0447 [C(OP_PREFETCH)] = { 0, 0 },
0448 },
0449 [C(LL)] = {
0450 [C(OP_READ)] = { 0, 0 },
0451 [C(OP_WRITE)] = { 0, 0 },
0452 [C(OP_PREFETCH)] = { 0x733, 0 },
0453 },
0454 [C(DTLB)] = {
0455 [C(OP_READ)] = { 0, 0x704 },
0456 [C(OP_WRITE)] = { -1, -1 },
0457 [C(OP_PREFETCH)] = { -1, -1 },
0458 },
0459 [C(ITLB)] = {
0460 [C(OP_READ)] = { 0, 0x700 },
0461 [C(OP_WRITE)] = { -1, -1 },
0462 [C(OP_PREFETCH)] = { -1, -1 },
0463 },
0464 [C(BPU)] = {
0465 [C(OP_READ)] = { 0x431, 0x327 },
0466 [C(OP_WRITE)] = { -1, -1 },
0467 [C(OP_PREFETCH)] = { -1, -1 },
0468 },
0469 [C(NODE)] = {
0470 [C(OP_READ)] = { -1, -1 },
0471 [C(OP_WRITE)] = { -1, -1 },
0472 [C(OP_PREFETCH)] = { -1, -1 },
0473 },
0474 };
0475
0476 static struct power_pmu ppc970_pmu = {
0477 .name = "PPC970/FX/MP",
0478 .n_counter = 8,
0479 .max_alternatives = 2,
0480 .add_fields = 0x001100005555ull,
0481 .test_adder = 0x013300000000ull,
0482 .compute_mmcr = p970_compute_mmcr,
0483 .get_constraint = p970_get_constraint,
0484 .get_alternatives = p970_get_alternatives,
0485 .disable_pmc = p970_disable_pmc,
0486 .n_generic = ARRAY_SIZE(ppc970_generic_events),
0487 .generic_events = ppc970_generic_events,
0488 .cache_events = &ppc970_cache_events,
0489 .flags = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
0490 };
0491
0492 int __init init_ppc970_pmu(void)
0493 {
0494 unsigned int pvr = mfspr(SPRN_PVR);
0495
0496 if (PVR_VER(pvr) != PVR_970 && PVR_VER(pvr) != PVR_970MP &&
0497 PVR_VER(pvr) != PVR_970FX && PVR_VER(pvr) != PVR_970GX)
0498 return -ENODEV;
0499
0500 return register_power_pmu(&ppc970_pmu);
0501 }