aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@openvz.org>2010-05-12 13:42:42 -0400
committerIngo Molnar <mingo@elte.hu>2010-05-13 02:51:13 -0400
commit720019908fd5a1bb442bb0a35a6027ba21864d25 (patch)
treeb6a637a752f67061403664ec28c5c587c544b01c
parent975fc2d5f20b071576e7c9920c4f1a1eae80f88d (diff)
x86, perf: P4 PMU -- use hash for p4_get_escr_idx()
Linear search over all p4 MSRs should be fine if only we would not use it in events scheduling routine which is pretty time critical. Lets use hashes. It should speed scheduling up significantly. v2: Steven proposed to use more gentle approach than issue BUG on error, so we use WARN_ONCE now Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Lin Ming <ming.m.lin@intel.com> LKML-Reference: <20100512174242.GA5190@lenovo> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-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;