aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/perf
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 20:09:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 20:09:55 -0500
commit9d3cae26acb471d5954cfdc25d1438b32060babe (patch)
tree77e93b6fb207438f7f1f30a201cc86bc5b0ec82b /arch/powerpc/perf
parentdf24eef3e794afbac69a377d1d2e2e3f5869f67a (diff)
parent8520e443aa56cc157b015205ea53e7b9fc831291 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc updates from Benjamin Herrenschmidt: "So from the depth of frozen Minnesota, here's the powerpc pull request for 3.9. It has a few interesting highlights, in addition to the usual bunch of bug fixes, minor updates, embedded device tree updates and new boards: - Hand tuned asm implementation of SHA1 (by Paulus & Michael Ellerman) - Support for Doorbell interrupts on Power8 (kind of fast thread-thread IPIs) by Ian Munsie - Long overdue cleanup of the way we handle relocation of our open firmware trampoline (prom_init.c) on 64-bit by Anton Blanchard - Support for saving/restoring & context switching the PPR (Processor Priority Register) on server processors that support it. This allows the kernel to preserve thread priorities established by userspace. By Haren Myneni. - DAWR (new watchpoint facility) support on Power8 by Michael Neuling - Ability to change the DSCR (Data Stream Control Register) which controls cache prefetching on a running process via ptrace by Alexey Kardashevskiy - Support for context switching the TAR register on Power8 (new branch target register meant to be used by some new specific userspace perf event interrupt facility which is yet to be enabled) by Ian Munsie. - Improve preservation of the CFAR register (which captures the origin of a branch) on various exception conditions by Paulus. - Move the Bestcomm DMA driver from arch powerpc to drivers/dma where it belongs by Philippe De Muyter - Support for Transactional Memory on Power8 by Michael Neuling (based on original work by Matt Evans). For those curious about the feature, the patch contains a pretty good description." (See commit db8ff907027b: "powerpc: Documentation for transactional memory on powerpc" for the mentioned description added to the file Documentation/powerpc/transactional_memory.txt) * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (140 commits) powerpc/kexec: Disable hard IRQ before kexec powerpc/85xx: l2sram - Add compatible string for BSC9131 platform powerpc/85xx: bsc9131 - Correct typo in SDHC device node powerpc/e500/qemu-e500: enable coreint powerpc/mpic: allow coreint to be determined by MPIC version powerpc/fsl_pci: Store the pci ctlr device ptr in the pci ctlr struct powerpc/85xx: Board support for ppa8548 powerpc/fsl: remove extraneous DIU platform functions arch/powerpc/platforms/85xx/p1022_ds.c: adjust duplicate test powerpc: Documentation for transactional memory on powerpc powerpc: Add transactional memory to pseries and ppc64 defconfigs powerpc: Add config option for transactional memory powerpc: Add transactional memory to POWER8 cpu features powerpc: Add new transactional memory state to the signal context powerpc: Hook in new transactional memory code powerpc: Routines for FP/VSX/VMX unavailable during a transaction powerpc: Add transactional memory unavaliable execption handler powerpc: Add reclaim and recheckpoint functions for context switching transactional memory processes powerpc: Add FP/VSX and VMX register load functions for transactional memory powerpc: Add helper functions for transactional memory context switching ...
Diffstat (limited to 'arch/powerpc/perf')
-rw-r--r--arch/powerpc/perf/core-book3s.c93
-rw-r--r--arch/powerpc/perf/e500-pmu.c2
2 files changed, 66 insertions, 29 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index fa476d50791f..65362e98eb26 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -880,8 +880,16 @@ static int power_pmu_add(struct perf_event *event, int ef_flags)
880 cpuhw->events[n0] = event->hw.config; 880 cpuhw->events[n0] = event->hw.config;
881 cpuhw->flags[n0] = event->hw.event_base; 881 cpuhw->flags[n0] = event->hw.event_base;
882 882
883 /*
884 * This event may have been disabled/stopped in record_and_restart()
885 * because we exceeded the ->event_limit. If re-starting the event,
886 * clear the ->hw.state (STOPPED and UPTODATE flags), so the user
887 * notification is re-enabled.
888 */
883 if (!(ef_flags & PERF_EF_START)) 889 if (!(ef_flags & PERF_EF_START))
884 event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE; 890 event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
891 else
892 event->hw.state = 0;
885 893
886 /* 894 /*
887 * If group events scheduling transaction was started, 895 * If group events scheduling transaction was started,
@@ -1359,6 +1367,8 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
1359 */ 1367 */
1360 val = 0; 1368 val = 0;
1361 left = local64_read(&event->hw.period_left) - delta; 1369 left = local64_read(&event->hw.period_left) - delta;
1370 if (delta == 0)
1371 left++;
1362 if (period) { 1372 if (period) {
1363 if (left <= 0) { 1373 if (left <= 0) {
1364 left += period; 1374 left += period;
@@ -1422,11 +1432,8 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs)
1422 return regs->nip; 1432 return regs->nip;
1423} 1433}
1424 1434
1425static bool pmc_overflow(unsigned long val) 1435static bool pmc_overflow_power7(unsigned long val)
1426{ 1436{
1427 if ((int)val < 0)
1428 return true;
1429
1430 /* 1437 /*
1431 * Events on POWER7 can roll back if a speculative event doesn't 1438 * Events on POWER7 can roll back if a speculative event doesn't
1432 * eventually complete. Unfortunately in some rare cases they will 1439 * eventually complete. Unfortunately in some rare cases they will
@@ -1438,7 +1445,15 @@ static bool pmc_overflow(unsigned long val)
1438 * PMCs because a user might set a period of less than 256 and we 1445 * PMCs because a user might set a period of less than 256 and we
1439 * don't want to mistakenly reset them. 1446 * don't want to mistakenly reset them.
1440 */ 1447 */
1441 if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256)) 1448 if ((0x80000000 - val) <= 256)
1449 return true;
1450
1451 return false;
1452}
1453
1454static bool pmc_overflow(unsigned long val)
1455{
1456 if ((int)val < 0)
1442 return true; 1457 return true;
1443 1458
1444 return false; 1459 return false;
@@ -1449,11 +1464,11 @@ static bool pmc_overflow(unsigned long val)
1449 */ 1464 */
1450static void perf_event_interrupt(struct pt_regs *regs) 1465static void perf_event_interrupt(struct pt_regs *regs)
1451{ 1466{
1452 int i; 1467 int i, j;
1453 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); 1468 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
1454 struct perf_event *event; 1469 struct perf_event *event;
1455 unsigned long val; 1470 unsigned long val[8];
1456 int found = 0; 1471 int found, active;
1457 int nmi; 1472 int nmi;
1458 1473
1459 if (cpuhw->n_limited) 1474 if (cpuhw->n_limited)
@@ -1468,33 +1483,53 @@ static void perf_event_interrupt(struct pt_regs *regs)
1468 else 1483 else
1469 irq_enter(); 1484 irq_enter();
1470 1485
1471 for (i = 0; i < cpuhw->n_events; ++i) { 1486 /* Read all the PMCs since we'll need them a bunch of times */
1472 event = cpuhw->event[i]; 1487 for (i = 0; i < ppmu->n_counter; ++i)
1473 if (!event->hw.idx || is_limited_pmc(event->hw.idx)) 1488 val[i] = read_pmc(i + 1);
1489
1490 /* Try to find what caused the IRQ */
1491 found = 0;
1492 for (i = 0; i < ppmu->n_counter; ++i) {
1493 if (!pmc_overflow(val[i]))
1474 continue; 1494 continue;
1475 val = read_pmc(event->hw.idx); 1495 if (is_limited_pmc(i + 1))
1476 if ((int)val < 0) { 1496 continue; /* these won't generate IRQs */
1477 /* event has overflowed */ 1497 /*
1478 found = 1; 1498 * We've found one that's overflowed. For active
1479 record_and_restart(event, val, regs); 1499 * counters we need to log this. For inactive
1500 * counters, we need to reset it anyway
1501 */
1502 found = 1;
1503 active = 0;
1504 for (j = 0; j < cpuhw->n_events; ++j) {
1505 event = cpuhw->event[j];
1506 if (event->hw.idx == (i + 1)) {
1507 active = 1;
1508 record_and_restart(event, val[i], regs);
1509 break;
1510 }
1480 } 1511 }
1512 if (!active)
1513 /* reset non active counters that have overflowed */
1514 write_pmc(i + 1, 0);
1481 } 1515 }
1482 1516 if (!found && pvr_version_is(PVR_POWER7)) {
1483 /* 1517 /* check active counters for special buggy p7 overflow */
1484 * In case we didn't find and reset the event that caused 1518 for (i = 0; i < cpuhw->n_events; ++i) {
1485 * the interrupt, scan all events and reset any that are 1519 event = cpuhw->event[i];
1486 * negative, to avoid getting continual interrupts. 1520 if (!event->hw.idx || is_limited_pmc(event->hw.idx))
1487 * Any that we processed in the previous loop will not be negative.
1488 */
1489 if (!found) {
1490 for (i = 0; i < ppmu->n_counter; ++i) {
1491 if (is_limited_pmc(i + 1))
1492 continue; 1521 continue;
1493 val = read_pmc(i + 1); 1522 if (pmc_overflow_power7(val[event->hw.idx - 1])) {
1494 if (pmc_overflow(val)) 1523 /* event has overflowed in a buggy way*/
1495 write_pmc(i + 1, 0); 1524 found = 1;
1525 record_and_restart(event,
1526 val[event->hw.idx - 1],
1527 regs);
1528 }
1496 } 1529 }
1497 } 1530 }
1531 if ((!found) && printk_ratelimit())
1532 printk(KERN_WARNING "Can't find PMC that caused IRQ\n");
1498 1533
1499 /* 1534 /*
1500 * Reset MMCR0 to its normal value. This will set PMXE and 1535 * Reset MMCR0 to its normal value. This will set PMXE and
diff --git a/arch/powerpc/perf/e500-pmu.c b/arch/powerpc/perf/e500-pmu.c
index cb2e2949c8d1..fb664929f5da 100644
--- a/arch/powerpc/perf/e500-pmu.c
+++ b/arch/powerpc/perf/e500-pmu.c
@@ -24,6 +24,8 @@ static int e500_generic_events[] = {
24 [PERF_COUNT_HW_CACHE_MISSES] = 41, /* Data L1 cache reloads */ 24 [PERF_COUNT_HW_CACHE_MISSES] = 41, /* Data L1 cache reloads */
25 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12, 25 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12,
26 [PERF_COUNT_HW_BRANCH_MISSES] = 15, 26 [PERF_COUNT_HW_BRANCH_MISSES] = 15,
27 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 18,
28 [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 19,
27}; 29};
28 30
29#define C(x) PERF_COUNT_HW_CACHE_##x 31#define C(x) PERF_COUNT_HW_CACHE_##x