diff options
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 126 |
1 files changed, 71 insertions, 55 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index a603930271f3..cb875b1e2e87 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c | |||
@@ -668,66 +668,80 @@ static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu) | |||
668 | } | 668 | } |
669 | } | 669 | } |
670 | 670 | ||
671 | /* ESCRs are not sequential in memory so we need a map */ | 671 | /* |
672 | static const unsigned int p4_escr_map[ARCH_P4_TOTAL_ESCR] = { | 672 | * ESCR address hashing is tricky, ESCRs are not sequential |
673 | MSR_P4_ALF_ESCR0, /* 0 */ | 673 | * in memory but all starts from MSR_P4_BSU_ESCR0 (0x03e0) and |
674 | MSR_P4_ALF_ESCR1, /* 1 */ | 674 | * the metric between any ESCRs is laid in range [0xa0,0xe1] |
675 | MSR_P4_BPU_ESCR0, /* 2 */ | 675 | * |
676 | MSR_P4_BPU_ESCR1, /* 3 */ | 676 | * so we make ~70% filled hashtable |
677 | MSR_P4_BSU_ESCR0, /* 4 */ | 677 | */ |
678 | MSR_P4_BSU_ESCR1, /* 5 */ | 678 | |
679 | MSR_P4_CRU_ESCR0, /* 6 */ | 679 | #define P4_ESCR_MSR_BASE 0x000003a0 |
680 | MSR_P4_CRU_ESCR1, /* 7 */ | 680 | #define P4_ESCR_MSR_MAX 0x000003e1 |
681 | MSR_P4_CRU_ESCR2, /* 8 */ | 681 | #define P4_ESCR_MSR_TABLE_SIZE (P4_ESCR_MSR_MAX - P4_ESCR_MSR_BASE + 1) |
682 | MSR_P4_CRU_ESCR3, /* 9 */ | 682 | #define P4_ESCR_MSR_IDX(msr) (msr - P4_ESCR_MSR_BASE) |
683 | MSR_P4_CRU_ESCR4, /* 10 */ | 683 | #define P4_ESCR_MSR_TABLE_ENTRY(msr) [P4_ESCR_MSR_IDX(msr)] = msr |
684 | MSR_P4_CRU_ESCR5, /* 11 */ | 684 | |
685 | MSR_P4_DAC_ESCR0, /* 12 */ | 685 | static const unsigned int p4_escr_table[P4_ESCR_MSR_TABLE_SIZE] = { |
686 | MSR_P4_DAC_ESCR1, /* 13 */ | 686 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR0), |
687 | MSR_P4_FIRM_ESCR0, /* 14 */ | 687 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR1), |
688 | MSR_P4_FIRM_ESCR1, /* 15 */ | 688 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR0), |
689 | MSR_P4_FLAME_ESCR0, /* 16 */ | 689 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR1), |
690 | MSR_P4_FLAME_ESCR1, /* 17 */ | 690 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR0), |
691 | MSR_P4_FSB_ESCR0, /* 18 */ | 691 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR1), |
692 | MSR_P4_FSB_ESCR1, /* 19 */ | 692 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR0), |
693 | MSR_P4_IQ_ESCR0, /* 20 */ | 693 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR1), |
694 | MSR_P4_IQ_ESCR1, /* 21 */ | 694 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR2), |
695 | MSR_P4_IS_ESCR0, /* 22 */ | 695 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR3), |
696 | MSR_P4_IS_ESCR1, /* 23 */ | 696 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR4), |
697 | MSR_P4_ITLB_ESCR0, /* 24 */ | 697 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR5), |
698 | MSR_P4_ITLB_ESCR1, /* 25 */ | 698 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR0), |
699 | MSR_P4_IX_ESCR0, /* 26 */ | 699 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR1), |
700 | MSR_P4_IX_ESCR1, /* 27 */ | 700 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR0), |
701 | MSR_P4_MOB_ESCR0, /* 28 */ | 701 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR1), |
702 | MSR_P4_MOB_ESCR1, /* 29 */ | 702 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR0), |
703 | MSR_P4_MS_ESCR0, /* 30 */ | 703 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR1), |
704 | MSR_P4_MS_ESCR1, /* 31 */ | 704 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR0), |
705 | MSR_P4_PMH_ESCR0, /* 32 */ | 705 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR1), |
706 | MSR_P4_PMH_ESCR1, /* 33 */ | 706 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR0), |
707 | MSR_P4_RAT_ESCR0, /* 34 */ | 707 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR1), |
708 | MSR_P4_RAT_ESCR1, /* 35 */ | 708 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR0), |
709 | MSR_P4_SAAT_ESCR0, /* 36 */ | 709 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR1), |
710 | MSR_P4_SAAT_ESCR1, /* 37 */ | 710 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR0), |
711 | MSR_P4_SSU_ESCR0, /* 38 */ | 711 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR1), |
712 | MSR_P4_SSU_ESCR1, /* 39 */ | 712 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR0), |
713 | MSR_P4_TBPU_ESCR0, /* 40 */ | 713 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR1), |
714 | MSR_P4_TBPU_ESCR1, /* 41 */ | 714 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR0), |
715 | MSR_P4_TC_ESCR0, /* 42 */ | 715 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR1), |
716 | MSR_P4_TC_ESCR1, /* 43 */ | 716 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR0), |
717 | MSR_P4_U2L_ESCR0, /* 44 */ | 717 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR1), |
718 | MSR_P4_U2L_ESCR1, /* 45 */ | 718 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR0), |
719 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR1), | ||
720 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR0), | ||
721 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR1), | ||
722 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR0), | ||
723 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR1), | ||
724 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR0), | ||
725 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR1), | ||
726 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR0), | ||
727 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR1), | ||
728 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR0), | ||
729 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR1), | ||
730 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR0), | ||
731 | P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR1), | ||
719 | }; | 732 | }; |
720 | 733 | ||
721 | static int p4_get_escr_idx(unsigned int addr) | 734 | static int p4_get_escr_idx(unsigned int addr) |
722 | { | 735 | { |
723 | unsigned int i; | 736 | unsigned int idx = P4_ESCR_MSR_IDX(addr); |
724 | 737 | ||
725 | for (i = 0; i < ARRAY_SIZE(p4_escr_map); i++) { | 738 | if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE || |
726 | if (addr == p4_escr_map[i]) | 739 | !p4_escr_table[idx])) { |
727 | return i; | 740 | WARN_ONCE(1, "P4 PMU: Wrong address passed: %x\n", addr); |
741 | return -1; | ||
728 | } | 742 | } |
729 | 743 | ||
730 | return -1; | 744 | return idx; |
731 | } | 745 | } |
732 | 746 | ||
733 | static int p4_next_cntr(int thread, unsigned long *used_mask, | 747 | static int p4_next_cntr(int thread, unsigned long *used_mask, |
@@ -747,7 +761,7 @@ static int p4_next_cntr(int thread, unsigned long *used_mask, | |||
747 | static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) | 761 | static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) |
748 | { | 762 | { |
749 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 763 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
750 | unsigned long escr_mask[BITS_TO_LONGS(ARCH_P4_TOTAL_ESCR)]; | 764 | unsigned long escr_mask[BITS_TO_LONGS(P4_ESCR_MSR_TABLE_SIZE)]; |
751 | int cpu = raw_smp_processor_id(); | 765 | int cpu = raw_smp_processor_id(); |
752 | struct hw_perf_event *hwc; | 766 | struct hw_perf_event *hwc; |
753 | struct p4_event_bind *bind; | 767 | struct p4_event_bind *bind; |
@@ -755,7 +769,7 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign | |||
755 | int cntr_idx, escr_idx; | 769 | int cntr_idx, escr_idx; |
756 | 770 | ||
757 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); | 771 | bitmap_zero(used_mask, X86_PMC_IDX_MAX); |
758 | bitmap_zero(escr_mask, ARCH_P4_TOTAL_ESCR); | 772 | bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE); |
759 | 773 | ||
760 | for (i = 0, num = n; i < n; i++, num--) { | 774 | for (i = 0, num = n; i < n; i++, num--) { |
761 | 775 | ||
@@ -763,6 +777,8 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign | |||
763 | thread = p4_ht_thread(cpu); | 777 | thread = p4_ht_thread(cpu); |
764 | bind = p4_config_get_bind(hwc->config); | 778 | bind = p4_config_get_bind(hwc->config); |
765 | escr_idx = p4_get_escr_idx(bind->escr_msr[thread]); | 779 | escr_idx = p4_get_escr_idx(bind->escr_msr[thread]); |
780 | if (unlikely(escr_idx == -1)) | ||
781 | goto done; | ||
766 | 782 | ||
767 | if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) { | 783 | if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) { |
768 | cntr_idx = hwc->idx; | 784 | cntr_idx = hwc->idx; |