aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/perf_counter.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c
index ea54686cb787..4cc4ac5c791c 100644
--- a/arch/powerpc/kernel/perf_counter.c
+++ b/arch/powerpc/kernel/perf_counter.c
@@ -372,16 +372,28 @@ static void write_mmcr0(struct cpu_hw_counters *cpuhw, unsigned long mmcr0)
372 372
373 /* 373 /*
374 * Write MMCR0, then read PMC5 and PMC6 immediately. 374 * Write MMCR0, then read PMC5 and PMC6 immediately.
375 * To ensure we don't get a performance monitor interrupt
376 * between writing MMCR0 and freezing/thawing the limited
377 * counters, we first write MMCR0 with the counter overflow
378 * interrupt enable bits turned off.
375 */ 379 */
376 asm volatile("mtspr %3,%2; mfspr %0,%4; mfspr %1,%5" 380 asm volatile("mtspr %3,%2; mfspr %0,%4; mfspr %1,%5"
377 : "=&r" (pmc5), "=&r" (pmc6) 381 : "=&r" (pmc5), "=&r" (pmc6)
378 : "r" (mmcr0), "i" (SPRN_MMCR0), 382 : "r" (mmcr0 & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)),
383 "i" (SPRN_MMCR0),
379 "i" (SPRN_PMC5), "i" (SPRN_PMC6)); 384 "i" (SPRN_PMC5), "i" (SPRN_PMC6));
380 385
381 if (mmcr0 & MMCR0_FC) 386 if (mmcr0 & MMCR0_FC)
382 freeze_limited_counters(cpuhw, pmc5, pmc6); 387 freeze_limited_counters(cpuhw, pmc5, pmc6);
383 else 388 else
384 thaw_limited_counters(cpuhw, pmc5, pmc6); 389 thaw_limited_counters(cpuhw, pmc5, pmc6);
390
391 /*
392 * Write the full MMCR0 including the counter overflow interrupt
393 * enable bits, if necessary.
394 */
395 if (mmcr0 & (MMCR0_PMC1CE | MMCR0_PMCjCE))
396 mtspr(SPRN_MMCR0, mmcr0);
385} 397}
386 398
387/* 399/*
@@ -1108,7 +1120,7 @@ static void perf_counter_interrupt(struct pt_regs *regs)
1108 1120
1109 for (i = 0; i < cpuhw->n_counters; ++i) { 1121 for (i = 0; i < cpuhw->n_counters; ++i) {
1110 counter = cpuhw->counter[i]; 1122 counter = cpuhw->counter[i];
1111 if (is_limited_pmc(counter->hw.idx)) 1123 if (!counter->hw.idx || is_limited_pmc(counter->hw.idx))
1112 continue; 1124 continue;
1113 val = read_pmc(counter->hw.idx); 1125 val = read_pmc(counter->hw.idx);
1114 if ((int)val < 0) { 1126 if ((int)val < 0) {