diff options
Diffstat (limited to 'arch/powerpc/kernel/power5+-pmu.c')
-rw-r--r-- | arch/powerpc/kernel/power5+-pmu.c | 95 |
1 files changed, 56 insertions, 39 deletions
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c index 41e5d2d958d4..f4adca8e98a4 100644 --- a/arch/powerpc/kernel/power5+-pmu.c +++ b/arch/powerpc/kernel/power5+-pmu.c | |||
@@ -10,7 +10,9 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/perf_counter.h> | 12 | #include <linux/perf_counter.h> |
13 | #include <linux/string.h> | ||
13 | #include <asm/reg.h> | 14 | #include <asm/reg.h> |
15 | #include <asm/cputable.h> | ||
14 | 16 | ||
15 | /* | 17 | /* |
16 | * Bits in event code for POWER5+ (POWER5 GS) and POWER5++ (POWER5 GS DD3) | 18 | * Bits in event code for POWER5+ (POWER5 GS) and POWER5++ (POWER5 GS DD3) |
@@ -126,20 +128,21 @@ static const int grsel_shift[8] = { | |||
126 | }; | 128 | }; |
127 | 129 | ||
128 | /* Masks and values for using events from the various units */ | 130 | /* Masks and values for using events from the various units */ |
129 | static u64 unit_cons[PM_LASTUNIT+1][2] = { | 131 | static unsigned long unit_cons[PM_LASTUNIT+1][2] = { |
130 | [PM_FPU] = { 0x3200000000ull, 0x0100000000ull }, | 132 | [PM_FPU] = { 0x3200000000ul, 0x0100000000ul }, |
131 | [PM_ISU0] = { 0x0200000000ull, 0x0080000000ull }, | 133 | [PM_ISU0] = { 0x0200000000ul, 0x0080000000ul }, |
132 | [PM_ISU1] = { 0x3200000000ull, 0x3100000000ull }, | 134 | [PM_ISU1] = { 0x3200000000ul, 0x3100000000ul }, |
133 | [PM_IFU] = { 0x3200000000ull, 0x2100000000ull }, | 135 | [PM_IFU] = { 0x3200000000ul, 0x2100000000ul }, |
134 | [PM_IDU] = { 0x0e00000000ull, 0x0040000000ull }, | 136 | [PM_IDU] = { 0x0e00000000ul, 0x0040000000ul }, |
135 | [PM_GRS] = { 0x0e00000000ull, 0x0c40000000ull }, | 137 | [PM_GRS] = { 0x0e00000000ul, 0x0c40000000ul }, |
136 | }; | 138 | }; |
137 | 139 | ||
138 | static int power5p_get_constraint(u64 event, u64 *maskp, u64 *valp) | 140 | static int power5p_get_constraint(u64 event, unsigned long *maskp, |
141 | unsigned long *valp) | ||
139 | { | 142 | { |
140 | int pmc, byte, unit, sh; | 143 | int pmc, byte, unit, sh; |
141 | int bit, fmask; | 144 | int bit, fmask; |
142 | u64 mask = 0, value = 0; | 145 | unsigned long mask = 0, value = 0; |
143 | 146 | ||
144 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 147 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
145 | if (pmc) { | 148 | if (pmc) { |
@@ -171,17 +174,18 @@ static int power5p_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
171 | bit = event & 7; | 174 | bit = event & 7; |
172 | fmask = (bit == 6)? 7: 3; | 175 | fmask = (bit == 6)? 7: 3; |
173 | sh = grsel_shift[bit]; | 176 | sh = grsel_shift[bit]; |
174 | mask |= (u64)fmask << sh; | 177 | mask |= (unsigned long)fmask << sh; |
175 | value |= (u64)((event >> PM_GRS_SH) & fmask) << sh; | 178 | value |= (unsigned long)((event >> PM_GRS_SH) & fmask) |
179 | << sh; | ||
176 | } | 180 | } |
177 | /* Set byte lane select field */ | 181 | /* Set byte lane select field */ |
178 | mask |= 0xfULL << (24 - 4 * byte); | 182 | mask |= 0xfUL << (24 - 4 * byte); |
179 | value |= (u64)unit << (24 - 4 * byte); | 183 | value |= (unsigned long)unit << (24 - 4 * byte); |
180 | } | 184 | } |
181 | if (pmc < 5) { | 185 | if (pmc < 5) { |
182 | /* need a counter from PMC1-4 set */ | 186 | /* need a counter from PMC1-4 set */ |
183 | mask |= 0x8000000000000ull; | 187 | mask |= 0x8000000000000ul; |
184 | value |= 0x1000000000000ull; | 188 | value |= 0x1000000000000ul; |
185 | } | 189 | } |
186 | *maskp = mask; | 190 | *maskp = mask; |
187 | *valp = value; | 191 | *valp = value; |
@@ -452,10 +456,10 @@ static int power5p_marked_instr_event(u64 event) | |||
452 | } | 456 | } |
453 | 457 | ||
454 | static int power5p_compute_mmcr(u64 event[], int n_ev, | 458 | static int power5p_compute_mmcr(u64 event[], int n_ev, |
455 | unsigned int hwc[], u64 mmcr[]) | 459 | unsigned int hwc[], unsigned long mmcr[]) |
456 | { | 460 | { |
457 | u64 mmcr1 = 0; | 461 | unsigned long mmcr1 = 0; |
458 | u64 mmcra = 0; | 462 | unsigned long mmcra = 0; |
459 | unsigned int pmc, unit, byte, psel; | 463 | unsigned int pmc, unit, byte, psel; |
460 | unsigned int ttm; | 464 | unsigned int ttm; |
461 | int i, isbus, bit, grsel; | 465 | int i, isbus, bit, grsel; |
@@ -517,7 +521,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
517 | continue; | 521 | continue; |
518 | if (ttmuse++) | 522 | if (ttmuse++) |
519 | return -1; | 523 | return -1; |
520 | mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH; | 524 | mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH; |
521 | } | 525 | } |
522 | ttmuse = 0; | 526 | ttmuse = 0; |
523 | for (; i <= PM_GRS; ++i) { | 527 | for (; i <= PM_GRS; ++i) { |
@@ -525,7 +529,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
525 | continue; | 529 | continue; |
526 | if (ttmuse++) | 530 | if (ttmuse++) |
527 | return -1; | 531 | return -1; |
528 | mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH; | 532 | mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH; |
529 | } | 533 | } |
530 | if (ttmuse > 1) | 534 | if (ttmuse > 1) |
531 | return -1; | 535 | return -1; |
@@ -540,10 +544,11 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
540 | unit = PM_ISU0_ALT; | 544 | unit = PM_ISU0_ALT; |
541 | } else if (unit == PM_LSU1 + 1) { | 545 | } else if (unit == PM_LSU1 + 1) { |
542 | /* select lower word of LSU1 for this byte */ | 546 | /* select lower word of LSU1 for this byte */ |
543 | mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); | 547 | mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte); |
544 | } | 548 | } |
545 | ttm = unit >> 2; | 549 | ttm = unit >> 2; |
546 | mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | 550 | mmcr1 |= (unsigned long)ttm |
551 | << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | ||
547 | } | 552 | } |
548 | 553 | ||
549 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ | 554 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ |
@@ -568,7 +573,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
568 | if (isbus && (byte & 2) && | 573 | if (isbus && (byte & 2) && |
569 | (psel == 8 || psel == 0x10 || psel == 0x28)) | 574 | (psel == 8 || psel == 0x10 || psel == 0x28)) |
570 | /* add events on higher-numbered bus */ | 575 | /* add events on higher-numbered bus */ |
571 | mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc); | 576 | mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc); |
572 | } else { | 577 | } else { |
573 | /* Instructions or run cycles on PMC5/6 */ | 578 | /* Instructions or run cycles on PMC5/6 */ |
574 | --pmc; | 579 | --pmc; |
@@ -576,7 +581,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
576 | if (isbus && unit == PM_GRS) { | 581 | if (isbus && unit == PM_GRS) { |
577 | bit = psel & 7; | 582 | bit = psel & 7; |
578 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; | 583 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; |
579 | mmcr1 |= (u64)grsel << grsel_shift[bit]; | 584 | mmcr1 |= (unsigned long)grsel << grsel_shift[bit]; |
580 | } | 585 | } |
581 | if (power5p_marked_instr_event(event[i])) | 586 | if (power5p_marked_instr_event(event[i])) |
582 | mmcra |= MMCRA_SAMPLE_ENABLE; | 587 | mmcra |= MMCRA_SAMPLE_ENABLE; |
@@ -599,7 +604,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
599 | return 0; | 604 | return 0; |
600 | } | 605 | } |
601 | 606 | ||
602 | static void power5p_disable_pmc(unsigned int pmc, u64 mmcr[]) | 607 | static void power5p_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
603 | { | 608 | { |
604 | if (pmc <= 3) | 609 | if (pmc <= 3) |
605 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); | 610 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); |
@@ -654,18 +659,30 @@ static int power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
654 | }, | 659 | }, |
655 | }; | 660 | }; |
656 | 661 | ||
657 | struct power_pmu power5p_pmu = { | 662 | static struct power_pmu power5p_pmu = { |
658 | .n_counter = 6, | 663 | .name = "POWER5+/++", |
659 | .max_alternatives = MAX_ALT, | 664 | .n_counter = 6, |
660 | .add_fields = 0x7000000000055ull, | 665 | .max_alternatives = MAX_ALT, |
661 | .test_adder = 0x3000040000000ull, | 666 | .add_fields = 0x7000000000055ul, |
662 | .compute_mmcr = power5p_compute_mmcr, | 667 | .test_adder = 0x3000040000000ul, |
663 | .get_constraint = power5p_get_constraint, | 668 | .compute_mmcr = power5p_compute_mmcr, |
664 | .get_alternatives = power5p_get_alternatives, | 669 | .get_constraint = power5p_get_constraint, |
665 | .disable_pmc = power5p_disable_pmc, | 670 | .get_alternatives = power5p_get_alternatives, |
666 | .limited_pmc_event = power5p_limited_pmc_event, | 671 | .disable_pmc = power5p_disable_pmc, |
667 | .flags = PPMU_LIMITED_PMC5_6, | 672 | .limited_pmc_event = power5p_limited_pmc_event, |
668 | .n_generic = ARRAY_SIZE(power5p_generic_events), | 673 | .flags = PPMU_LIMITED_PMC5_6, |
669 | .generic_events = power5p_generic_events, | 674 | .n_generic = ARRAY_SIZE(power5p_generic_events), |
670 | .cache_events = &power5p_cache_events, | 675 | .generic_events = power5p_generic_events, |
676 | .cache_events = &power5p_cache_events, | ||
671 | }; | 677 | }; |
678 | |||
679 | static int init_power5p_pmu(void) | ||
680 | { | ||
681 | if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+") | ||
682 | && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5++")) | ||
683 | return -ENODEV; | ||
684 | |||
685 | return register_power_pmu(&power5p_pmu); | ||
686 | } | ||
687 | |||
688 | arch_initcall(init_power5p_pmu); | ||