aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/power5-pmu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-20 14:29:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-20 14:29:32 -0400
commit12e24f34cb0d55efd08c18b2112507d4bf498008 (patch)
tree83b07be17b8ef45f42360a3b9159b3aaae3fbad4 /arch/powerpc/kernel/power5-pmu.c
parent1eb51c33b21ffa3fceb634d1d6bcd6488c79bc26 (diff)
parenteadc84cc01e04f9f74ec2de0c9355be035c7b396 (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.c98
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 */
133static u64 unit_cons[PM_LASTUNIT+1][2] = { 135static 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
142static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) 144static 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
385static int power5_compute_mmcr(u64 event[], int n_ev, 389static 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
544static void power5_disable_pmc(unsigned int pmc, u64 mmcr[]) 549static 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
599struct power_pmu power5_pmu = { 604static 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
619static 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
627arch_initcall(init_power5_pmu);