Skip to content

Commit 8f2a28c

Browse files
olsajiriIngo Molnar
authored andcommitted
perf/x86/cstate: Use new probe function
Using perf_msr_probe function to probe for cstate events. The functionality is the same, with one exception, that perf_msr_probe checks for rdmsr to return value != 0 for given MSR register. Using the new attribute groups and adding the events via pmu::attr_update. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Kan <kan.liang@linux.intel.com> Cc: Liang Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vince Weaver <vincent.weaver@maine.edu> Link: https://lkml.kernel.org/r/20190616140358.27799-4-jolsa@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent dde5e72 commit 8f2a28c

File tree

1 file changed

+87
-65
lines changed

1 file changed

+87
-65
lines changed

arch/x86/events/intel/cstate.c

Lines changed: 87 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
#include <asm/cpu_device_id.h>
9797
#include <asm/intel-family.h>
9898
#include "../perf_event.h"
99+
#include "../probe.h"
99100

100101
MODULE_LICENSE("GPL");
101102

@@ -144,25 +145,42 @@ enum perf_cstate_core_events {
144145
PERF_CSTATE_CORE_EVENT_MAX,
145146
};
146147

147-
PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00");
148-
PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01");
149-
PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02");
150-
PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03");
148+
PMU_EVENT_ATTR_STRING(c1-residency, attr_cstate_core_c1, "event=0x00");
149+
PMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_core_c3, "event=0x01");
150+
PMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_core_c6, "event=0x02");
151+
PMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_core_c7, "event=0x03");
151152

