aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-08-18 02:06:09 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-19 02:26:21 -0400
commit035ea28dde1802ad4cc570976da34f8b7c2ed515 (patch)
treed3f68220b5fab2a9aa9541dafd662759d6f9457f /arch/sparc/kernel
parent7a37a0b8f8df0872932cf8373b21b5e14a92a794 (diff)
sparc64: Add SPARC-T4 perf event support.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r--arch/sparc/kernel/perf_event.c189
1 files changed, 187 insertions, 2 deletions
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 64415922a28f..18853705282b 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -53,8 +53,8 @@
53 * normal code. 53 * normal code.
54 */ 54 */
55 55
56#define MAX_HWEVENTS 2 56#define MAX_HWEVENTS 4
57#define MAX_PCRS 1 57#define MAX_PCRS 4
58#define MAX_PERIOD ((1UL << 32) - 1) 58#define MAX_PERIOD ((1UL << 32) - 1)
59 59
60#define PIC_UPPER_INDEX 0 60#define PIC_UPPER_INDEX 0
@@ -597,6 +597,187 @@ static const struct sparc_pmu niagara2_pmu = {
597 .num_pic_regs = 1, 597 .num_pic_regs = 1,
598}; 598};
599 599
600static const struct perf_event_map niagara4_perfmon_event_map[] = {
601 [PERF_COUNT_HW_CPU_CYCLES] = { (26 << 6) },
602 [PERF_COUNT_HW_INSTRUCTIONS] = { (3 << 6) | 0x3f },
603 [PERF_COUNT_HW_CACHE_REFERENCES] = { (3 << 6) | 0x04 },
604 [PERF_COUNT_HW_CACHE_MISSES] = { (16 << 6) | 0x07 },
605 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { (4 << 6) | 0x01 },
606 [PERF_COUNT_HW_BRANCH_MISSES] = { (25 << 6) | 0x0f },
607};
608
609static const struct perf_event_map *niagara4_event_map(int event_id)
610{
611 return &niagara4_perfmon_event_map[event_id];
612}
613
614static const cache_map_t niagara4_cache_map = {
615[C(L1D)] = {
616 [C(OP_READ)] = {
617 [C(RESULT_ACCESS)] = { (3 << 6) | 0x04 },
618 [C(RESULT_MISS)] = { (16 << 6) | 0x07 },
619 },
620 [C(OP_WRITE)] = {
621 [C(RESULT_ACCESS)] = { (3 << 6) | 0x08 },
622 [C(RESULT_MISS)] = { (16 << 6) | 0x07 },
623 },
624 [C(OP_PREFETCH)] = {
625 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
626 [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
627 },
628},
629[C(L1I)] = {
630 [C(OP_READ)] = {
631 [C(RESULT_ACCESS)] = { (3 << 6) | 0x3f },
632 [C(RESULT_MISS)] = { (11 << 6) | 0x03 },
633 },
634 [ C(OP_WRITE) ] = {
635 [ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE },
636 [ C(RESULT_MISS) ] = { CACHE_OP_NONSENSE },
637 },
638 [ C(OP_PREFETCH) ] = {
639 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
640 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
641 },
642},
643[C(LL)] = {
644 [C(OP_READ)] = {
645 [C(RESULT_ACCESS)] = { (3 << 6) | 0x04 },
646 [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
647 },
648 [C(OP_WRITE)] = {
649 [C(RESULT_ACCESS)] = { (3 << 6) | 0x08 },
650 [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
651 },
652 [C(OP_PREFETCH)] = {
653 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
654 [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
655 },
656},
657[C(DTLB)] = {
658 [C(OP_READ)] = {
659 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
660 [C(RESULT_MISS)] = { (17 << 6) | 0x3f },
661 },
662 [ C(OP_WRITE) ] = {
663 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
664 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
665 },
666 [ C(OP_PREFETCH) ] = {
667 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
668 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
669 },
670},
671[C(ITLB)] = {
672 [C(OP_READ)] = {
673 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
674 [C(RESULT_MISS)] = { (6 << 6) | 0x3f },
675 },
676 [ C(OP_WRITE) ] = {
677 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
678 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
679 },
680 [ C(OP_PREFETCH) ] = {
681 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
682 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
683 },
684},
685[C(BPU)] = {
686 [C(OP_READ)] = {
687 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
688 [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
689 },
690 [ C(OP_WRITE) ] = {
691 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
692 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
693 },
694 [ C(OP_PREFETCH) ] = {
695 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
696 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
697 },
698},
699[C(NODE)] = {
700 [C(OP_READ)] = {
701 [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
702 [C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
703 },
704 [ C(OP_WRITE) ] = {
705 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
706 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
707 },
708 [ C(OP_PREFETCH) ] = {
709 [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
710 [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED },
711 },
712},
713};
714
715static u32 sparc_vt_read_pmc(int idx)
716{
717 u64 val = pcr_ops->read_pic(idx);
718
719 return val & 0xffffffff;
720}
721
722static void sparc_vt_write_pmc(int idx, u64 val)
723{
724 u64 pcr;
725
726 /* There seems to be an internal latch on the overflow event
727 * on SPARC-T4 that prevents it from triggering unless you
728 * update the PIC exactly as we do here. The requirement
729 * seems to be that you have to turn off event counting in the
730 * PCR around the PIC update.
731 *
732 * For example, after the following sequence:
733 *
734 * 1) set PIC to -1
735 * 2) enable event counting and overflow reporting in PCR
736 * 3) overflow triggers, softint 15 handler invoked
737 * 4) clear OV bit in PCR
738 * 5) write PIC to -1
739 *
740 * a subsequent overflow event will not trigger. This
741 * sequence works on SPARC-T3 and previous chips.
742 */
743 pcr = pcr_ops->read_pcr(idx);
744 pcr_ops->write_pcr(idx, PCR_N4_PICNPT);
745
746 pcr_ops->write_pic(idx, val & 0xffffffff);
747
748 pcr_ops->write_pcr(idx, pcr);
749}
750
751static const struct sparc_pmu niagara4_pmu = {
752 .event_map = niagara4_event_map,
753 .cache_map = &niagara4_cache_map,
754 .max_events = ARRAY_SIZE(niagara4_perfmon_event_map),
755 .read_pmc = sparc_vt_read_pmc,
756 .write_pmc = sparc_vt_write_pmc,
757 .upper_shift = 5,
758 .lower_shift = 5,
759 .event_mask = 0x7ff,
760 .user_bit = PCR_N4_UTRACE,
761 .priv_bit = PCR_N4_STRACE,
762
763 /* We explicitly don't support hypervisor tracing. The T4
764 * generates the overflow event for precise events via a trap
765 * which will not be generated (ie. it's completely lost) if
766 * we happen to be in the hypervisor when the event triggers.
767 * Essentially, the overflow event reporting is completely
768 * unusable when you have hypervisor mode tracing enabled.
769 */
770 .hv_bit = 0,
771
772 .irq_bit = PCR_N4_TOE,
773 .upper_nop = 0,
774 .lower_nop = 0,
775 .flags = 0,
776 .max_hw_events = 4,
777 .num_pcrs = 4,
778 .num_pic_regs = 4,
779};
780
600static const struct sparc_pmu *sparc_pmu __read_mostly; 781static const struct sparc_pmu *sparc_pmu __read_mostly;
601 782
602static u64 event_encoding(u64 event_id, int idx) 783static u64 event_encoding(u64 event_id, int idx)
@@ -1465,6 +1646,10 @@ static bool __init supported_pmu(void)
1465 sparc_pmu = &niagara2_pmu; 1646 sparc_pmu = &niagara2_pmu;
1466 return true; 1647 return true;
1467 } 1648 }
1649 if (!strcmp(sparc_pmu_type, "niagara4")) {
1650 sparc_pmu = &niagara4_pmu;
1651 return true;
1652 }
1468 return false; 1653 return false;
1469} 1654}
1470 1655