aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/perf_event_p4.c126
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/*
672static 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 */ 685static 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
721static int p4_get_escr_idx(unsigned int addr) 734static 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
733static int p4_next_cntr(int thread, unsigned long *used_mask, 747static 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,
747static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) 761static 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;