diff options
-rw-r--r-- | arch/powerpc/kernel/perf_counter.c | 16 |
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) { |