aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/perf_counter.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 1910f39ff19a..c7cc6eac14ec 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -84,6 +84,14 @@ static u64 p6_pmu_event_map(int event)
84 return p6_perfmon_event_map[event]; 84 return p6_perfmon_event_map[event];
85} 85}
86 86
87/*
88 * Counter setting that is specified not to count anything.
89 * We use this to effectively disable a counter.
90 *
91 * L2_RQSTS with 0 MESI unit mask.
92 */
93#define P6_NOP_COUNTER 0x0000002EULL
94
87static u64 p6_pmu_raw_event(u64 event) 95static u64 p6_pmu_raw_event(u64 event)
88{ 96{
89#define P6_EVNTSEL_EVENT_MASK 0x000000FFULL 97#define P6_EVNTSEL_EVENT_MASK 0x000000FFULL
@@ -704,6 +712,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
704{ 712{
705 struct perf_counter_attr *attr = &counter->attr; 713 struct perf_counter_attr *attr = &counter->attr;
706 struct hw_perf_counter *hwc = &counter->hw; 714 struct hw_perf_counter *hwc = &counter->hw;
715 u64 config;
707 int err; 716 int err;
708 717
709 if (!x86_pmu_initialized()) 718 if (!x86_pmu_initialized())
@@ -756,10 +765,19 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
756 765
757 if (attr->config >= x86_pmu.max_events) 766 if (attr->config >= x86_pmu.max_events)
758 return -EINVAL; 767 return -EINVAL;
768
759 /* 769 /*
760 * The generic map: 770 * The generic map:
761 */ 771 */
762 hwc->config |= x86_pmu.event_map(attr->config); 772 config = x86_pmu.event_map(attr->config);
773
774 if (config == 0)
775 return -ENOENT;
776
777 if (config == -1LL)
778 return -EINVAL;
779
780 hwc->config |= config;
763 781
764 return 0; 782 return 0;
765} 783}
@@ -767,7 +785,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
767static void p6_pmu_disable_all(void) 785static void p6_pmu_disable_all(void)
768{ 786{
769 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); 787 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
770 unsigned long val; 788 u64 val;
771 789
772 if (!cpuc->enabled) 790 if (!cpuc->enabled)
773 return; 791 return;
@@ -917,10 +935,10 @@ static inline void
917p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) 935p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
918{ 936{
919 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); 937 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
920 unsigned long val = ARCH_PERFMON_EVENTSEL0_ENABLE; 938 u64 val = P6_NOP_COUNTER;
921 939
922 if (!cpuc->enabled) 940 if (cpuc->enabled)
923 val = 0; 941 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
924 942
925 (void)checking_wrmsrl(hwc->config_base + idx, val); 943 (void)checking_wrmsrl(hwc->config_base + idx, val);
926} 944}