Branch data Line data Source code
1 : : /*
2 : : * Support cstate residency counters
3 : : *
4 : : * Copyright (C) 2015, Intel Corp.
5 : : * Author: Kan Liang (kan.liang@intel.com)
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Library General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Library General Public License for more details.
16 : : *
17 : : */
18 : :
19 : : /*
20 : : * This file export cstate related free running (read-only) counters
21 : : * for perf. These counters may be use simultaneously by other tools,
22 : : * such as turbostat. However, it still make sense to implement them
23 : : * in perf. Because we can conveniently collect them together with
24 : : * other events, and allow to use them from tools without special MSR
25 : : * access code.
26 : : *
27 : : * The events only support system-wide mode counting. There is no
28 : : * sampling support because it is not supported by the hardware.
29 : : *
30 : : * According to counters' scope and category, two PMUs are registered
31 : : * with the perf_event core subsystem.
32 : : * - 'cstate_core': The counter is available for each physical core.
33 : : * The counters include CORE_C*_RESIDENCY.
34 : : * - 'cstate_pkg': The counter is available for each physical package.
35 : : * The counters include PKG_C*_RESIDENCY.
36 : : *
37 : : * All of these counters are specified in the IntelĀ® 64 and IA-32
38 : : * Architectures Software Developer.s Manual Vol3b.
39 : : *
40 : : * Model specific counters:
41 : : * MSR_CORE_C1_RES: CORE C1 Residency Counter
42 : : * perf code: 0x00
43 : : * Available model: SLM,AMT,GLM,CNL,TNT
44 : : * Scope: Core (each processor core has a MSR)
45 : : * MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
46 : : * perf code: 0x01
47 : : * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,GLM,
48 : : * CNL,KBL,CML,TNT
49 : : * Scope: Core
50 : : * MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter
51 : : * perf code: 0x02
52 : : * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
53 : : * SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL,
54 : : * TNT
55 : : * Scope: Core
56 : : * MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
57 : : * perf code: 0x03
58 : : * Available model: SNB,IVB,HSW,BDW,SKL,CNL,KBL,CML,
59 : : * ICL,TGL
60 : : * Scope: Core
61 : : * MSR_PKG_C2_RESIDENCY: Package C2 Residency Counter.
62 : : * perf code: 0x00
63 : : * Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
64 : : * KBL,CML,ICL,TGL,TNT
65 : : * Scope: Package (physical package)
66 : : * MSR_PKG_C3_RESIDENCY: Package C3 Residency Counter.
67 : : * perf code: 0x01
68 : : * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
69 : : * GLM,CNL,KBL,CML,ICL,TGL,TNT
70 : : * Scope: Package (physical package)
71 : : * MSR_PKG_C6_RESIDENCY: Package C6 Residency Counter.
72 : : * perf code: 0x02
73 : : * Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
74 : : * SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL,
75 : : * TNT
76 : : * Scope: Package (physical package)
77 : : * MSR_PKG_C7_RESIDENCY: Package C7 Residency Counter.
78 : : * perf code: 0x03
79 : : * Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,CNL,
80 : : * KBL,CML,ICL,TGL
81 : : * Scope: Package (physical package)
82 : : * MSR_PKG_C8_RESIDENCY: Package C8 Residency Counter.
83 : : * perf code: 0x04
84 : : * Available model: HSW ULT,KBL,CNL,CML,ICL,TGL
85 : : * Scope: Package (physical package)
86 : : * MSR_PKG_C9_RESIDENCY: Package C9 Residency Counter.
87 : : * perf code: 0x05
88 : : * Available model: HSW ULT,KBL,CNL,CML,ICL,TGL
89 : : * Scope: Package (physical package)
90 : : * MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
91 : : * perf code: 0x06
92 : : * Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
93 : : * TNT
94 : : * Scope: Package (physical package)
95 : : *
96 : : */
97 : :
98 : : #include <linux/module.h>
99 : : #include <linux/slab.h>
100 : : #include <linux/perf_event.h>
101 : : #include <linux/nospec.h>
102 : : #include <asm/cpu_device_id.h>
103 : : #include <asm/intel-family.h>
104 : : #include "../perf_event.h"
105 : : #include "../probe.h"
106 : :
107 : : MODULE_LICENSE("GPL");
108 : :
109 : : #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \
110 : : static ssize_t __cstate_##_var##_show(struct kobject *kobj, \
111 : : struct kobj_attribute *attr, \
112 : : char *page) \
113 : : { \
114 : : BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \
115 : : return sprintf(page, _format "\n"); \
116 : : } \
117 : : static struct kobj_attribute format_attr_##_var = \
118 : : __ATTR(_name, 0444, __cstate_##_var##_show, NULL)
119 : :
120 : : static ssize_t cstate_get_attr_cpumask(struct device *dev,
121 : : struct device_attribute *attr,
122 : : char *buf);
123 : :
124 : : /* Model -> events mapping */
125 : : struct cstate_model {
126 : : unsigned long core_events;
127 : : unsigned long pkg_events;
128 : : unsigned long quirks;
129 : : };
130 : :
131 : : /* Quirk flags */
132 : : #define SLM_PKG_C6_USE_C7_MSR (1UL << 0)
133 : : #define KNL_CORE_C6_MSR (1UL << 1)
134 : :
135 : : struct perf_cstate_msr {
136 : : u64 msr;
137 : : struct perf_pmu_events_attr *attr;
138 : : };
139 : :
140 : :
141 : : /* cstate_core PMU */
142 : : static struct pmu cstate_core_pmu;
143 : : static bool has_cstate_core;
144 : :
145 : : enum perf_cstate_core_events {
146 : : PERF_CSTATE_CORE_C1_RES = 0,
147 : : PERF_CSTATE_CORE_C3_RES,
148 : : PERF_CSTATE_CORE_C6_RES,
149 : : PERF_CSTATE_CORE_C7_RES,
150 : :
151 : : PERF_CSTATE_CORE_EVENT_MAX,
152 : : };
153 : :
154 : : PMU_EVENT_ATTR_STRING(c1-residency, attr_cstate_core_c1, "event=0x00");
155 : : PMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_core_c3, "event=0x01");
156 : : PMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_core_c6, "event=0x02");
157 : : PMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_core_c7, "event=0x03");
158 : :
159 : : static unsigned long core_msr_mask;
160 : :
161 : : PMU_EVENT_GROUP(events, cstate_core_c1);
162 : : PMU_EVENT_GROUP(events, cstate_core_c3);
163 : : PMU_EVENT_GROUP(events, cstate_core_c6);
164 : : PMU_EVENT_GROUP(events, cstate_core_c7);
165 : :
166 : 0 : static bool test_msr(int idx, void *data)
167 : : {
168 : 0 : return test_bit(idx, (unsigned long *) data);
169 : : }
170 : :
171 : : static struct perf_msr core_msr[] = {
172 : : [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &group_cstate_core_c1, test_msr },
173 : : [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &group_cstate_core_c3, test_msr },
174 : : [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &group_cstate_core_c6, test_msr },
175 : : [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &group_cstate_core_c7, test_msr },
176 : : };
177 : :
178 : : static struct attribute *attrs_empty[] = {
179 : : NULL,
180 : : };
181 : :
182 : : /*
183 : : * There are no default events, but we need to create
184 : : * "events" group (with empty attrs) before updating
185 : : * it with detected events.
186 : : */
187 : : static struct attribute_group core_events_attr_group = {
188 : : .name = "events",
189 : : .attrs = attrs_empty,
190 : : };
191 : :
192 : 0 : DEFINE_CSTATE_FORMAT_ATTR(core_event, event, "config:0-63");
193 : : static struct attribute *core_format_attrs[] = {
194 : : &format_attr_core_event.attr,
195 : : NULL,
196 : : };
197 : :
198 : : static struct attribute_group core_format_attr_group = {
199 : : .name = "format",
200 : : .attrs = core_format_attrs,
201 : : };
202 : :
203 : : static cpumask_t cstate_core_cpu_mask;
204 : : static DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL);
205 : :
206 : : static struct attribute *cstate_cpumask_attrs[] = {
207 : : &dev_attr_cpumask.attr,
208 : : NULL,
209 : : };
210 : :
211 : : static struct attribute_group cpumask_attr_group = {
212 : : .attrs = cstate_cpumask_attrs,
213 : : };
214 : :
215 : : static const struct attribute_group *core_attr_groups[] = {
216 : : &core_events_attr_group,
217 : : &core_format_attr_group,
218 : : &cpumask_attr_group,
219 : : NULL,
220 : : };
221 : :
222 : : /* cstate_pkg PMU */
223 : : static struct pmu cstate_pkg_pmu;
224 : : static bool has_cstate_pkg;
225 : :
226 : : enum perf_cstate_pkg_events {
227 : : PERF_CSTATE_PKG_C2_RES = 0,
228 : : PERF_CSTATE_PKG_C3_RES,
229 : : PERF_CSTATE_PKG_C6_RES,
230 : : PERF_CSTATE_PKG_C7_RES,
231 : : PERF_CSTATE_PKG_C8_RES,
232 : : PERF_CSTATE_PKG_C9_RES,
233 : : PERF_CSTATE_PKG_C10_RES,
234 : :
235 : : PERF_CSTATE_PKG_EVENT_MAX,
236 : : };
237 : :
238 : : PMU_EVENT_ATTR_STRING(c2-residency, attr_cstate_pkg_c2, "event=0x00");
239 : : PMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_pkg_c3, "event=0x01");
240 : : PMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_pkg_c6, "event=0x02");
241 : : PMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_pkg_c7, "event=0x03");
242 : : PMU_EVENT_ATTR_STRING(c8-residency, attr_cstate_pkg_c8, "event=0x04");
243 : : PMU_EVENT_ATTR_STRING(c9-residency, attr_cstate_pkg_c9, "event=0x05");
244 : : PMU_EVENT_ATTR_STRING(c10-residency, attr_cstate_pkg_c10, "event=0x06");
245 : :
246 : : static unsigned long pkg_msr_mask;
247 : :
248 : : PMU_EVENT_GROUP(events, cstate_pkg_c2);
249 : : PMU_EVENT_GROUP(events, cstate_pkg_c3);
250 : : PMU_EVENT_GROUP(events, cstate_pkg_c6);
251 : : PMU_EVENT_GROUP(events, cstate_pkg_c7);
252 : : PMU_EVENT_GROUP(events, cstate_pkg_c8);
253 : : PMU_EVENT_GROUP(events, cstate_pkg_c9);
254 : : PMU_EVENT_GROUP(events, cstate_pkg_c10);
255 : :
256 : : static struct perf_msr pkg_msr[] = {
257 : : [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &group_cstate_pkg_c2, test_msr },
258 : : [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &group_cstate_pkg_c3, test_msr },
259 : : [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &group_cstate_pkg_c6, test_msr },
260 : : [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &group_cstate_pkg_c7, test_msr },
261 : : [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &group_cstate_pkg_c8, test_msr },
262 : : [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &group_cstate_pkg_c9, test_msr },
263 : : [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &group_cstate_pkg_c10, test_msr },
264 : : };
265 : :
266 : : static struct attribute_group pkg_events_attr_group = {
267 : : .name = "events",
268 : : .attrs = attrs_empty,
269 : : };
270 : :
271 : 0 : DEFINE_CSTATE_FORMAT_ATTR(pkg_event, event, "config:0-63");
272 : : static struct attribute *pkg_format_attrs[] = {
273 : : &format_attr_pkg_event.attr,
274 : : NULL,
275 : : };
276 : : static struct attribute_group pkg_format_attr_group = {
277 : : .name = "format",
278 : : .attrs = pkg_format_attrs,
279 : : };
280 : :
281 : : static cpumask_t cstate_pkg_cpu_mask;
282 : :
283 : : static const struct attribute_group *pkg_attr_groups[] = {
284 : : &pkg_events_attr_group,
285 : : &pkg_format_attr_group,
286 : : &cpumask_attr_group,
287 : : NULL,
288 : : };
289 : :
290 : 0 : static ssize_t cstate_get_attr_cpumask(struct device *dev,
291 : : struct device_attribute *attr,
292 : : char *buf)
293 : : {
294 [ # # ]: 0 : struct pmu *pmu = dev_get_drvdata(dev);
295 : :
296 [ # # ]: 0 : if (pmu == &cstate_core_pmu)
297 : 0 : return cpumap_print_to_pagebuf(true, buf, &cstate_core_cpu_mask);
298 [ # # ]: 0 : else if (pmu == &cstate_pkg_pmu)
299 : 0 : return cpumap_print_to_pagebuf(true, buf, &cstate_pkg_cpu_mask);
300 : : else
301 : : return 0;
302 : : }
303 : :
304 : 0 : static int cstate_pmu_event_init(struct perf_event *event)
305 : : {
306 : 0 : u64 cfg = event->attr.config;
307 : 0 : int cpu;
308 : :
309 [ # # ]: 0 : if (event->attr.type != event->pmu->type)
310 : : return -ENOENT;
311 : :
312 : : /* unsupported modes and filters */
313 [ # # ]: 0 : if (event->attr.sample_period) /* no sampling */
314 : : return -EINVAL;
315 : :
316 [ # # ]: 0 : if (event->cpu < 0)
317 : : return -EINVAL;
318 : :
319 [ # # ]: 0 : if (event->pmu == &cstate_core_pmu) {
320 [ # # ]: 0 : if (cfg >= PERF_CSTATE_CORE_EVENT_MAX)
321 : : return -EINVAL;
322 : 0 : cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_CORE_EVENT_MAX);
323 [ # # ]: 0 : if (!(core_msr_mask & (1 << cfg)))
324 : : return -EINVAL;
325 : 0 : event->hw.event_base = core_msr[cfg].msr;
326 : 0 : cpu = cpumask_any_and(&cstate_core_cpu_mask,
327 : : topology_sibling_cpumask(event->cpu));
328 [ # # ]: 0 : } else if (event->pmu == &cstate_pkg_pmu) {
329 [ # # ]: 0 : if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
330 : : return -EINVAL;
331 : 0 : cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX);
332 [ # # ]: 0 : if (!(pkg_msr_mask & (1 << cfg)))
333 : : return -EINVAL;
334 : 0 : event->hw.event_base = pkg_msr[cfg].msr;
335 : 0 : cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
336 : : topology_die_cpumask(event->cpu));
337 : : } else {
338 : : return -ENOENT;
339 : : }
340 : :
341 [ # # ]: 0 : if (cpu >= nr_cpu_ids)
342 : : return -ENODEV;
343 : :
344 : 0 : event->cpu = cpu;
345 : 0 : event->hw.config = cfg;
346 : 0 : event->hw.idx = -1;
347 : 0 : return 0;
348 : : }
349 : :
350 : 0 : static inline u64 cstate_pmu_read_counter(struct perf_event *event)
351 : : {
352 : 0 : u64 val;
353 : :
354 : 0 : rdmsrl(event->hw.event_base, val);
355 : 0 : return val;
356 : : }
357 : :
358 : 0 : static void cstate_pmu_event_update(struct perf_event *event)
359 : : {
360 : 0 : struct hw_perf_event *hwc = &event->hw;
361 : 0 : u64 prev_raw_count, new_raw_count;
362 : :
363 : 0 : again:
364 : 0 : prev_raw_count = local64_read(&hwc->prev_count);
365 : 0 : new_raw_count = cstate_pmu_read_counter(event);
366 : :
367 [ # # ]: 0 : if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
368 : : new_raw_count) != prev_raw_count)
369 : 0 : goto again;
370 : :
371 : 0 : local64_add(new_raw_count - prev_raw_count, &event->count);
372 : 0 : }
373 : :
374 : 0 : static void cstate_pmu_event_start(struct perf_event *event, int mode)
375 : : {
376 : 0 : local64_set(&event->hw.prev_count, cstate_pmu_read_counter(event));
377 : 0 : }
378 : :
379 : 0 : static void cstate_pmu_event_stop(struct perf_event *event, int mode)
380 : : {
381 : 0 : cstate_pmu_event_update(event);
382 : 0 : }
383 : :
384 : 0 : static void cstate_pmu_event_del(struct perf_event *event, int mode)
385 : : {
386 : 0 : cstate_pmu_event_stop(event, PERF_EF_UPDATE);
387 : 0 : }
388 : :
389 : 0 : static int cstate_pmu_event_add(struct perf_event *event, int mode)
390 : : {
391 [ # # ]: 0 : if (mode & PERF_EF_START)
392 : 0 : cstate_pmu_event_start(event, mode);
393 : :
394 : 0 : return 0;
395 : : }
396 : :
397 : : /*
398 : : * Check if exiting cpu is the designated reader. If so migrate the
399 : : * events when there is a valid target available
400 : : */
401 : 0 : static int cstate_cpu_exit(unsigned int cpu)
402 : : {
403 : 0 : unsigned int target;
404 : :
405 [ # # # # ]: 0 : if (has_cstate_core &&
406 : 0 : cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask)) {
407 : :
408 : 0 : target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
409 : : /* Migrate events if there is a valid target */
410 [ # # ]: 0 : if (target < nr_cpu_ids) {
411 : 0 : cpumask_set_cpu(target, &cstate_core_cpu_mask);
412 : 0 : perf_pmu_migrate_context(&cstate_core_pmu, cpu, target);
413 : : }
414 : : }
415 : :
416 [ # # # # ]: 0 : if (has_cstate_pkg &&
417 : 0 : cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) {
418 : :
419 : 0 : target = cpumask_any_but(topology_die_cpumask(cpu), cpu);
420 : : /* Migrate events if there is a valid target */
421 [ # # ]: 0 : if (target < nr_cpu_ids) {
422 : 0 : cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
423 : 0 : perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target);
424 : : }
425 : : }
426 : 0 : return 0;
427 : : }
428 : :
429 : 0 : static int cstate_cpu_init(unsigned int cpu)
430 : : {
431 : 0 : unsigned int target;
432 : :
433 : : /*
434 : : * If this is the first online thread of that core, set it in
435 : : * the core cpu mask as the designated reader.
436 : : */
437 : 0 : target = cpumask_any_and(&cstate_core_cpu_mask,
438 : : topology_sibling_cpumask(cpu));
439 : :
440 [ # # # # ]: 0 : if (has_cstate_core && target >= nr_cpu_ids)
441 : 0 : cpumask_set_cpu(cpu, &cstate_core_cpu_mask);
442 : :
443 : : /*
444 : : * If this is the first online thread of that package, set it
445 : : * in the package cpu mask as the designated reader.
446 : : */
447 : 0 : target = cpumask_any_and(&cstate_pkg_cpu_mask,
448 : : topology_die_cpumask(cpu));
449 [ # # # # ]: 0 : if (has_cstate_pkg && target >= nr_cpu_ids)
450 : 0 : cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
451 : :
452 : 0 : return 0;
453 : : }
454 : :
455 : : static const struct attribute_group *core_attr_update[] = {
456 : : &group_cstate_core_c1,
457 : : &group_cstate_core_c3,
458 : : &group_cstate_core_c6,
459 : : &group_cstate_core_c7,
460 : : NULL,
461 : : };
462 : :
463 : : static const struct attribute_group *pkg_attr_update[] = {
464 : : &group_cstate_pkg_c2,
465 : : &group_cstate_pkg_c3,
466 : : &group_cstate_pkg_c6,
467 : : &group_cstate_pkg_c7,
468 : : &group_cstate_pkg_c8,
469 : : &group_cstate_pkg_c9,
470 : : &group_cstate_pkg_c10,
471 : : NULL,
472 : : };
473 : :
474 : : static struct pmu cstate_core_pmu = {
475 : : .attr_groups = core_attr_groups,
476 : : .attr_update = core_attr_update,
477 : : .name = "cstate_core",
478 : : .task_ctx_nr = perf_invalid_context,
479 : : .event_init = cstate_pmu_event_init,
480 : : .add = cstate_pmu_event_add,
481 : : .del = cstate_pmu_event_del,
482 : : .start = cstate_pmu_event_start,
483 : : .stop = cstate_pmu_event_stop,
484 : : .read = cstate_pmu_event_update,
485 : : .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE,
486 : : .module = THIS_MODULE,
487 : : };
488 : :
489 : : static struct pmu cstate_pkg_pmu = {
490 : : .attr_groups = pkg_attr_groups,
491 : : .attr_update = pkg_attr_update,
492 : : .name = "cstate_pkg",
493 : : .task_ctx_nr = perf_invalid_context,
494 : : .event_init = cstate_pmu_event_init,
495 : : .add = cstate_pmu_event_add,
496 : : .del = cstate_pmu_event_del,
497 : : .start = cstate_pmu_event_start,
498 : : .stop = cstate_pmu_event_stop,
499 : : .read = cstate_pmu_event_update,
500 : : .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE,
501 : : .module = THIS_MODULE,
502 : : };
503 : :
504 : : static const struct cstate_model nhm_cstates __initconst = {
505 : : .core_events = BIT(PERF_CSTATE_CORE_C3_RES) |
506 : : BIT(PERF_CSTATE_CORE_C6_RES),
507 : :
508 : : .pkg_events = BIT(PERF_CSTATE_PKG_C3_RES) |
509 : : BIT(PERF_CSTATE_PKG_C6_RES) |
510 : : BIT(PERF_CSTATE_PKG_C7_RES),
511 : : };
512 : :
513 : : static const struct cstate_model snb_cstates __initconst = {
514 : : .core_events = BIT(PERF_CSTATE_CORE_C3_RES) |
515 : : BIT(PERF_CSTATE_CORE_C6_RES) |
516 : : BIT(PERF_CSTATE_CORE_C7_RES),
517 : :
518 : : .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
519 : : BIT(PERF_CSTATE_PKG_C3_RES) |
520 : : BIT(PERF_CSTATE_PKG_C6_RES) |
521 : : BIT(PERF_CSTATE_PKG_C7_RES),
522 : : };
523 : :
524 : : static const struct cstate_model hswult_cstates __initconst = {
525 : : .core_events = BIT(PERF_CSTATE_CORE_C3_RES) |
526 : : BIT(PERF_CSTATE_CORE_C6_RES) |
527 : : BIT(PERF_CSTATE_CORE_C7_RES),
528 : :
529 : : .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
530 : : BIT(PERF_CSTATE_PKG_C3_RES) |
531 : : BIT(PERF_CSTATE_PKG_C6_RES) |
532 : : BIT(PERF_CSTATE_PKG_C7_RES) |
533 : : BIT(PERF_CSTATE_PKG_C8_RES) |
534 : : BIT(PERF_CSTATE_PKG_C9_RES) |
535 : : BIT(PERF_CSTATE_PKG_C10_RES),
536 : : };
537 : :
538 : : static const struct cstate_model cnl_cstates __initconst = {
539 : : .core_events = BIT(PERF_CSTATE_CORE_C1_RES) |
540 : : BIT(PERF_CSTATE_CORE_C3_RES) |
541 : : BIT(PERF_CSTATE_CORE_C6_RES) |
542 : : BIT(PERF_CSTATE_CORE_C7_RES),
543 : :
544 : : .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
545 : : BIT(PERF_CSTATE_PKG_C3_RES) |
546 : : BIT(PERF_CSTATE_PKG_C6_RES) |
547 : : BIT(PERF_CSTATE_PKG_C7_RES) |
548 : : BIT(PERF_CSTATE_PKG_C8_RES) |
549 : : BIT(PERF_CSTATE_PKG_C9_RES) |
550 : : BIT(PERF_CSTATE_PKG_C10_RES),
551 : : };
552 : :
553 : : static const struct cstate_model icl_cstates __initconst = {
554 : : .core_events = BIT(PERF_CSTATE_CORE_C6_RES) |
555 : : BIT(PERF_CSTATE_CORE_C7_RES),
556 : :
557 : : .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
558 : : BIT(PERF_CSTATE_PKG_C3_RES) |
559 : : BIT(PERF_CSTATE_PKG_C6_RES) |
560 : : BIT(PERF_CSTATE_PKG_C7_RES) |
561 : : BIT(PERF_CSTATE_PKG_C8_RES) |
562 : : BIT(PERF_CSTATE_PKG_C9_RES) |
563 : : BIT(PERF_CSTATE_PKG_C10_RES),
564 : : };
565 : :
566 : : static const struct cstate_model slm_cstates __initconst = {
567 : : .core_events = BIT(PERF_CSTATE_CORE_C1_RES) |
568 : : BIT(PERF_CSTATE_CORE_C6_RES),
569 : :
570 : : .pkg_events = BIT(PERF_CSTATE_PKG_C6_RES),
571 : : .quirks = SLM_PKG_C6_USE_C7_MSR,
572 : : };
573 : :
574 : :
575 : : static const struct cstate_model knl_cstates __initconst = {
576 : : .core_events = BIT(PERF_CSTATE_CORE_C6_RES),
577 : :
578 : : .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
579 : : BIT(PERF_CSTATE_PKG_C3_RES) |
580 : : BIT(PERF_CSTATE_PKG_C6_RES),
581 : : .quirks = KNL_CORE_C6_MSR,
582 : : };
583 : :
584 : :
585 : : static const struct cstate_model glm_cstates __initconst = {
586 : : .core_events = BIT(PERF_CSTATE_CORE_C1_RES) |
587 : : BIT(PERF_CSTATE_CORE_C3_RES) |
588 : : BIT(PERF_CSTATE_CORE_C6_RES),
589 : :
590 : : .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
591 : : BIT(PERF_CSTATE_PKG_C3_RES) |
592 : : BIT(PERF_CSTATE_PKG_C6_RES) |
593 : : BIT(PERF_CSTATE_PKG_C10_RES),
594 : : };
595 : :
596 : :
597 : : #define X86_CSTATES_MODEL(model, states) \
598 : : { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long) &(states) }
599 : :
600 : : static const struct x86_cpu_id intel_cstates_match[] __initconst = {
601 : : X86_CSTATES_MODEL(INTEL_FAM6_NEHALEM, nhm_cstates),
602 : : X86_CSTATES_MODEL(INTEL_FAM6_NEHALEM_EP, nhm_cstates),
603 : : X86_CSTATES_MODEL(INTEL_FAM6_NEHALEM_EX, nhm_cstates),
604 : :
605 : : X86_CSTATES_MODEL(INTEL_FAM6_WESTMERE, nhm_cstates),
606 : : X86_CSTATES_MODEL(INTEL_FAM6_WESTMERE_EP, nhm_cstates),
607 : : X86_CSTATES_MODEL(INTEL_FAM6_WESTMERE_EX, nhm_cstates),
608 : :
609 : : X86_CSTATES_MODEL(INTEL_FAM6_SANDYBRIDGE, snb_cstates),
610 : : X86_CSTATES_MODEL(INTEL_FAM6_SANDYBRIDGE_X, snb_cstates),
611 : :
612 : : X86_CSTATES_MODEL(INTEL_FAM6_IVYBRIDGE, snb_cstates),
613 : : X86_CSTATES_MODEL(INTEL_FAM6_IVYBRIDGE_X, snb_cstates),
614 : :
615 : : X86_CSTATES_MODEL(INTEL_FAM6_HASWELL, snb_cstates),
616 : : X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_X, snb_cstates),
617 : : X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_G, snb_cstates),
618 : :
619 : : X86_CSTATES_MODEL(INTEL_FAM6_HASWELL_L, hswult_cstates),
620 : :
621 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT, slm_cstates),
622 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_SILVERMONT_D, slm_cstates),
623 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_AIRMONT, slm_cstates),
624 : :
625 : : X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL, snb_cstates),
626 : : X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_D, snb_cstates),
627 : : X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_G, snb_cstates),
628 : : X86_CSTATES_MODEL(INTEL_FAM6_BROADWELL_X, snb_cstates),
629 : :
630 : : X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_L, snb_cstates),
631 : : X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE, snb_cstates),
632 : : X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_X, snb_cstates),
633 : :
634 : : X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_L, hswult_cstates),
635 : : X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE, hswult_cstates),
636 : : X86_CSTATES_MODEL(INTEL_FAM6_COMETLAKE_L, hswult_cstates),
637 : : X86_CSTATES_MODEL(INTEL_FAM6_COMETLAKE, hswult_cstates),
638 : :
639 : : X86_CSTATES_MODEL(INTEL_FAM6_CANNONLAKE_L, cnl_cstates),
640 : :
641 : : X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNL, knl_cstates),
642 : : X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNM, knl_cstates),
643 : :
644 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT, glm_cstates),
645 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_D, glm_cstates),
646 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_PLUS, glm_cstates),
647 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_TREMONT_D, glm_cstates),
648 : : X86_CSTATES_MODEL(INTEL_FAM6_ATOM_TREMONT, glm_cstates),
649 : :
650 : : X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE_L, icl_cstates),
651 : : X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE, icl_cstates),
652 : : X86_CSTATES_MODEL(INTEL_FAM6_TIGERLAKE_L, icl_cstates),
653 : : X86_CSTATES_MODEL(INTEL_FAM6_TIGERLAKE, icl_cstates),
654 : : { },
655 : : };
656 : : MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
657 : :
658 : 0 : static int __init cstate_probe(const struct cstate_model *cm)
659 : : {
660 : : /* SLM has different MSR for PKG C6 */
661 [ # # ]: 0 : if (cm->quirks & SLM_PKG_C6_USE_C7_MSR)
662 : 0 : pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
663 : :
664 : : /* KNL has different MSR for CORE C6 */
665 [ # # ]: 0 : if (cm->quirks & KNL_CORE_C6_MSR)
666 : 0 : pkg_msr[PERF_CSTATE_CORE_C6_RES].msr = MSR_KNL_CORE_C6_RESIDENCY;
667 : :
668 : :
669 : 0 : core_msr_mask = perf_msr_probe(core_msr, PERF_CSTATE_CORE_EVENT_MAX,
670 : 0 : true, (void *) &cm->core_events);
671 : :
672 : 0 : pkg_msr_mask = perf_msr_probe(pkg_msr, PERF_CSTATE_PKG_EVENT_MAX,
673 : 0 : true, (void *) &cm->pkg_events);
674 : :
675 : 0 : has_cstate_core = !!core_msr_mask;
676 : 0 : has_cstate_pkg = !!pkg_msr_mask;
677 : :
678 [ # # # # ]: 0 : return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
679 : : }
680 : :
681 : 0 : static inline void cstate_cleanup(void)
682 : : {
683 : 0 : cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_ONLINE);
684 : 0 : cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_STARTING);
685 : :
686 [ # # ]: 0 : if (has_cstate_core)
687 : 0 : perf_pmu_unregister(&cstate_core_pmu);
688 : :
689 [ # # ]: 0 : if (has_cstate_pkg)
690 : 0 : perf_pmu_unregister(&cstate_pkg_pmu);
691 : 0 : }
692 : :
693 : 0 : static int __init cstate_init(void)
694 : : {
695 : 0 : int err;
696 : :
697 : 0 : cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_STARTING,
698 : : "perf/x86/cstate:starting", cstate_cpu_init, NULL);
699 : 0 : cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_ONLINE,
700 : : "perf/x86/cstate:online", NULL, cstate_cpu_exit);
701 : :
702 [ # # ]: 0 : if (has_cstate_core) {
703 : 0 : err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);
704 [ # # ]: 0 : if (err) {
705 : 0 : has_cstate_core = false;
706 : 0 : pr_info("Failed to register cstate core pmu\n");
707 : 0 : cstate_cleanup();
708 : 0 : return err;
709 : : }
710 : : }
711 : :
712 [ # # ]: 0 : if (has_cstate_pkg) {
713 [ # # ]: 0 : if (topology_max_die_per_package() > 1) {
714 : 0 : err = perf_pmu_register(&cstate_pkg_pmu,
715 : : "cstate_die", -1);
716 : : } else {
717 : 0 : err = perf_pmu_register(&cstate_pkg_pmu,
718 : : cstate_pkg_pmu.name, -1);
719 : : }
720 [ # # ]: 0 : if (err) {
721 : 0 : has_cstate_pkg = false;
722 : 0 : pr_info("Failed to register cstate pkg pmu\n");
723 : 0 : cstate_cleanup();
724 : 0 : return err;
725 : : }
726 : : }
727 : : return 0;
728 : : }
729 : :
730 : 11 : static int __init cstate_pmu_init(void)
731 : : {
732 : 11 : const struct x86_cpu_id *id;
733 : 11 : int err;
734 : :
735 [ - + ]: 11 : if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
736 : : return -ENODEV;
737 : :
738 : 0 : id = x86_match_cpu(intel_cstates_match);
739 [ # # ]: 0 : if (!id)
740 : : return -ENODEV;
741 : :
742 : 0 : err = cstate_probe((const struct cstate_model *) id->driver_data);
743 [ # # ]: 0 : if (err)
744 : : return err;
745 : :
746 : 0 : return cstate_init();
747 : : }
748 : : module_init(cstate_pmu_init);
749 : :
750 : 0 : static void __exit cstate_pmu_exit(void)
751 : : {
752 : 0 : cstate_cleanup();
753 : 0 : }
754 : : module_exit(cstate_pmu_exit);
|