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 0x7
22 #define PM_PMC_MSKS (PM_PMC_MSK << PM_PMC_SH)
24 #define PM_UNIT_MSK 0xf
25 #define PM_UNIT_MSKS (PM_UNIT_MSK << PM_UNIT_SH)
26 #define PM_LLAV 0x8000
30 #define PM_SUBUNIT_SH 8
31 #define PM_SUBUNIT_MSK 7
32 #define PM_SUBUNIT_MSKS (PM_SUBUNIT_MSK << PM_SUBUNIT_SH)
33 #define PM_PMCSEL_MSK 0xff
34 #define PM_BUSEVENT_MSK 0xf3700
39 #define MMCR1_TTM0SEL_SH 60
40 #define MMCR1_TTMSEL_SH(n) (MMCR1_TTM0SEL_SH - (n) * 4)
41 #define MMCR1_TTMSEL_MSK 0xf
42 #define MMCR1_TTMSEL(m, n) (((m) >> MMCR1_TTMSEL_SH(n)) & MMCR1_TTMSEL_MSK)
43 #define MMCR1_NESTSEL_SH 45
44 #define MMCR1_NESTSEL_MSK 0x7
45 #define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK)
46 #define MMCR1_PMC1_LLA (1ul << 44)
47 #define MMCR1_PMC1_LLA_VALUE (1ul << 39)
48 #define MMCR1_PMC1_ADDR_SEL (1ul << 35)
49 #define MMCR1_PMC1SEL_SH 24
50 #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8)
51 #define MMCR1_PMCSEL_MSK 0xff
65 static unsigned char direct_event_is_marked[0x60 >> 1] = {
120 static u32 marked_bus_events[16] = {
139 static int power6_marked_instr_event(
u64 event)
141 int pmc, psel, ptype;
151 if (psel <
sizeof(direct_event_is_marked)) {
152 ptype = direct_event_is_marked[psel];
153 if (pmc == 0 || !(ptype & (1 << (pmc - 1))))
161 bit = ptype ^ (pmc - 1);
162 }
else if ((psel & 0x48) == 0x40)
170 mask = marked_bus_events[
unit];
171 return (mask >> (byte * 8 + bit)) & 1;
177 static int p6_compute_mmcr(
u64 event[],
int n_ev,
178 unsigned int hwc[],
unsigned long mmcr[])
180 unsigned long mmcr1 = 0;
181 unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
183 unsigned int pmc, ev,
b,
u,
s, psel;
184 unsigned int ttmset = 0;
185 unsigned int pmc_inuse = 0;
189 for (i = 0; i < n_ev; ++
i) {
192 if (pmc_inuse & (1 << (pmc - 1)))
194 pmc_inuse |= 1 << (pmc - 1);
197 for (i = 0; i < n_ev; ++
i) {
204 for (pmc = 0; pmc < 4; ++pmc)
205 if (!(pmc_inuse & (1 << pmc)))
209 pmc_inuse |= 1 << pmc;
213 if (ev & PM_BUSEVENT_MSK) {
225 if ((ttmset & 0x10) &&
231 if (0x30 <= psel && psel <= 0x3d) {
237 if (pmc >= 2 && (psel & 0x90) == 0x80)
245 if (power6_marked_instr_event(event[i]))
246 mmcra |= MMCRA_SAMPLE_ENABLE;
252 mmcr[0] = MMCR0_PMC1CE;
254 mmcr[0] |= MMCR0_PMCjCE;
270 static int p6_get_constraint(
u64 event,
unsigned long *maskp,
273 int pmc,
byte, sh, subunit;
274 unsigned long mask = 0,
value = 0;
278 if (pmc > 4 && !(event == 0x500009 || event == 0x600005))
284 if (event & PM_BUSEVENT_MSK) {
289 if ((event & PM_UNIT_MSKS) == (5 <<
PM_UNIT_SH)) {
304 static int p6_limited_pmc_event(
u64 event)
308 return pmc == 5 || pmc == 6;
313 static const unsigned int event_alternatives[][
MAX_ALT] = {
314 { 0x0130e8, 0x2000f6, 0x3000fc },
315 { 0x080080, 0x10000d, 0x30000c, 0x4000f0 },
316 { 0x080088, 0x200054, 0x3000f0 },
317 { 0x10000a, 0x2000f4, 0x600005 },
318 { 0x10000b, 0x2000f5 },
319 { 0x10000e, 0x400010 },
320 { 0x100010, 0x4000f8 },
321 { 0x10001a, 0x200010 },
322 { 0x100026, 0x3000f8 },
323 { 0x100054, 0x2000f0 },
324 { 0x100056, 0x2000fc },
325 { 0x1000f0, 0x40000a },
326 { 0x1000f8, 0x200008 },
327 { 0x1000fc, 0x400006 },
328 { 0x20000e, 0x400007 },
329 { 0x200012, 0x300012 },
330 { 0x2000f2, 0x3000f2 },
331 { 0x2000f8, 0x300010 },
332 { 0x2000fe, 0x300056 },
333 { 0x2d0030, 0x30001a },
334 { 0x30000a, 0x400018 },
335 { 0x3000f6, 0x40000e },
336 { 0x3000fe, 0x400056 },
343 static int find_alternatives_list(
u64 event)
348 for (i = 0; i <
ARRAY_SIZE(event_alternatives); ++
i) {
349 if (event < event_alternatives[i][0])
352 alt = event_alternatives[
i][
j];
353 if (!alt || event < alt)
362 static int p6_get_alternatives(
u64 event,
unsigned int flags,
u64 alt[])
365 unsigned int psel, pmc;
366 unsigned int nalt = 1;
370 nlim = p6_limited_pmc_event(event);
373 i = find_alternatives_list(event);
377 aevent = event_alternatives[
i][
j];
381 alt[nalt++] = aevent;
382 nlim += p6_limited_pmc_event(aevent);
388 psel =
event & (PM_PMCSEL_MSK & ~1);
390 if (pmc && (psel == 0x32 || psel == 0x34))
395 if (pmc && (psel == 0x38 || psel == 0x3a))
397 ((pmc > 2? pmc - 2: pmc + 2) <<
PM_PMC_SH);
412 for (i = 0; i < nalt; ++
i) {
442 for (i = 0; i < nalt; ++
i) {
443 if (!p6_limited_pmc_event(alt[i])) {
452 for (i = 0; i < nalt; ++
i) {
453 if (p6_limited_pmc_event(alt[i])) {
464 static void p6_disable_pmc(
unsigned int pmc,
unsigned long mmcr[])
471 static int power6_generic_events[] = {
480 #define C(x) PERF_COUNT_HW_CACHE_##x
488 static int power6_cache_events[
C(
MAX)][
C(
OP_MAX)][
C(RESULT_MAX)] = {
490 [
C(
OP_READ)] = { 0x280030, 0x80080 },
492 [
C(OP_PREFETCH)] = { 0x810a4, 0 },
497 [
C(OP_PREFETCH)] = { 0x4008c, 0 },
500 [
C(
OP_READ)] = { 0x150730, 0x250532 },
502 [
C(OP_PREFETCH)] = { 0x810a6, 0 },
507 [
C(OP_PREFETCH)] = { -1, -1 },
512 [
C(OP_PREFETCH)] = { -1, -1 },
515 [
C(
OP_READ)] = { 0x430e6, 0x400052 },
517 [
C(OP_PREFETCH)] = { -1, -1 },
522 [
C(OP_PREFETCH)] = { -1, -1 },
530 .add_fields = 0x1555,
531 .test_adder = 0x3000,
532 .compute_mmcr = p6_compute_mmcr,
533 .get_constraint = p6_get_constraint,
534 .get_alternatives = p6_get_alternatives,
535 .disable_pmc = p6_disable_pmc,
536 .limited_pmc_event = p6_limited_pmc_event,
538 .n_generic =
ARRAY_SIZE(power6_generic_events),
539 .generic_events = power6_generic_events,
540 .cache_events = &power6_cache_events,
543 static int __init init_power6_pmu(
void)