diff options
Diffstat (limited to 'arch/powerpc/kernel')
| -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) { |
