diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-20 14:29:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-20 14:29:32 -0400 |
commit | 12e24f34cb0d55efd08c18b2112507d4bf498008 (patch) | |
tree | 83b07be17b8ef45f42360a3b9159b3aaae3fbad4 /arch/powerpc/kernel/power5-pmu.c | |
parent | 1eb51c33b21ffa3fceb634d1d6bcd6488c79bc26 (diff) | |
parent | eadc84cc01e04f9f74ec2de0c9355be035c7b396 (diff) |
Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (49 commits)
perfcounter: Handle some IO return values
perf_counter: Push perf_sample_data through the swcounter code
perf_counter tools: Define and use our own u64, s64 etc. definitions
perf_counter: Close race in perf_lock_task_context()
perf_counter, x86: Improve interactions with fast-gup
perf_counter: Simplify and fix task migration counting
perf_counter tools: Add a data file header
perf_counter: Update userspace callchain sampling uses
perf_counter: Make callchain samples extensible
perf report: Filter to parent set by default
perf_counter tools: Handle lost events
perf_counter: Add event overlow handling
fs: Provide empty .set_page_dirty() aop for anon inodes
perf_counter: tools: Makefile tweaks for 64-bit powerpc
perf_counter: powerpc: Add processor back-end for MPC7450 family
perf_counter: powerpc: Make powerpc perf_counter code safe for 32-bit kernels
perf_counter: powerpc: Change how processor-specific back-ends get selected
perf_counter: powerpc: Use unsigned long for register and constraint values
perf_counter: powerpc: Enable use of software counters on 32-bit powerpc
perf_counter tools: Add and use isprint()
...
Diffstat (limited to 'arch/powerpc/kernel/power5-pmu.c')
-rw-r--r-- | arch/powerpc/kernel/power5-pmu.c | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c index 05600b66221a..29b2c6c0e83a 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 (not POWER5++) | 18 | * Bits in event code for POWER5 (not POWER5++) |
@@ -130,20 +132,21 @@ static const int grsel_shift[8] = { | |||
130 | }; | 132 | }; |
131 | 133 | ||
132 | /* Masks and values for using events from the various units */ | 134 | /* Masks and values for using events from the various units */ |
133 | static u64 unit_cons[PM_LASTUNIT+1][2] = { | 135 | static unsigned long unit_cons[PM_LASTUNIT+1][2] = { |
134 | [PM_FPU] = { 0xc0002000000000ull, 0x00001000000000ull }, | 136 | [PM_FPU] = { 0xc0002000000000ul, 0x00001000000000ul }, |
135 | [PM_ISU0] = { 0x00002000000000ull, 0x00000800000000ull }, | 137 | [PM_ISU0] = { 0x00002000000000ul, 0x00000800000000ul }, |
136 | [PM_ISU1] = { 0xc0002000000000ull, 0xc0001000000000ull }, | 138 | [PM_ISU1] = { 0xc0002000000000ul, 0xc0001000000000ul }, |
137 | [PM_IFU] = { 0xc0002000000000ull, 0x80001000000000ull }, | 139 | [PM_IFU] = { 0xc0002000000000ul, 0x80001000000000ul }, |
138 | [PM_IDU] = { 0x30002000000000ull, 0x00000400000000ull }, | 140 | [PM_IDU] = { 0x30002000000000ul, 0x00000400000000ul }, |
139 | [PM_GRS] = { 0x30002000000000ull, 0x30000400000000ull }, | 141 | [PM_GRS] = { 0x30002000000000ul, 0x30000400000000ul }, |
140 | }; | 142 | }; |
141 | 143 | ||
142 | static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) | 144 | static int power5_get_constraint(u64 event, unsigned long *maskp, |
145 | unsigned long *valp) | ||
143 | { | 146 | { |
144 | int pmc, byte, unit, sh; | 147 | int pmc, byte, unit, sh; |
145 | int bit, fmask; | 148 | int bit, fmask; |
146 | u64 mask = 0, value = 0; | 149 | unsigned long mask = 0, value = 0; |
147 | int grp = -1; | 150 | int grp = -1; |
148 | 151 | ||
149 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 152 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
@@ -178,8 +181,9 @@ static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
178 | bit = event & 7; | 181 | bit = event & 7; |
179 | fmask = (bit == 6)? 7: 3; | 182 | fmask = (bit == 6)? 7: 3; |
180 | sh = grsel_shift[bit]; | 183 | sh = grsel_shift[bit]; |
181 | mask |= (u64)fmask << sh; | 184 | mask |= (unsigned long)fmask << sh; |
182 | value |= (u64)((event >> PM_GRS_SH) & fmask) << sh; | 185 | value |= (unsigned long)((event >> PM_GRS_SH) & fmask) |
186 | << sh; | ||
183 | } | 187 | } |
184 | /* | 188 | /* |
185 | * Bus events on bytes 0 and 2 can be counted | 189 | * Bus events on bytes 0 and 2 can be counted |
@@ -188,22 +192,22 @@ static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
188 | if (!pmc) | 192 | if (!pmc) |
189 | grp = byte & 1; | 193 | grp = byte & 1; |
190 | /* Set byte lane select field */ | 194 | /* Set byte lane select field */ |
191 | mask |= 0xfULL << (24 - 4 * byte); | 195 | mask |= 0xfUL << (24 - 4 * byte); |
192 | value |= (u64)unit << (24 - 4 * byte); | 196 | value |= (unsigned long)unit << (24 - 4 * byte); |
193 | } | 197 | } |
194 | if (grp == 0) { | 198 | if (grp == 0) { |
195 | /* increment PMC1/2 field */ | 199 | /* increment PMC1/2 field */ |
196 | mask |= 0x200000000ull; | 200 | mask |= 0x200000000ul; |
197 | value |= 0x080000000ull; | 201 | value |= 0x080000000ul; |
198 | } else if (grp == 1) { | 202 | } else if (grp == 1) { |
199 | /* increment PMC3/4 field */ | 203 | /* increment PMC3/4 field */ |
200 | mask |= 0x40000000ull; | 204 | mask |= 0x40000000ul; |
201 | value |= 0x10000000ull; | 205 | value |= 0x10000000ul; |
202 | } | 206 | } |
203 | if (pmc < 5) { | 207 | if (pmc < 5) { |
204 | /* need a counter from PMC1-4 set */ | 208 | /* need a counter from PMC1-4 set */ |
205 | mask |= 0x8000000000000ull; | 209 | mask |= 0x8000000000000ul; |
206 | value |= 0x1000000000000ull; | 210 | value |= 0x1000000000000ul; |
207 | } | 211 | } |
208 | *maskp = mask; | 212 | *maskp = mask; |
209 | *valp = value; | 213 | *valp = value; |
@@ -383,10 +387,10 @@ static int power5_marked_instr_event(u64 event) | |||
383 | } | 387 | } |
384 | 388 | ||
385 | static int power5_compute_mmcr(u64 event[], int n_ev, | 389 | static int power5_compute_mmcr(u64 event[], int n_ev, |
386 | unsigned int hwc[], u64 mmcr[]) | 390 | unsigned int hwc[], unsigned long mmcr[]) |
387 | { | 391 | { |
388 | u64 mmcr1 = 0; | 392 | unsigned long mmcr1 = 0; |
389 | u64 mmcra = 0; | 393 | unsigned long mmcra = 0; |
390 | unsigned int pmc, unit, byte, psel; | 394 | unsigned int pmc, unit, byte, psel; |
391 | unsigned int ttm, grp; | 395 | unsigned int ttm, grp; |
392 | int i, isbus, bit, grsel; | 396 | int i, isbus, bit, grsel; |
@@ -457,7 +461,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
457 | continue; | 461 | continue; |
458 | if (ttmuse++) | 462 | if (ttmuse++) |
459 | return -1; | 463 | return -1; |
460 | mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH; | 464 | mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH; |
461 | } | 465 | } |
462 | ttmuse = 0; | 466 | ttmuse = 0; |
463 | for (; i <= PM_GRS; ++i) { | 467 | for (; i <= PM_GRS; ++i) { |
@@ -465,7 +469,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
465 | continue; | 469 | continue; |
466 | if (ttmuse++) | 470 | if (ttmuse++) |
467 | return -1; | 471 | return -1; |
468 | mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH; | 472 | mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH; |
469 | } | 473 | } |
470 | if (ttmuse > 1) | 474 | if (ttmuse > 1) |
471 | return -1; | 475 | return -1; |
@@ -480,10 +484,11 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
480 | unit = PM_ISU0_ALT; | 484 | unit = PM_ISU0_ALT; |
481 | } else if (unit == PM_LSU1 + 1) { | 485 | } else if (unit == PM_LSU1 + 1) { |
482 | /* select lower word of LSU1 for this byte */ | 486 | /* select lower word of LSU1 for this byte */ |
483 | mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); | 487 | mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte); |
484 | } | 488 | } |
485 | ttm = unit >> 2; | 489 | ttm = unit >> 2; |
486 | mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | 490 | mmcr1 |= (unsigned long)ttm |
491 | << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | ||
487 | } | 492 | } |
488 | 493 | ||
489 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ | 494 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ |
@@ -513,7 +518,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
513 | --pmc; | 518 | --pmc; |
514 | if ((psel == 8 || psel == 0x10) && isbus && (byte & 2)) | 519 | if ((psel == 8 || psel == 0x10) && isbus && (byte & 2)) |
515 | /* add events on higher-numbered bus */ | 520 | /* add events on higher-numbered bus */ |
516 | mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc); | 521 | mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc); |
517 | } else { | 522 | } else { |
518 | /* Instructions or run cycles on PMC5/6 */ | 523 | /* Instructions or run cycles on PMC5/6 */ |
519 | --pmc; | 524 | --pmc; |
@@ -521,7 +526,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
521 | if (isbus && unit == PM_GRS) { | 526 | if (isbus && unit == PM_GRS) { |
522 | bit = psel & 7; | 527 | bit = psel & 7; |
523 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; | 528 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; |
524 | mmcr1 |= (u64)grsel << grsel_shift[bit]; | 529 | mmcr1 |= (unsigned long)grsel << grsel_shift[bit]; |
525 | } | 530 | } |
526 | if (power5_marked_instr_event(event[i])) | 531 | if (power5_marked_instr_event(event[i])) |
527 | mmcra |= MMCRA_SAMPLE_ENABLE; | 532 | mmcra |= MMCRA_SAMPLE_ENABLE; |
@@ -541,7 +546,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
541 | return 0; | 546 | return 0; |
542 | } | 547 | } |
543 | 548 | ||
544 | static void power5_disable_pmc(unsigned int pmc, u64 mmcr[]) | 549 | static void power5_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
545 | { | 550 | { |
546 | if (pmc <= 3) | 551 | if (pmc <= 3) |
547 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); | 552 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); |
@@ -596,16 +601,27 @@ static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
596 | }, | 601 | }, |
597 | }; | 602 | }; |
598 | 603 | ||
599 | struct power_pmu power5_pmu = { | 604 | static struct power_pmu power5_pmu = { |
600 | .n_counter = 6, | 605 | .name = "POWER5", |
601 | .max_alternatives = MAX_ALT, | 606 | .n_counter = 6, |
602 | .add_fields = 0x7000090000555ull, | 607 | .max_alternatives = MAX_ALT, |
603 | .test_adder = 0x3000490000000ull, | 608 | .add_fields = 0x7000090000555ul, |
604 | .compute_mmcr = power5_compute_mmcr, | 609 | .test_adder = 0x3000490000000ul, |
605 | .get_constraint = power5_get_constraint, | 610 | .compute_mmcr = power5_compute_mmcr, |
606 | .get_alternatives = power5_get_alternatives, | 611 | .get_constraint = power5_get_constraint, |
607 | .disable_pmc = power5_disable_pmc, | 612 | .get_alternatives = power5_get_alternatives, |
608 | .n_generic = ARRAY_SIZE(power5_generic_events), | 613 | .disable_pmc = power5_disable_pmc, |
609 | .generic_events = power5_generic_events, | 614 | .n_generic = ARRAY_SIZE(power5_generic_events), |
610 | .cache_events = &power5_cache_events, | 615 | .generic_events = power5_generic_events, |
616 | .cache_events = &power5_cache_events, | ||
611 | }; | 617 | }; |
618 | |||
619 | static int init_power5_pmu(void) | ||
620 | { | ||
621 | if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5")) | ||
622 | return -ENODEV; | ||
623 | |||
624 | return register_power_pmu(&power5_pmu); | ||
625 | } | ||
626 | |||
627 | arch_initcall(init_power5_pmu); | ||