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; |
