diff options
author | David S. Miller <davem@davemloft.net> | 2012-08-18 02:06:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-08-19 02:26:21 -0400 |
commit | 035ea28dde1802ad4cc570976da34f8b7c2ed515 (patch) | |
tree | d3f68220b5fab2a9aa9541dafd662759d6f9457f /arch/sparc/kernel | |
parent | 7a37a0b8f8df0872932cf8373b21b5e14a92a794 (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.c | 189 |
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 | ||
600 | static 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 | |||
609 | static const struct perf_event_map *niagara4_event_map(int event_id) | ||
610 | { | ||
611 | return &niagara4_perfmon_event_map[event_id]; | ||
612 | } | ||
613 | |||
614 | static 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 | |||
715 | static u32 sparc_vt_read_pmc(int idx) | ||
716 | { | ||
717 | u64 val = pcr_ops->read_pic(idx); | ||
718 | |||
719 | return val & 0xffffffff; | ||
720 | } | ||
721 | |||
722 | static 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 | |||
751 | static 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 | |||
600 | static const struct sparc_pmu *sparc_pmu __read_mostly; | 781 | static const struct sparc_pmu *sparc_pmu __read_mostly; |
601 | 782 | ||
602 | static u64 event_encoding(u64 event_id, int idx) | 783 | static 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 | ||