aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/perf_counter.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/perf_counter.c')
-rw-r--r--arch/powerpc/kernel/perf_counter.c68
1 files changed, 35 insertions, 33 deletions
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c
index 70e1f57f7dd8..7ceefaf3a7f5 100644
--- a/arch/powerpc/kernel/perf_counter.c
+++ b/arch/powerpc/kernel/perf_counter.c
@@ -32,6 +32,9 @@ struct cpu_hw_counters {
32 unsigned long mmcr[3]; 32 unsigned long mmcr[3];
33 struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS]; 33 struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS];
34 u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; 34 u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS];
35 u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
36 unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
37 unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
35}; 38};
36DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters); 39DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters);
37 40
@@ -62,7 +65,6 @@ static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
62{ 65{
63 return 0; 66 return 0;
64} 67}
65static inline void perf_set_pmu_inuse(int inuse) { }
66static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { } 68static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { }
67static inline u32 perf_get_misc_flags(struct pt_regs *regs) 69static inline u32 perf_get_misc_flags(struct pt_regs *regs)
68{ 70{
@@ -93,11 +95,6 @@ static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
93 return 0; 95 return 0;
94} 96}
95 97
96static inline void perf_set_pmu_inuse(int inuse)
97{
98 get_lppaca()->pmcregs_in_use = inuse;
99}
100
101/* 98/*
102 * The user wants a data address recorded. 99 * The user wants a data address recorded.
103 * If we're not doing instruction sampling, give them the SDAR 100 * If we're not doing instruction sampling, give them the SDAR
@@ -245,13 +242,11 @@ static void write_pmc(int idx, unsigned long val)
245 * and see if any combination of alternative codes is feasible. 242 * and see if any combination of alternative codes is feasible.
246 * The feasible set is returned in event[]. 243 * The feasible set is returned in event[].
247 */ 244 */
248static int power_check_constraints(u64 event[], unsigned int cflags[], 245static int power_check_constraints(struct cpu_hw_counters *cpuhw,
246 u64 event[], unsigned int cflags[],
249 int n_ev) 247 int n_ev)
250{ 248{
251 unsigned long mask, value, nv; 249 unsigned long mask, value, nv;
252 u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
253 unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
254 unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES];
255 unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS]; 250 unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS];
256 int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS]; 251 int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS];
257 int i, j; 252 int i, j;
@@ -266,21 +261,23 @@ static int power_check_constraints(u64 event[], unsigned int cflags[],
266 if ((cflags[i] & PPMU_LIMITED_PMC_REQD) 261 if ((cflags[i] & PPMU_LIMITED_PMC_REQD)
267 && !ppmu->limited_pmc_event(event[i])) { 262 && !ppmu->limited_pmc_event(event[i])) {
268 ppmu->get_alternatives(event[i], cflags[i], 263 ppmu->get_alternatives(event[i], cflags[i],
269 alternatives[i]); 264 cpuhw->alternatives[i]);
270 event[i] = alternatives[i][0]; 265 event[i] = cpuhw->alternatives[i][0];
271 } 266 }
272 if (ppmu->get_constraint(event[i], &amasks[i][0], 267 if (ppmu->get_constraint(event[i], &cpuhw->amasks[i][0],
273 &avalues[i][0])) 268 &cpuhw->avalues[i][0]))
274 return -1; 269 return -1;
275 } 270 }
276 value = mask = 0; 271 value = mask = 0;
277 for (i = 0; i < n_ev; ++i) { 272 for (i = 0; i < n_ev; ++i) {
278 nv = (value | avalues[i][0]) + (value & avalues[i][0] & addf); 273 nv = (value | cpuhw->avalues[i][0]) +
274 (value & cpuhw->avalues[i][0] & addf);
279 if ((((nv + tadd) ^ value) & mask) != 0 || 275 if ((((nv + tadd) ^ value) & mask) != 0 ||
280 (((nv + tadd) ^ avalues[i][0]) & amasks[i][0]) != 0) 276 (((nv + tadd) ^ cpuhw->avalues[i][0]) &
277 cpuhw->amasks[i][0]) != 0)
281 break; 278 break;
282 value = nv; 279 value = nv;
283 mask |= amasks[i][0]; 280 mask |= cpuhw->amasks[i][0];
284 } 281 }
285 if (i == n_ev) 282 if (i == n_ev)
286 return 0; /* all OK */ 283 return 0; /* all OK */
@@ -291,10 +288,11 @@ static int power_check_constraints(u64 event[], unsigned int cflags[],
291 for (i = 0; i < n_ev; ++i) { 288 for (i = 0; i < n_ev; ++i) {
292 choice[i] = 0; 289 choice[i] = 0;
293 n_alt[i] = ppmu->get_alternatives(event[i], cflags[i], 290 n_alt[i] = ppmu->get_alternatives(event[i], cflags[i],
294 alternatives[i]); 291 cpuhw->alternatives[i]);
295 for (j = 1; j < n_alt[i]; ++j) 292 for (j = 1; j < n_alt[i]; ++j)
296 ppmu->get_constraint(alternatives[i][j], 293 ppmu->get_constraint(cpuhw->alternatives[i][j],
297 &amasks[i][j], &avalues[i][j]); 294 &cpuhw->amasks[i][j],
295 &cpuhw->avalues[i][j]);
298 } 296 }
299 297
300 /* enumerate all possibilities and see if any will work */ 298 /* enumerate all possibilities and see if any will work */
@@ -313,11 +311,11 @@ static int power_check_constraints(u64 event[], unsigned int cflags[],
313 * where k > j, will satisfy the constraints. 311 * where k > j, will satisfy the constraints.
314 */ 312 */
315 while (++j < n_alt[i]) { 313 while (++j < n_alt[i]) {
316 nv = (value | avalues[i][j]) + 314 nv = (value | cpuhw->avalues[i][j]) +
317 (value & avalues[i][j] & addf); 315 (value & cpuhw->avalues[i][j] & addf);
318 if ((((nv + tadd) ^ value) & mask) == 0 && 316 if ((((nv + tadd) ^ value) & mask) == 0 &&
319 (((nv + tadd) ^ avalues[i][j]) 317 (((nv + tadd) ^ cpuhw->avalues[i][j])
320 & amasks[i][j]) == 0) 318 & cpuhw->amasks[i][j]) == 0)
321 break; 319 break;
322 } 320 }
323 if (j >= n_alt[i]) { 321 if (j >= n_alt[i]) {
@@ -339,7 +337,7 @@ static int power_check_constraints(u64 event[], unsigned int cflags[],
339 svalues[i] = value; 337 svalues[i] = value;
340 smasks[i] = mask; 338 smasks[i] = mask;
341 value = nv; 339 value = nv;
342 mask |= amasks[i][j]; 340 mask |= cpuhw->amasks[i][j];
343 ++i; 341 ++i;
344 j = -1; 342 j = -1;
345 } 343 }
@@ -347,7 +345,7 @@ static int power_check_constraints(u64 event[], unsigned int cflags[],
347 345
348 /* OK, we have a feasible combination, tell the caller the solution */ 346 /* OK, we have a feasible combination, tell the caller the solution */
349 for (i = 0; i < n_ev; ++i) 347 for (i = 0; i < n_ev; ++i)
350 event[i] = alternatives[i][choice[i]]; 348 event[i] = cpuhw->alternatives[i][choice[i]];
351 return 0; 349 return 0;
352} 350}
353 351
@@ -531,8 +529,7 @@ void hw_perf_disable(void)
531 * Check if we ever enabled the PMU on this cpu. 529 * Check if we ever enabled the PMU on this cpu.
532 */ 530 */
533 if (!cpuhw->pmcs_enabled) { 531 if (!cpuhw->pmcs_enabled) {
534 if (ppc_md.enable_pmcs) 532 ppc_enable_pmcs();
535 ppc_md.enable_pmcs();
536 cpuhw->pmcs_enabled = 1; 533 cpuhw->pmcs_enabled = 1;
537 } 534 }
538 535
@@ -594,7 +591,7 @@ void hw_perf_enable(void)
594 mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); 591 mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
595 mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); 592 mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
596 if (cpuhw->n_counters == 0) 593 if (cpuhw->n_counters == 0)
597 perf_set_pmu_inuse(0); 594 ppc_set_pmu_inuse(0);
598 goto out_enable; 595 goto out_enable;
599 } 596 }
600 597
@@ -627,7 +624,7 @@ void hw_perf_enable(void)
627 * bit set and set the hardware counters to their initial values. 624 * bit set and set the hardware counters to their initial values.
628 * Then unfreeze the counters. 625 * Then unfreeze the counters.
629 */ 626 */
630 perf_set_pmu_inuse(1); 627 ppc_set_pmu_inuse(1);
631 mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); 628 mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
632 mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); 629 mtspr(SPRN_MMCR1, cpuhw->mmcr[1]);
633 mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) 630 mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE))
@@ -752,7 +749,7 @@ int hw_perf_group_sched_in(struct perf_counter *group_leader,
752 return -EAGAIN; 749 return -EAGAIN;
753 if (check_excludes(cpuhw->counter, cpuhw->flags, n0, n)) 750 if (check_excludes(cpuhw->counter, cpuhw->flags, n0, n))
754 return -EAGAIN; 751 return -EAGAIN;
755 i = power_check_constraints(cpuhw->events, cpuhw->flags, n + n0); 752 i = power_check_constraints(cpuhw, cpuhw->events, cpuhw->flags, n + n0);
756 if (i < 0) 753 if (i < 0)
757 return -EAGAIN; 754 return -EAGAIN;
758 cpuhw->n_counters = n0 + n; 755 cpuhw->n_counters = n0 + n;
@@ -807,7 +804,7 @@ static int power_pmu_enable(struct perf_counter *counter)
807 cpuhw->flags[n0] = counter->hw.counter_base; 804 cpuhw->flags[n0] = counter->hw.counter_base;
808 if (check_excludes(cpuhw->counter, cpuhw->flags, n0, 1)) 805 if (check_excludes(cpuhw->counter, cpuhw->flags, n0, 1))
809 goto out; 806 goto out;
810 if (power_check_constraints(cpuhw->events, cpuhw->flags, n0 + 1)) 807 if (power_check_constraints(cpuhw, cpuhw->events, cpuhw->flags, n0 + 1))
811 goto out; 808 goto out;
812 809
813 counter->hw.config = cpuhw->events[n0]; 810 counter->hw.config = cpuhw->events[n0];
@@ -1012,6 +1009,7 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
1012 unsigned int cflags[MAX_HWCOUNTERS]; 1009 unsigned int cflags[MAX_HWCOUNTERS];
1013 int n; 1010 int n;
1014 int err; 1011 int err;
1012 struct cpu_hw_counters *cpuhw;
1015 1013
1016 if (!ppmu) 1014 if (!ppmu)
1017 return ERR_PTR(-ENXIO); 1015 return ERR_PTR(-ENXIO);
@@ -1090,7 +1088,11 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
1090 cflags[n] = flags; 1088 cflags[n] = flags;
1091 if (check_excludes(ctrs, cflags, n, 1)) 1089 if (check_excludes(ctrs, cflags, n, 1))
1092 return ERR_PTR(-EINVAL); 1090 return ERR_PTR(-EINVAL);
1093 if (power_check_constraints(events, cflags, n + 1)) 1091
1092 cpuhw = &get_cpu_var(cpu_hw_counters);
1093 err = power_check_constraints(cpuhw, events, cflags, n + 1);
1094 put_cpu_var(cpu_hw_counters);
1095 if (err)
1094 return ERR_PTR(-EINVAL); 1096 return ERR_PTR(-EINVAL);
1095 1097
1096 counter->hw.config = events[n]; 1098 counter->hw.config = events[n];