GNU Linux-libre 4.4.288-gnu1
[releases.git] / arch / x86 / kernel / cpu / perf_event_msr.c
1 #include <linux/perf_event.h>
2 #include <linux/nospec.h>
3
4 enum perf_msr_id {
5         PERF_MSR_TSC                    = 0,
6         PERF_MSR_APERF                  = 1,
7         PERF_MSR_MPERF                  = 2,
8         PERF_MSR_PPERF                  = 3,
9         PERF_MSR_SMI                    = 4,
10
11         PERF_MSR_EVENT_MAX,
12 };
13
14 static bool test_aperfmperf(int idx)
15 {
16         return boot_cpu_has(X86_FEATURE_APERFMPERF);
17 }
18
19 static bool test_intel(int idx)
20 {
21         if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
22             boot_cpu_data.x86 != 6)
23                 return false;
24
25         switch (boot_cpu_data.x86_model) {
26         case 30: /* 45nm Nehalem    */
27         case 26: /* 45nm Nehalem-EP */
28         case 46: /* 45nm Nehalem-EX */
29
30         case 37: /* 32nm Westmere    */
31         case 44: /* 32nm Westmere-EP */
32         case 47: /* 32nm Westmere-EX */
33
34         case 42: /* 32nm SandyBridge         */
35         case 45: /* 32nm SandyBridge-E/EN/EP */
36
37         case 58: /* 22nm IvyBridge       */
38         case 62: /* 22nm IvyBridge-EP/EX */
39
40         case 60: /* 22nm Haswell Core */
41         case 63: /* 22nm Haswell Server */
42         case 69: /* 22nm Haswell ULT */
43         case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
44
45         case 61: /* 14nm Broadwell Core-M */
46         case 86: /* 14nm Broadwell Xeon D */
47         case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
48         case 79: /* 14nm Broadwell Server */
49
50         case 55: /* 22nm Atom "Silvermont"                */
51         case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
52         case 76: /* 14nm Atom "Airmont"                   */
53                 if (idx == PERF_MSR_SMI)
54                         return true;
55                 break;
56
57         case 78: /* 14nm Skylake Mobile */
58         case 94: /* 14nm Skylake Desktop */
59                 if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
60                         return true;
61                 break;
62         }
63
64         return false;
65 }
66
67 struct perf_msr {
68         u64     msr;
69         struct  perf_pmu_events_attr *attr;
70         bool    (*test)(int idx);
71 };
72
73 PMU_EVENT_ATTR_STRING(tsc,   evattr_tsc,   "event=0x00");
74 PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01");
75 PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02");
76 PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");
77 PMU_EVENT_ATTR_STRING(smi,   evattr_smi,   "event=0x04");
78
79 static struct perf_msr msr[] = {
80         [PERF_MSR_TSC]   = { 0,                 &evattr_tsc,    NULL,            },
81         [PERF_MSR_APERF] = { MSR_IA32_APERF,    &evattr_aperf,  test_aperfmperf, },
82         [PERF_MSR_MPERF] = { MSR_IA32_MPERF,    &evattr_mperf,  test_aperfmperf, },
83         [PERF_MSR_PPERF] = { MSR_PPERF,         &evattr_pperf,  test_intel,      },
84         [PERF_MSR_SMI]   = { MSR_SMI_COUNT,     &evattr_smi,    test_intel,      },
85 };
86
87 static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
88         NULL,
89 };
90
91 static struct attribute_group events_attr_group = {
92         .name = "events",
93         .attrs = events_attrs,
94 };
95
96 PMU_FORMAT_ATTR(event, "config:0-63");
97 static struct attribute *format_attrs[] = {
98         &format_attr_event.attr,
99         NULL,
100 };
101 static struct attribute_group format_attr_group = {
102         .name = "format",
103         .attrs = format_attrs,
104 };
105
106 static const struct attribute_group *attr_groups[] = {
107         &events_attr_group,
108         &format_attr_group,
109         NULL,
110 };
111
112 static int msr_event_init(struct perf_event *event)
113 {
114         u64 cfg = event->attr.config;
115
116         if (event->attr.type != event->pmu->type)
117                 return -ENOENT;
118
119         /* unsupported modes and filters */
120         if (event->attr.exclude_user   ||
121             event->attr.exclude_kernel ||
122             event->attr.exclude_hv     ||
123             event->attr.exclude_idle   ||
124             event->attr.exclude_host   ||
125             event->attr.exclude_guest  ||
126             event->attr.sample_period) /* no sampling */
127                 return -EINVAL;
128
129         if (cfg >= PERF_MSR_EVENT_MAX)
130                 return -EINVAL;
131
132         cfg = array_index_nospec((unsigned long)cfg, PERF_MSR_EVENT_MAX);
133
134         if (!msr[cfg].attr)
135                 return -EINVAL;
136
137         event->hw.idx = -1;
138         event->hw.event_base = msr[cfg].msr;
139         event->hw.config = cfg;
140
141         return 0;
142 }
143
144 static inline u64 msr_read_counter(struct perf_event *event)
145 {
146         u64 now;
147
148         if (event->hw.event_base)
149                 rdmsrl(event->hw.event_base, now);
150         else
151                 rdtscll(now);
152
153         return now;
154 }
155 static void msr_event_update(struct perf_event *event)
156 {
157         u64 prev, now;
158         s64 delta;
159
160         /* Careful, an NMI might modify the previous event value. */
161 again:
162         prev = local64_read(&event->hw.prev_count);
163         now = msr_read_counter(event);
164
165         if (local64_cmpxchg(&event->hw.prev_count, prev, now) != prev)
166                 goto again;
167
168         delta = now - prev;
169         if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
170                 delta = sign_extend64(delta, 31);
171
172         local64_add(now - prev, &event->count);
173 }
174
175 static void msr_event_start(struct perf_event *event, int flags)
176 {
177         u64 now;
178
179         now = msr_read_counter(event);
180         local64_set(&event->hw.prev_count, now);
181 }
182
183 static void msr_event_stop(struct perf_event *event, int flags)
184 {
185         msr_event_update(event);
186 }
187
188 static void msr_event_del(struct perf_event *event, int flags)
189 {
190         msr_event_stop(event, PERF_EF_UPDATE);
191 }
192
193 static int msr_event_add(struct perf_event *event, int flags)
194 {
195         if (flags & PERF_EF_START)
196                 msr_event_start(event, flags);
197
198         return 0;
199 }
200
201 static struct pmu pmu_msr = {
202         .task_ctx_nr    = perf_sw_context,
203         .attr_groups    = attr_groups,
204         .event_init     = msr_event_init,
205         .add            = msr_event_add,
206         .del            = msr_event_del,
207         .start          = msr_event_start,
208         .stop           = msr_event_stop,
209         .read           = msr_event_update,
210         .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
211 };
212
213 static int __init msr_init(void)
214 {
215         int i, j = 0;
216
217         if (!boot_cpu_has(X86_FEATURE_TSC)) {
218                 pr_cont("no MSR PMU driver.\n");
219                 return 0;
220         }
221
222         /* Probe the MSRs. */
223         for (i = PERF_MSR_TSC + 1; i < PERF_MSR_EVENT_MAX; i++) {
224                 u64 val;
225
226                 /*
227                  * Virt sucks arse; you cannot tell if a R/O MSR is present :/
228                  */
229                 if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
230                         msr[i].attr = NULL;
231         }
232
233         /* List remaining MSRs in the sysfs attrs. */
234         for (i = 0; i < PERF_MSR_EVENT_MAX; i++) {
235                 if (msr[i].attr)
236                         events_attrs[j++] = &msr[i].attr->attr.attr;
237         }
238         events_attrs[j] = NULL;
239
240         perf_pmu_register(&pmu_msr, "msr", -1);
241
242         return 0;
243 }
244 device_initcall(msr_init);