aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/perf/core-book3s.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-14 10:43:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-14 10:43:11 -0400
commita2c7a54fcc36dc3d0d461e883d9535f8f52f5a3f (patch)
tree3bc7e727e6ebe67d7099b01a1b3cc159840912ca /arch/powerpc/perf/core-book3s.c
parent674825d05001e218afe5a04438683e1e597e14fb (diff)
parente34166ad63eac4d0fa98b4c4ed7a98202a18faef (diff)
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Benjamin Herrenschmidt: "This is mostly bug fixes (some of them regressions, some of them I deemed worth merging now) along with some patches from Li Zhong hooking up the new context tracking stuff (for the new full NO_HZ)" * 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (25 commits) powerpc: Set show_unhandled_signals to 1 by default powerpc/perf: Fix setting of "to" addresses for BHRB powerpc/pmu: Fix order of interpreting BHRB target entries powerpc/perf: Move BHRB code into CONFIG_PPC64 region powerpc: select HAVE_CONTEXT_TRACKING for pSeries powerpc: Use the new schedule_user API on userspace preemption powerpc: Exit user context on notify resume powerpc: Exception hooks for context tracking subsystem powerpc: Syscall hooks for context tracking subsystem powerpc/booke64: Fix kernel hangs at kernel_dbg_exc powerpc: Fix irq_set_affinity() return values powerpc: Provide __bswapdi2 powerpc/powernv: Fix starting of secondary CPUs on OPALv2 and v3 powerpc/powernv: Detect OPAL v3 API version powerpc: Fix MAX_STACK_TRACE_ENTRIES too low warning again powerpc: Make CONFIG_RTAS_PROC depend on CONFIG_PROC_FS powerpc: Bring all threads online prior to migration/hibernation powerpc/rtas_flash: Fix validate_flash buffer overflow issue powerpc/kexec: Fix kexec when using VMX optimised memcpy powerpc: Fix build errors STRICT_MM_TYPECHECKS ...
Diffstat (limited to 'arch/powerpc/perf/core-book3s.c')
-rw-r--r--arch/powerpc/perf/core-book3s.c280
1 files changed, 159 insertions, 121 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index c627843c5b2e..426180b84978 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -13,11 +13,13 @@
13#include <linux/perf_event.h> 13#include <linux/perf_event.h>
14#include <linux/percpu.h> 14#include <linux/percpu.h>
15#include <linux/hardirq.h> 15#include <linux/hardirq.h>
16#include <linux/uaccess.h>
16#include <asm/reg.h> 17#include <asm/reg.h>
17#include <asm/pmc.h> 18#include <asm/pmc.h>
18#include <asm/machdep.h> 19#include <asm/machdep.h>
19#include <asm/firmware.h> 20#include <asm/firmware.h>
20#include <asm/ptrace.h> 21#include <asm/ptrace.h>
22#include <asm/code-patching.h>
21 23
22#define BHRB_MAX_ENTRIES 32 24#define BHRB_MAX_ENTRIES 32
23#define BHRB_TARGET 0x0000000000000002 25#define BHRB_TARGET 0x0000000000000002
@@ -100,6 +102,10 @@ static inline int siar_valid(struct pt_regs *regs)
100 return 1; 102 return 1;
101} 103}
102 104
105static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
106static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
107void power_pmu_flush_branch_stack(void) {}
108static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
103#endif /* CONFIG_PPC32 */ 109#endif /* CONFIG_PPC32 */
104 110
105static bool regs_use_siar(struct pt_regs *regs) 111static bool regs_use_siar(struct pt_regs *regs)
@@ -308,6 +314,159 @@ static inline int siar_valid(struct pt_regs *regs)
308 return 1; 314 return 1;
309} 315}
310 316
317
318/* Reset all possible BHRB entries */
319static void power_pmu_bhrb_reset(void)
320{
321 asm volatile(PPC_CLRBHRB);
322}
323
324static void power_pmu_bhrb_enable(struct perf_event *event)
325{
326 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
327
328 if (!ppmu->bhrb_nr)
329 return;
330
331 /* Clear BHRB if we changed task context to avoid data leaks */
332 if (event->ctx->task && cpuhw->bhrb_context != event->ctx) {
333 power_pmu_bhrb_reset();
334 cpuhw->bhrb_context = event->ctx;
335 }
336 cpuhw->bhrb_users++;
337}
338
339static void power_pmu_bhrb_disable(struct perf_event *event)
340{
341 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
342
343 if (!ppmu->bhrb_nr)
344 return;
345
346 cpuhw->bhrb_users--;
347 WARN_ON_ONCE(cpuhw->bhrb_users < 0);
348
349 if (!cpuhw->disabled && !cpuhw->bhrb_users) {
350 /* BHRB cannot be turned off when other
351 * events are active on the PMU.
352 */
353
354 /* avoid stale pointer */
355 cpuhw->bhrb_context = NULL;
356 }
357}
358
359/* Called from ctxsw to prevent one process's branch entries to
360 * mingle with the other process's entries during context switch.
361 */
362void power_pmu_flush_branch_stack(void)
363{
364 if (ppmu->bhrb_nr)
365 power_pmu_bhrb_reset();
366}
367/* Calculate the to address for a branch */
368static __u64 power_pmu_bhrb_to(u64 addr)
369{
370 unsigned int instr;
371 int ret;
372 __u64 target;
373
374 if (is_kernel_addr(addr))
375 return branch_target((unsigned int *)addr);
376
377 /* Userspace: need copy instruction here then translate it */
378 pagefault_disable();
379 ret = __get_user_inatomic(instr, (unsigned int __user *)addr);
380 if (ret) {
381 pagefault_enable();
382 return 0;
383 }
384 pagefault_enable();
385
386 target = branch_target(&instr);
387 if ((!target) || (instr & BRANCH_ABSOLUTE))
388 return target;
389
390 /* Translate relative branch target from kernel to user address */
391 return target - (unsigned long)&instr + addr;
392}
393
394/* Processing BHRB entries */
395void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
396{
397 u64 val;
398 u64 addr;
399 int r_index, u_index, pred;
400
401 r_index = 0;
402 u_index = 0;
403 while (r_index < ppmu->bhrb_nr) {
404 /* Assembly read function */
405 val = read_bhrb(r_index++);
406 if (!val)
407 /* Terminal marker: End of valid BHRB entries */
408 break;
409 else {
410 addr = val & BHRB_EA;
411 pred = val & BHRB_PREDICTION;
412
413 if (!addr)
414 /* invalid entry */
415 continue;
416
417 /* Branches are read most recent first (ie. mfbhrb 0 is
418 * the most recent branch).
419 * There are two types of valid entries:
420 * 1) a target entry which is the to address of a
421 * computed goto like a blr,bctr,btar. The next
422 * entry read from the bhrb will be branch
423 * corresponding to this target (ie. the actual
424 * blr/bctr/btar instruction).
425 * 2) a from address which is an actual branch. If a
426 * target entry proceeds this, then this is the
427 * matching branch for that target. If this is not
428 * following a target entry, then this is a branch
429 * where the target is given as an immediate field
430 * in the instruction (ie. an i or b form branch).
431 * In this case we need to read the instruction from
432 * memory to determine the target/to address.
433 */
434
435 if (val & BHRB_TARGET) {
436 /* Target branches use two entries
437 * (ie. computed gotos/XL form)
438 */
439 cpuhw->bhrb_entries[u_index].to = addr;
440 cpuhw->bhrb_entries[u_index].mispred = pred;
441 cpuhw->bhrb_entries[u_index].predicted = ~pred;
442
443 /* Get from address in next entry */
444 val = read_bhrb(r_index++);
445 addr = val & BHRB_EA;
446 if (val & BHRB_TARGET) {
447 /* Shouldn't have two targets in a
448 row.. Reset index and try again */
449 r_index--;
450 addr = 0;
451 }
452 cpuhw->bhrb_entries[u_index].from = addr;
453 } else {
454 /* Branches to immediate field
455 (ie I or B form) */
456 cpuhw->bhrb_entries[u_index].from = addr;
457 cpuhw->bhrb_entries[u_index].to =
458 power_pmu_bhrb_to(addr);
459 cpuhw->bhrb_entries[u_index].mispred = pred;
460 cpuhw->bhrb_entries[u_index].predicted = ~pred;
461 }
462 u_index++;
463
464 }
465 }
466 cpuhw->bhrb_stack.nr = u_index;
467 return;
468}
469
311#endif /* CONFIG_PPC64 */ 470#endif /* CONFIG_PPC64 */
312 471
313static void perf_event_interrupt(struct pt_regs *regs); 472static void perf_event_interrupt(struct pt_regs *regs);
@@ -904,47 +1063,6 @@ static int collect_events(struct perf_event *group, int max_count,
904 return n; 1063 return n;
905} 1064}
906 1065
907/* Reset all possible BHRB entries */
908static void power_pmu_bhrb_reset(void)
909{
910 asm volatile(PPC_CLRBHRB);
911}
912
913void power_pmu_bhrb_enable(struct perf_event *event)
914{
915 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
916
917 if (!ppmu->bhrb_nr)
918 return;
919
920 /* Clear BHRB if we changed task context to avoid data leaks */
921 if (event->ctx->task && cpuhw->bhrb_context != event->ctx) {
922 power_pmu_bhrb_reset();
923 cpuhw->bhrb_context = event->ctx;
924 }
925 cpuhw->bhrb_users++;
926}
927
928void power_pmu_bhrb_disable(struct perf_event *event)
929{
930 struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
931
932 if (!ppmu->bhrb_nr)
933 return;
934
935 cpuhw->bhrb_users--;
936 WARN_ON_ONCE(cpuhw->bhrb_users < 0);
937
938 if (!cpuhw->disabled && !cpuhw->bhrb_users) {
939 /* BHRB cannot be turned off when other
940 * events are active on the PMU.
941 */
942
943 /* avoid stale pointer */
944 cpuhw->bhrb_context = NULL;
945 }
946}
947
948/* 1066/*
949 * Add a event to the PMU. 1067 * Add a event to the PMU.
950 * If all events are not already frozen, then we disable and 1068 * If all events are not already frozen, then we disable and
@@ -1180,15 +1298,6 @@ int power_pmu_commit_txn(struct pmu *pmu)
1180 return 0; 1298 return 0;
1181} 1299}
1182 1300
1183/* Called from ctxsw to prevent one process's branch entries to
1184 * mingle with the other process's entries during context switch.
1185 */
1186void power_pmu_flush_branch_stack(void)
1187{
1188 if (ppmu->bhrb_nr)
1189 power_pmu_bhrb_reset();
1190}
1191
1192/* 1301/*
1193 * Return 1 if we might be able to put event on a limited PMC, 1302 * Return 1 if we might be able to put event on a limited PMC,
1194 * or 0 if not. 1303 * or 0 if not.
@@ -1458,77 +1567,6 @@ struct pmu power_pmu = {
1458 .flush_branch_stack = power_pmu_flush_branch_stack, 1567 .flush_branch_stack = power_pmu_flush_branch_stack,
1459}; 1568};
1460 1569
1461/* Processing BHRB entries */
1462void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
1463{
1464 u64 val;
1465 u64 addr;
1466 int r_index, u_index, target, pred;
1467
1468 r_index = 0;
1469 u_index = 0;
1470 while (r_index < ppmu->bhrb_nr) {
1471 /* Assembly read function */
1472 val = read_bhrb(r_index);
1473
1474 /* Terminal marker: End of valid BHRB entries */
1475 if (val == 0) {
1476 break;
1477 } else {
1478 /* BHRB field break up */
1479 addr = val & BHRB_EA;
1480 pred = val & BHRB_PREDICTION;
1481 target = val & BHRB_TARGET;
1482
1483 /* Probable Missed entry: Not applicable for POWER8 */
1484 if ((addr == 0) && (target == 0) && (pred == 1)) {
1485 r_index++;
1486 continue;
1487 }
1488
1489 /* Real Missed entry: Power8 based missed entry */
1490 if ((addr == 0) && (target == 1) && (pred == 1)) {
1491 r_index++;
1492 continue;
1493 }
1494
1495 /* Reserved condition: Not a valid entry */
1496 if ((addr == 0) && (target == 1) && (pred == 0)) {
1497 r_index++;
1498 continue;
1499 }
1500
1501 /* Is a target address */
1502 if (val & BHRB_TARGET) {
1503 /* First address cannot be a target address */
1504 if (r_index == 0) {
1505 r_index++;
1506 continue;
1507 }
1508
1509 /* Update target address for the previous entry */
1510 cpuhw->bhrb_entries[u_index - 1].to = addr;
1511 cpuhw->bhrb_entries[u_index - 1].mispred = pred;
1512 cpuhw->bhrb_entries[u_index - 1].predicted = ~pred;
1513
1514 /* Dont increment u_index */
1515 r_index++;
1516 } else {
1517 /* Update address, flags for current entry */
1518 cpuhw->bhrb_entries[u_index].from = addr;
1519 cpuhw->bhrb_entries[u_index].mispred = pred;
1520 cpuhw->bhrb_entries[u_index].predicted = ~pred;
1521
1522 /* Successfully popullated one entry */
1523 u_index++;
1524 r_index++;
1525 }
1526 }
1527 }
1528 cpuhw->bhrb_stack.nr = u_index;
1529 return;
1530}
1531
1532/* 1570/*
1533 * A counter has overflowed; update its count and record 1571 * A counter has overflowed; update its count and record
1534 * things if requested. Note that interrupts are hard-disabled 1572 * things if requested. Note that interrupts are hard-disabled