GNU Linux-libre 4.14.290-gnu1
[releases.git] / arch / x86 / events / msr.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/perf_event.h>
3 #include <linux/nospec.h>
4 #include <asm/intel-family.h>
5
6 enum perf_msr_id {
7         PERF_MSR_TSC                    = 0,
8         PERF_MSR_APERF                  = 1,
9         PERF_MSR_MPERF                  = 2,
10         PERF_MSR_PPERF                  = 3,
11         PERF_MSR_SMI                    = 4,
12         PERF_MSR_PTSC                   = 5,
13         PERF_MSR_IRPERF                 = 6,
14
15         PERF_MSR_EVENT_MAX,
16 };
17
18 static bool test_aperfmperf(int idx)
19 {
20         return boot_cpu_has(X86_FEATURE_APERFMPERF);
21 }
22
23 static bool test_ptsc(int idx)
24 {
25         return boot_cpu_has(X86_FEATURE_PTSC);
26 }
27
28 static bool test_irperf(int idx)
29 {
30         return boot_cpu_has(X86_FEATURE_IRPERF);
31 }
32
33 static bool test_intel(int idx)
34 {
35         if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
36             boot_cpu_data.x86 != 6)
37                 return false;
38
39         switch (boot_cpu_data.x86_model) {
40         case INTEL_FAM6_NEHALEM:
41         case INTEL_FAM6_NEHALEM_G:
42         case INTEL_FAM6_NEHALEM_EP:
43         case INTEL_FAM6_NEHALEM_EX:
44
45         case INTEL_FAM6_WESTMERE:
46         case INTEL_FAM6_WESTMERE_EP:
47         case INTEL_FAM6_WESTMERE_EX:
48
49         case INTEL_FAM6_SANDYBRIDGE:
50         case INTEL_FAM6_SANDYBRIDGE_X:
51
52         case INTEL_FAM6_IVYBRIDGE:
53         case INTEL_FAM6_IVYBRIDGE_X:
54
55         case INTEL_FAM6_HASWELL_CORE:
56         case INTEL_FAM6_HASWELL_X:
57         case INTEL_FAM6_HASWELL_ULT:
58         case INTEL_FAM6_HASWELL_GT3E:
59
60         case INTEL_FAM6_BROADWELL_CORE:
61         case INTEL_FAM6_BROADWELL_XEON_D:
62         case INTEL_FAM6_BROADWELL_GT3E:
63         case INTEL_FAM6_BROADWELL_X:
64
65         case INTEL_FAM6_ATOM_SILVERMONT:
66         case INTEL_FAM6_ATOM_SILVERMONT_X:
67         case INTEL_FAM6_ATOM_AIRMONT:
68
69         case INTEL_FAM6_ATOM_GOLDMONT:
70         case INTEL_FAM6_ATOM_GOLDMONT_X:
71
72         case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
73
74         case INTEL_FAM6_XEON_PHI_KNL:
75         case INTEL_FAM6_XEON_PHI_KNM:
76                 if (idx == PERF_MSR_SMI)
77                         return true;
78                 break;
79
80         case INTEL_FAM6_SKYLAKE_MOBILE:
81         case INTEL_FAM6_SKYLAKE_DESKTOP:
82         case INTEL_FAM6_SKYLAKE_X:
83         case INTEL_FAM6_KABYLAKE_MOBILE:
84         case INTEL_FAM6_KABYLAKE_DESKTOP:
85                 if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
86                         return true;
87                 break;
88         }
89
90         return false;
91 }
92
93 struct perf_msr {
94         u64     msr;
95         struct  perf_pmu_events_attr *attr;
96         bool    (*test)(int idx);
97 };
98
99 PMU_EVENT_ATTR_STRING(tsc,    evattr_tsc,    "event=0x00");
100 PMU_EVENT_ATTR_STRING(aperf,  evattr_aperf,  "event=0x01");
101 PMU_EVENT_ATTR_STRING(mperf,  evattr_mperf,  "event=0x02");
102 PMU_EVENT_ATTR_STRING(pperf,  evattr_pperf,  "event=0x03");
103 PMU_EVENT_ATTR_STRING(smi,    evattr_smi,    "event=0x04");
104 PMU_EVENT_ATTR_STRING(ptsc,   evattr_ptsc,   "event=0x05");
105 PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
106
107 static struct perf_msr msr[] = {
108         [PERF_MSR_TSC]    = { 0,                &evattr_tsc,    NULL,            },
109         [PERF_MSR_APERF]  = { MSR_IA32_APERF,   &evattr_aperf,  test_aperfmperf, },
110         [PERF_MSR_MPERF]  = { MSR_IA32_MPERF,   &evattr_mperf,  test_aperfmperf, },
111         [PERF_MSR_PPERF]  = { MSR_PPERF,        &evattr_pperf,  test_intel,      },
112         [PERF_MSR_SMI]    = { MSR_SMI_COUNT,    &evattr_smi,    test_intel,      },
113         [PERF_MSR_PTSC]   = { MSR_F15H_PTSC,    &evattr_ptsc,   test_ptsc,       },
114         [PERF_MSR_IRPERF] = { MSR_F17H_IRPERF,  &evattr_irperf, test_irperf,     },
115 };
116
117 static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
118         NULL,
119 };
120
121 static struct attribute_group events_attr_group = {
122         .name = "events",
123         .attrs = events_attrs,
124 };
125
126 PMU_FORMAT_ATTR(event, "config:0-63");
127 static struct attribute *format_attrs[] = {
128         &format_attr_event.attr,
129         NULL,
130 };
131 static struct attribute_group format_attr_group = {
132         .name = "format",
133         .attrs = format_attrs,
134 };
135
136 static const struct attribute_group *attr_groups[] = {
137         &events_attr_group,
138         &format_attr_group,
139         NULL,
140 };
141
142 static int msr_event_init(struct perf_event *event)
143 {
144         u64 cfg = event->attr.config;
145
146         if (event->attr.type != event->pmu->type)
147                 return -ENOENT;
148
149         /* unsupported modes and filters */
150         if (event->attr.exclude_user   ||
151             event->attr.exclude_kernel ||
152             event->attr.exclude_hv     ||
153             event->attr.exclude_idle   ||
154             event->attr.exclude_host   ||
155             event->attr.exclude_guest  ||
156             event->attr.sample_period) /* no sampling */
157                 return -EINVAL;
158
159         if (cfg >= PERF_MSR_EVENT_MAX)
160                 return -EINVAL;
161
162         cfg = array_index_nospec((unsigned long)cfg, PERF_MSR_EVENT_MAX);
163
164         if (!msr[cfg].attr)
165                 return -EINVAL;
166
167         event->hw.idx = -1;
168         event->hw.event_base = msr[cfg].msr;
169         event->hw.config = cfg;
170
171         return 0;
172 }
173
174 static inline u64 msr_read_counter(struct perf_event *event)
175 {
176         u64 now;
177
178         if (event->hw.event_base)
179                 rdmsrl(event->hw.event_base, now);
180         else
181                 rdtscll(now);
182
183         return now;
184 }
185 static void msr_event_update(struct perf_event *event)
186 {
187         u64 prev, now;
188         s64 delta;
189
190         /* Careful, an NMI might modify the previous event value. */
191 again:
192         prev = local64_read(&event->hw.prev_count);
193         now = msr_read_counter(event);
194
195         if (local64_cmpxchg(&event->hw.prev_count, prev, now) != prev)
196                 goto again;
197
198         delta = now - prev;
199         if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
200                 delta = sign_extend64(delta, 31);
201
202         local64_add(delta, &event->count);
203 }
204
205 static void msr_event_start(struct perf_event *event, int flags)
206 {
207         u64 now;
208
209         now = msr_read_counter(event);
210         local64_set(&event->hw.prev_count, now);
211 }
212
213 static void msr_event_stop(struct perf_event *event, int flags)
214 {
215         msr_event_update(event);
216 }
217
218 static void msr_event_del(struct perf_event *event, int flags)
219 {
220         msr_event_stop(event, PERF_EF_UPDATE);
221 }
222
223 static int msr_event_add(struct perf_event *event, int flags)
224 {
225         if (flags & PERF_EF_START)
226                 msr_event_start(event, flags);
227
228         return 0;
229 }
230
231 static struct pmu pmu_msr = {
232         .task_ctx_nr    = perf_sw_context,
233         .attr_groups    = attr_groups,
234         .event_init     = msr_event_init,
235         .add            = msr_event_add,
236         .del            = msr_event_del,
237         .start          = msr_event_start,
238         .stop           = msr_event_stop,
239         .read           = msr_event_update,
240         .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
241 };
242
243 static int __init msr_init(void)
244 {
245         int i, j = 0;
246
247         if (!boot_cpu_has(X86_FEATURE_TSC)) {
248                 pr_cont("no MSR PMU driver.\n");
249                 return 0;
250         }
251
252         /* Probe the MSRs. */
253         for (i = PERF_MSR_TSC + 1; i < PERF_MSR_EVENT_MAX; i++) {
254                 u64 val;
255
256                 /*
257                  * Virt sucks arse; you cannot tell if a R/O MSR is present :/
258                  */
259                 if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
260                         msr[i].attr = NULL;
261         }
262
263         /* List remaining MSRs in the sysfs attrs. */
264         for (i = 0; i < PERF_MSR_EVENT_MAX; i++) {
265                 if (msr[i].attr)
266                         events_attrs[j++] = &msr[i].attr->attr.attr;
267         }
268         events_attrs[j] = NULL;
269
270         perf_pmu_register(&pmu_msr, "msr", -1);
271
272         return 0;
273 }
274 device_initcall(msr_init);