152-
static struct perf_cstate_msr core_msr[] = {
153-
[PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &evattr_cstate_core_c1 },
154-
[PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &evattr_cstate_core_c3 },
155-
[PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &evattr_cstate_core_c6 },
156-
[PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &evattr_cstate_core_c7 },
153+
static unsigned long core_msr_mask;
154+
155+
PMU_EVENT_GROUP(events, cstate_core_c1);
156+
PMU_EVENT_GROUP(events, cstate_core_c3);
157+
PMU_EVENT_GROUP(events, cstate_core_c6);
158+
PMU_EVENT_GROUP(events, cstate_core_c7);
159+
160+
static bool test_msr(int idx, void *data)
161+
{
162+
return test_bit(idx, (unsigned long *) data);
163+
}
164+
165+
static struct perf_msr core_msr[] = {
166+
[PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &group_cstate_core_c1, test_msr },
167+
[PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &group_cstate_core_c3, test_msr },
168+
[PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &group_cstate_core_c6, test_msr },
169+
[PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &group_cstate_core_c7, test_msr },
157170
};
158171

159-
static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = {
172+
static struct attribute *attrs_empty[] = {
160173
NULL,
161174
};
162175

176+
/*
177+
* There are no default events, but we need to create
178+
* "events" group (with empty attrs) before updating
179+
* it with detected events.
180+
*/
163181
static struct attribute_group core_events_attr_group = {
164182
.name = "events",
165-
.attrs = core_events_attrs,
183+
.attrs = attrs_empty,
166184
};
167185

168186
DEFINE_CSTATE_FORMAT_ATTR(core_event, event, "config:0-63");
@@ -211,31 +229,37 @@ enum perf_cstate_pkg_events {
211229
PERF_CSTATE_PKG_EVENT_MAX,
212230
};
213231

214-
PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00");
215-
PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01");
216-
PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02");
217-
PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_pkg_c7, "event=0x03");
218-
PMU_EVENT_ATTR_STRING(c8-residency, evattr_cstate_pkg_c8, "event=0x04");
219-
PMU_EVENT_ATTR_STRING(c9-residency, evattr_cstate_pkg_c9, "event=0x05");
220-
PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06");
221-
222-
static struct perf_cstate_msr pkg_msr[] = {
223-
[PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &evattr_cstate_pkg_c2 },
224-
[PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &evattr_cstate_pkg_c3 },
225-
[PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &evattr_cstate_pkg_c6 },
226-
[PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &evattr_cstate_pkg_c7 },
227-
[PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &evattr_cstate_pkg_c8 },
228-
[PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &evattr_cstate_pkg_c9 },
229-
[PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &evattr_cstate_pkg_c10 },
230-
};
231-
232-
static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = {
233-
NULL,
232+
PMU_EVENT_ATTR_STRING(c2-residency, attr_cstate_pkg_c2, "event=0x00");
233+
PMU_EVENT_ATTR_STRING(c3-residency, attr_cstate_pkg_c3, "event=0x01");
234+
PMU_EVENT_ATTR_STRING(c6-residency, attr_cstate_pkg_c6, "event=0x02");
235+
PMU_EVENT_ATTR_STRING(c7-residency, attr_cstate_pkg_c7, "event=0x03");
236+
PMU_EVENT_ATTR_STRING(c8-residency, attr_cstate_pkg_c8, "event=0x04");
237+
PMU_EVENT_ATTR_STRING(c9-residency, attr_cstate_pkg_c9, "event=0x05");
238+
PMU_EVENT_ATTR_STRING(c10-residency, attr_cstate_pkg_c10, "event=0x06");
239+
240+
static unsigned long pkg_msr_mask;
241+
242+
PMU_EVENT_GROUP(events, cstate_pkg_c2);
243+
PMU_EVENT_GROUP(events, cstate_pkg_c3);
244+
PMU_EVENT_GROUP(events, cstate_pkg_c6);
245+
PMU_EVENT_GROUP(events, cstate_pkg_c7);
246+
PMU_EVENT_GROUP(events, cstate_pkg_c8);
247+
PMU_EVENT_GROUP(events, cstate_pkg_c9);
248+
PMU_EVENT_GROUP(events, cstate_pkg_c10);
249+
250+
static struct perf_msr pkg_msr[] = {
251+
[PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &group_cstate_pkg_c2, test_msr },
252+
[PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &group_cstate_pkg_c3, test_msr },
253+
[PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &group_cstate_pkg_c6, test_msr },
254+
[PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &group_cstate_pkg_c7, test_msr },
255+
[PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &group_cstate_pkg_c8, test_msr },
256+
[PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &group_cstate_pkg_c9, test_msr },
257+
[PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &group_cstate_pkg_c10, test_msr },
234258
};
235259

236260
static struct attribute_group pkg_events_attr_group = {
237261
.name = "events",
238-
.attrs = pkg_events_attrs,
262+
.attrs = attrs_empty,
239263
};
240264

241265
DEFINE_CSTATE_FORMAT_ATTR(pkg_event, event, "config:0-63");
@@ -289,7 +313,8 @@ static int cstate_pmu_event_init(struct perf_event *event)
289313
if (event->pmu == &cstate_core_pmu) {
290314
if (cfg >= PERF_CSTATE_CORE_EVENT_MAX)
291315
return -EINVAL;
292-
if (!core_msr[cfg].attr)
316+
cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_CORE_EVENT_MAX);
317+
if (!(core_msr_mask & (1 << cfg)))
293318
return -EINVAL;
294319
event->hw.event_base = core_msr[cfg].msr;
295320
cpu = cpumask_any_and(&cstate_core_cpu_mask,
@@ -298,7 +323,7 @@ static int cstate_pmu_event_init(struct perf_event *event)
298323
if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
299324
return -EINVAL;
300325
cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX);
301-
if (!pkg_msr[cfg].attr)
326+
if (!(pkg_msr_mask & (1 << cfg)))
302327
return -EINVAL;
303328
event->hw.event_base = pkg_msr[cfg].msr;
304329
cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
@@ -421,8 +446,28 @@ static int cstate_cpu_init(unsigned int cpu)
421446
return 0;
422447
}
423448

449+
const struct attribute_group *core_attr_update[] = {
450+
&group_cstate_core_c1,
451+
&group_cstate_core_c3,
452+
&group_cstate_core_c6,
453+
&group_cstate_core_c7,
454+
NULL,
455+
};
456+
457+
const struct attribute_group *pkg_attr_update[] = {
458+
&group_cstate_pkg_c2,
459+
&group_cstate_pkg_c3,
460+
&group_cstate_pkg_c6,
461+
&group_cstate_pkg_c7,
462+
&group_cstate_pkg_c8,
463+
&group_cstate_pkg_c9,
464+
&group_cstate_pkg_c10,
465+
NULL,
466+
};
467+
424468
static struct pmu cstate_core_pmu = {
425469
.attr_groups = core_attr_groups,
470+
.attr_update = core_attr_update,
426471
.name = "cstate_core",
427472
.task_ctx_nr = perf_invalid_context,
428473
.event_init = cstate_pmu_event_init,
@@ -437,6 +482,7 @@ static struct pmu cstate_core_pmu = {
437482

438483
static struct pmu cstate_pkg_pmu = {
439484
.attr_groups = pkg_attr_groups,
485+
.attr_update = pkg_attr_update,
440486
.name = "cstate_pkg",
441487
.task_ctx_nr = perf_invalid_context,
442488
.event_init = cstate_pmu_event_init,
@@ -585,31 +631,6 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
585631
};
586632
MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
587633

588-
/*
589-
* Probe the cstate events and insert the available one into sysfs attrs
590-
* Return false if there are no available events.
591-
*/
592-
static bool __init cstate_probe_msr(const unsigned long evmsk, int max,
593-
struct perf_cstate_msr *msr,
594-
struct attribute **attrs)
595-
{
596-
bool found = false;
597-
unsigned int bit;
598-
u64 val;
599-
600-
for (bit = 0; bit < max; bit++) {
601-
if (test_bit(bit, &evmsk) && !rdmsrl_safe(msr[bit].msr, &val)) {
602-
*attrs++ = &msr[bit].attr->attr.attr;
603-
found = true;
604-
} else {
605-
msr[bit].attr = NULL;
606-
}
607-
}
608-
*attrs = NULL;
609-
610-
return found;
611-
}
612-
613634
static int __init cstate_probe(const struct cstate_model *cm)
614635
{
615636
/* SLM has different MSR for PKG C6 */
@@ -621,13 +642,14 @@ static int __init cstate_probe(const struct cstate_model *cm)
621642
pkg_msr[PERF_CSTATE_CORE_C6_RES].msr = MSR_KNL_CORE_C6_RESIDENCY;
622643

623644

624-
has_cstate_core = cstate_probe_msr(cm->core_events,
625-
PERF_CSTATE_CORE_EVENT_MAX,
626-
core_msr, core_events_attrs);
645+
core_msr_mask = perf_msr_probe(core_msr, PERF_CSTATE_CORE_EVENT_MAX,
646+
true, (void *) &cm->core_events);
647+
648+
pkg_msr_mask = perf_msr_probe(pkg_msr, PERF_CSTATE_PKG_EVENT_MAX,
649+
true, (void *) &cm->pkg_events);
627650

628-
has_cstate_pkg = cstate_probe_msr(cm->pkg_events,
629-
PERF_CSTATE_PKG_EVENT_MAX,
630-
pkg_msr, pkg_events_attrs);
651+
has_cstate_core = !!core_msr_mask;
652+
has_cstate_pkg = !!pkg_msr_mask;
631653

632654
return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
633655
}

0 commit comments

Comments
 (0)