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/power6-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/power6-pmu.c')
-rw-r--r-- | arch/powerpc/kernel/power6-pmu.c | 72 |
1 files changed, 43 insertions, 29 deletions
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c index 46f74bebcfd9..09ae5bf5bda7 100644 --- a/arch/powerpc/kernel/power6-pmu.c +++ b/arch/powerpc/kernel/power6-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 POWER6 | 18 | * Bits in event code for POWER6 |
@@ -41,9 +43,9 @@ | |||
41 | #define MMCR1_NESTSEL_SH 45 | 43 | #define MMCR1_NESTSEL_SH 45 |
42 | #define MMCR1_NESTSEL_MSK 0x7 | 44 | #define MMCR1_NESTSEL_MSK 0x7 |
43 | #define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK) | 45 | #define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK) |
44 | #define MMCR1_PMC1_LLA ((u64)1 << 44) | 46 | #define MMCR1_PMC1_LLA (1ul << 44) |
45 | #define MMCR1_PMC1_LLA_VALUE ((u64)1 << 39) | 47 | #define MMCR1_PMC1_LLA_VALUE (1ul << 39) |
46 | #define MMCR1_PMC1_ADDR_SEL ((u64)1 << 35) | 48 | #define MMCR1_PMC1_ADDR_SEL (1ul << 35) |
47 | #define MMCR1_PMC1SEL_SH 24 | 49 | #define MMCR1_PMC1SEL_SH 24 |
48 | #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8) | 50 | #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8) |
49 | #define MMCR1_PMCSEL_MSK 0xff | 51 | #define MMCR1_PMCSEL_MSK 0xff |
@@ -173,10 +175,10 @@ static int power6_marked_instr_event(u64 event) | |||
173 | * Assign PMC numbers and compute MMCR1 value for a set of events | 175 | * Assign PMC numbers and compute MMCR1 value for a set of events |
174 | */ | 176 | */ |
175 | static int p6_compute_mmcr(u64 event[], int n_ev, | 177 | static int p6_compute_mmcr(u64 event[], int n_ev, |
176 | unsigned int hwc[], u64 mmcr[]) | 178 | unsigned int hwc[], unsigned long mmcr[]) |
177 | { | 179 | { |
178 | u64 mmcr1 = 0; | 180 | unsigned long mmcr1 = 0; |
179 | u64 mmcra = 0; | 181 | unsigned long mmcra = 0; |
180 | int i; | 182 | int i; |
181 | unsigned int pmc, ev, b, u, s, psel; | 183 | unsigned int pmc, ev, b, u, s, psel; |
182 | unsigned int ttmset = 0; | 184 | unsigned int ttmset = 0; |
@@ -215,7 +217,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
215 | /* check for conflict on this byte of event bus */ | 217 | /* check for conflict on this byte of event bus */ |
216 | if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u) | 218 | if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u) |
217 | return -1; | 219 | return -1; |
218 | mmcr1 |= (u64)u << MMCR1_TTMSEL_SH(b); | 220 | mmcr1 |= (unsigned long)u << MMCR1_TTMSEL_SH(b); |
219 | ttmset |= 1 << b; | 221 | ttmset |= 1 << b; |
220 | if (u == 5) { | 222 | if (u == 5) { |
221 | /* Nest events have a further mux */ | 223 | /* Nest events have a further mux */ |
@@ -224,7 +226,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
224 | MMCR1_NESTSEL(mmcr1) != s) | 226 | MMCR1_NESTSEL(mmcr1) != s) |
225 | return -1; | 227 | return -1; |
226 | ttmset |= 0x10; | 228 | ttmset |= 0x10; |
227 | mmcr1 |= (u64)s << MMCR1_NESTSEL_SH; | 229 | mmcr1 |= (unsigned long)s << MMCR1_NESTSEL_SH; |
228 | } | 230 | } |
229 | if (0x30 <= psel && psel <= 0x3d) { | 231 | if (0x30 <= psel && psel <= 0x3d) { |
230 | /* these need the PMCx_ADDR_SEL bits */ | 232 | /* these need the PMCx_ADDR_SEL bits */ |
@@ -243,7 +245,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
243 | if (power6_marked_instr_event(event[i])) | 245 | if (power6_marked_instr_event(event[i])) |
244 | mmcra |= MMCRA_SAMPLE_ENABLE; | 246 | mmcra |= MMCRA_SAMPLE_ENABLE; |
245 | if (pmc < 4) | 247 | if (pmc < 4) |
246 | mmcr1 |= (u64)psel << MMCR1_PMCSEL_SH(pmc); | 248 | mmcr1 |= (unsigned long)psel << MMCR1_PMCSEL_SH(pmc); |
247 | } | 249 | } |
248 | mmcr[0] = 0; | 250 | mmcr[0] = 0; |
249 | if (pmc_inuse & 1) | 251 | if (pmc_inuse & 1) |
@@ -265,10 +267,11 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
265 | * 20-23, 24-27, 28-31 ditto for bytes 1, 2, 3 | 267 | * 20-23, 24-27, 28-31 ditto for bytes 1, 2, 3 |
266 | * 32-34 select field: nest (subunit) event selector | 268 | * 32-34 select field: nest (subunit) event selector |
267 | */ | 269 | */ |
268 | static int p6_get_constraint(u64 event, u64 *maskp, u64 *valp) | 270 | static int p6_get_constraint(u64 event, unsigned long *maskp, |
271 | unsigned long *valp) | ||
269 | { | 272 | { |
270 | int pmc, byte, sh, subunit; | 273 | int pmc, byte, sh, subunit; |
271 | u64 mask = 0, value = 0; | 274 | unsigned long mask = 0, value = 0; |
272 | 275 | ||
273 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 276 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
274 | if (pmc) { | 277 | if (pmc) { |
@@ -282,11 +285,11 @@ static int p6_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
282 | byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK; | 285 | byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK; |
283 | sh = byte * 4 + (16 - PM_UNIT_SH); | 286 | sh = byte * 4 + (16 - PM_UNIT_SH); |
284 | mask |= PM_UNIT_MSKS << sh; | 287 | mask |= PM_UNIT_MSKS << sh; |
285 | value |= (u64)(event & PM_UNIT_MSKS) << sh; | 288 | value |= (unsigned long)(event & PM_UNIT_MSKS) << sh; |
286 | if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) { | 289 | if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) { |
287 | subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK; | 290 | subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK; |
288 | mask |= (u64)PM_SUBUNIT_MSK << 32; | 291 | mask |= (unsigned long)PM_SUBUNIT_MSK << 32; |
289 | value |= (u64)subunit << 32; | 292 | value |= (unsigned long)subunit << 32; |
290 | } | 293 | } |
291 | } | 294 | } |
292 | if (pmc <= 4) { | 295 | if (pmc <= 4) { |
@@ -458,7 +461,7 @@ static int p6_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
458 | return nalt; | 461 | return nalt; |
459 | } | 462 | } |
460 | 463 | ||
461 | static void p6_disable_pmc(unsigned int pmc, u64 mmcr[]) | 464 | static void p6_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
462 | { | 465 | { |
463 | /* Set PMCxSEL to 0 to disable PMCx */ | 466 | /* Set PMCxSEL to 0 to disable PMCx */ |
464 | if (pmc <= 3) | 467 | if (pmc <= 3) |
@@ -515,18 +518,29 @@ static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
515 | }, | 518 | }, |
516 | }; | 519 | }; |
517 | 520 | ||
518 | struct power_pmu power6_pmu = { | 521 | static struct power_pmu power6_pmu = { |
519 | .n_counter = 6, | 522 | .name = "POWER6", |
520 | .max_alternatives = MAX_ALT, | 523 | .n_counter = 6, |
521 | .add_fields = 0x1555, | 524 | .max_alternatives = MAX_ALT, |
522 | .test_adder = 0x3000, | 525 | .add_fields = 0x1555, |
523 | .compute_mmcr = p6_compute_mmcr, | 526 | .test_adder = 0x3000, |
524 | .get_constraint = p6_get_constraint, | 527 | .compute_mmcr = p6_compute_mmcr, |
525 | .get_alternatives = p6_get_alternatives, | 528 | .get_constraint = p6_get_constraint, |
526 | .disable_pmc = p6_disable_pmc, | 529 | .get_alternatives = p6_get_alternatives, |
527 | .limited_pmc_event = p6_limited_pmc_event, | 530 | .disable_pmc = p6_disable_pmc, |
528 | .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR, | 531 | .limited_pmc_event = p6_limited_pmc_event, |
529 | .n_generic = ARRAY_SIZE(power6_generic_events), | 532 | .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR, |
530 | .generic_events = power6_generic_events, | 533 | .n_generic = ARRAY_SIZE(power6_generic_events), |
531 | .cache_events = &power6_cache_events, | 534 | .generic_events = power6_generic_events, |
535 | .cache_events = &power6_cache_events, | ||
532 | }; | 536 | }; |
537 | |||
538 | static int init_power6_pmu(void) | ||
539 | { | ||
540 | if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6")) | ||
541 | return -ENODEV; | ||
542 | |||
543 | return register_power_pmu(&power6_pmu); | ||
544 | } | ||
545 | |||
546 | arch_initcall(init_power6_pmu); | ||