aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2012-11-05 10:53:54 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-01-10 01:02:01 -0500
commitbc09c219b2e6f9436d06a1a3a10eff97faab371c (patch)
tree375afd6a73f497aab5cf36c5e92038da9a4cbdd3
parent6a040ce72598159a74969a2d01ab0ba5ee6536b3 (diff)
powerpc/perf: Fix finding overflowed PMC in interrupt
If a PMC is about to overflow on a counter that's on an active perf event (ie. less than 256 from the end) and a _different_ PMC overflows just at this time (a PMC that's not on an active perf event), we currently mark the event as found, but in reality it's not as it's likely the other PMC that caused the IRQ. Since we mark it as found the second catch all for overflows doesn't run, and we don't reset the overflowing PMC ever. Hence we keep hitting that same PMC IRQ over and over and don't reset the actual overflowing counter. This is a rewrite of the perf interrupt handler for book3s to get around this. We now check to see if any of the PMCs have actually overflowed (ie >= 0x80000000). If yes, record it for active counters and just reset it for inactive counters. If it's not overflowed, then we check to see if it's one of the buggy power7 counters and if it is, record it and continue. If none of the PMCs match this, then we make note that we couldn't find the PMC that caused the IRQ. Signed-off-by: Michael Neuling <mikey@neuling.org> Reviewed-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> cc: Paul Mackerras <paulus@samba.org> cc: Anton Blanchard <anton@samba.org> cc: Linux PPC dev <linuxppc-dev@ozlabs.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/perf/core-book3s.c83
1 files changed, 54 insertions, 29 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index aa2465e21f1a..53fc7b8e5d9a 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1412,11 +1412,8 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs)
1412 return regs->nip; 1412 return regs->nip;
1413} 1413}
1414 1414
1415static bool pmc_overflow(unsigned long val) 1415static bool pmc_overflow_power7(unsigned long val)
1416{ 1416{
1417 if ((int)val < 0)
1418 return true;
1419
1420 /* 1417 /*
1421 * Events on POWER7 can roll back if a speculative event doesn't 1418 * Events on POWER7 can roll back if a speculative event doesn't
1422 * eventually complete. Unfortunately in some rare cases they will 1419 * eventually complete. Unfortunately in some rare cases they will
@@ -1428,7 +1425,15 @@ static bool pmc_overflow(unsigned long val)
1428 * PMCs because a user might set a period of less than 256 and we 1425 * PMCs because a user might set a period of less than 256 and we
1429 * don't want to mistakenly reset them. 1426 * don't want to mistakenly reset them.
1430 */ 1427 */
1431 if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256)) 1428 if ((0x80000000 - val) <= 256)
1429 return true;
1430
1431 return false;
1432}
1433
1434static bool pmc_overflow(unsigned long val)
1435{
1436 if ((int)val < 0)
1432 return true; 1437 return true;
1433 1438
1434 return false; 1439 return false;
@@ -1439,11 +1444,11 @@ static bool pmc_overflow(unsigned long val)
1439 */ 1444 */
1440static void perf_event_interrupt(struct pt_regs *regs) 1445static void perf_event_interrupt(struct pt_regs *regs)
1441{ 1446{
1442 int i; 1447 int i, j;
1443 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); 1448 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
1444 struct perf_event *event; 1449 struct perf_event *event;
1445 unsigned long val; 1450 unsigned long val[8];
1446 int found = 0; 1451 int found, active;
1447 int nmi; 1452 int nmi;
1448 1453
1449 if (cpuhw->n_limited) 1454 if (cpuhw->n_limited)
@@ -1458,33 +1463,53 @@ static void perf_event_interrupt(struct pt_regs *regs)
1458 else 1463 else
1459 irq_enter(); 1464 irq_enter();
1460 1465
1461 for (i = 0; i < cpuhw->n_events; ++i) { 1466 /* Read all the PMCs since we'll need them a bunch of times */
1462 event = cpuhw->event[i]; 1467 for (i = 0; i < ppmu->n_counter; ++i)
1463 if (!event->hw.idx || is_limited_pmc(event->hw.idx)) 1468 val[i] = read_pmc(i + 1);
1469
1470 /* Try to find what caused the IRQ */
1471 found = 0;
1472 for (i = 0; i < ppmu->n_counter; ++i) {
1473 if (!pmc_overflow(val[i]))
1464 continue; 1474 continue;
1465 val = read_pmc(event->hw.idx); 1475 if (is_limited_pmc(i + 1))
1466 if ((int)val < 0) { 1476 continue; /* these won't generate IRQs */
1467 /* event has overflowed */ 1477 /*
1468 found = 1; 1478 * We've found one that's overflowed. For active
1469 record_and_restart(event, val, regs); 1479 * counters we need to log this. For inactive
1480 * counters, we need to reset it anyway
1481 */
1482 found = 1;
1483 active = 0;
1484 for (j = 0; j < cpuhw->n_events; ++j) {
1485 event = cpuhw->event[j];
1486 if (event->hw.idx == (i + 1)) {
1487 active = 1;
1488 record_and_restart(event, val[i], regs);
1489 break;
1490 }
1470 } 1491 }
1492 if (!active)
1493 /* reset non active counters that have overflowed */
1494 write_pmc(i + 1, 0);
1471 } 1495 }
1472 1496 if (!found && pvr_version_is(PVR_POWER7)) {
1473 /* 1497 /* check active counters for special buggy p7 overflow */
1474 * In case we didn't find and reset the event that caused 1498 for (i = 0; i < cpuhw->n_events; ++i) {
1475 * the interrupt, scan all events and reset any that are 1499 event = cpuhw->event[i];
1476 * negative, to avoid getting continual interrupts. 1500 if (!event->hw.idx || is_limited_pmc(event->hw.idx))
1477 * Any that we processed in the previous loop will not be negative.
1478 */
1479 if (!found) {
1480 for (i = 0; i < ppmu->n_counter; ++i) {
1481 if (is_limited_pmc(i + 1))
1482 continue; 1501 continue;
1483 val = read_pmc(i + 1); 1502 if (pmc_overflow_power7(val[event->hw.idx - 1])) {
1484 if (pmc_overflow(val)) 1503 /* event has overflowed in a buggy way*/
1485 write_pmc(i + 1, 0); 1504 found = 1;
1505 record_and_restart(event,
1506 val[event->hw.idx - 1],
1507 regs);
1508 }
1486 } 1509 }
1487 } 1510 }
1511 if ((!found) && printk_ratelimit())
1512 printk(KERN_WARNING "Can't find PMC that caused IRQ\n");
1488 1513
1489 /* 1514 /*
1490 * Reset MMCR0 to its normal value. This will set PMXE and 1515 * Reset MMCR0 to its normal value. This will set PMXE and