perf/rapl: fix sysfs_show() initialization for RAPL PMU
Subsystems (2)
PATCH 1/1 perf/rapl: fix sysfs_show() initialization for RAPL PMU
This patch fixes a problem with the initialization of the sysfs_show() routine for the RAPL PMU.
The current code was wrongly relying on the EVENT_ATTR_STR() macro which uses the events_sysfs_show() function in the x86 PMU code. That function itself was relying on the x86_pmu data structure. Yet RAPL and the core PMU (x86_pmu) have nothing to do with each other. They should therefore not interact with each other.
The x86_pmu structure is initialized at boot time based on the host CPU model. When the host CPU is not supported, the x86_pmu remains uninitialized and some of the callbacks it contains are NULL.
The false dependency with x86_pmu could potentially cause crashes in case the x86_pmu is not initialized while the RAPL PMU is. This may, for instance, be the case in virtualized environments.
This patch fixes the problem by using a private sysfs_show() routine for exporting the RAPL PMU events.
--- arch/x86/kernel/cpu/perf_event_intel_rapl.c | 44 +++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-)
arch/x86/kernel/cpu/perf_event_intel_rapl.c +32 -12
@@ -103,6 +103,13 @@ static struct kobj_attribute format_attr_##_var = \#define RAPL_CNTR_WIDTH 32/* 32-bit rapl counters */ +#define RAPL_EVENT_ATTR_STR (_name, v, str) \ +static struct perf_pmu_events_attr event_attr_##v = { \ + .attr = __ATTR(_name, 0444, rapl_sysfs_show, NULL), \ + .id = 0, \ + .event_str = str, \ +}; +struct rapl_pmu {spinlock_t lock;int hw_unit;/* 1/2^hw_unit Joule */
@@ -379,23 +386,36 @@ static struct attribute_group rapl_pmu_attr_group = { .attrs = rapl_pmu_attrs, }; -EVENT_ATTR_STR (energy-cores, rapl_cores,"event=0x01" ); -EVENT_ATTR_STR (energy-pkg , rapl_pkg,"event=0x02" ); -EVENT_ATTR_STR (energy-ram , rapl_ram,"event=0x03" ); -EVENT_ATTR_STR (energy-gpu , rapl_gpu,"event=0x04" ); +static ssize_t rapl_sysfs_show (struct device *dev, +struct device_attribute *attr, +char *page) +{ +struct perf_pmu_events_attr *pmu_attr = \ + container_of(attr, struct perf_pmu_events_attr, attr); + +if (pmu_attr->event_str) +return sprintf (page,"%s" , pmu_attr->event_str); + +return 0 ; +} + +RAPL_EVENT_ATTR_STR (energy-cores, rapl_cores,"event=0x01" ); +RAPL_EVENT_ATTR_STR (energy-pkg , rapl_pkg,"event=0x02" ); +RAPL_EVENT_ATTR_STR (energy-ram , rapl_ram,"event=0x03" ); +RAPL_EVENT_ATTR_STR (energy-gpu , rapl_gpu,"event=0x04" ); -EVENT_ATTR_STR (energy-cores.unit, rapl_cores_unit,"Joules" ); -EVENT_ATTR_STR (energy-pkg.unit , rapl_pkg_unit,"Joules" ); -EVENT_ATTR_STR (energy-ram.unit , rapl_ram_unit,"Joules" ); -EVENT_ATTR_STR (energy-gpu.unit , rapl_gpu_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-cores.unit, rapl_cores_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-pkg.unit , rapl_pkg_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-ram.unit , rapl_ram_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-gpu.unit , rapl_gpu_unit,"Joules" );/* * we compute in 0.23 nJ increments regardless of MSR */ -EVENT_ATTR_STR (energy-cores.scale, rapl_cores_scale,"2.3283064365386962890625e-10" ); -EVENT_ATTR_STR (energy-pkg.scale, rapl_pkg_scale,"2.3283064365386962890625e-10" ); -EVENT_ATTR_STR (energy-ram.scale, rapl_ram_scale,"2.3283064365386962890625e-10" ); -EVENT_ATTR_STR (energy-gpu.scale, rapl_gpu_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-cores.scale, rapl_cores_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-pkg.scale, rapl_pkg_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-ram.scale, rapl_ram_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-gpu.scale, rapl_gpu_scale,"2.3283064365386962890625e-10" );static struct attribute *rapl_events_srv_attr[] = {EVENT_PTR (rapl_cores),
Signature · 1 line
1.9.1
tip-bot for Stephane Eranian
merge bot[tip:perf/urgent] perf/rapl: Fix sysfs_show() initialization for RAPL PMU
perf/rapl: Fix sysfs_show() initialization for RAPL PMU
Commit-ID: 433678bdc6ed39f053c55da96b51de5bf0aeebb1 Gitweb: http://git.kernel.org/tip/433678bdc6ed39f053c55da96b51de5bf0aeebb1 Author: Stephane Eranian <[email protected]> AuthorDate: Tue, 13 Jan 2015 23:59:53 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 16 Jan 2015 09:06:58 +0100
perf/rapl: Fix sysfs_show() initialization for RAPL PMU
This patch fixes a problem with the initialization of the sysfs_show() routine for the RAPL PMU.
The current code was wrongly relying on the EVENT_ATTR_STR() macro which uses the events_sysfs_show() function in the x86 PMU code. That function itself was relying on the x86_pmu data structure. Yet RAPL and the core PMU (x86_pmu) have nothing to do with each other. They should therefore not interact with each other.
The x86_pmu structure is initialized at boot time based on the host CPU model. When the host CPU is not supported, the x86_pmu remains uninitialized and some of the callbacks it contains are NULL.
The false dependency with x86_pmu could potentially cause crashes in case the x86_pmu is not initialized while the RAPL PMU is. This may, for instance, be the case in virtualized environments.
This patch fixes the problem by using a private sysfs_show() routine for exporting the RAPL PMU events.
--- arch/x86/kernel/cpu/perf_event_intel_rapl.c | 44 +++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-)
arch/x86/kernel/cpu/perf_event_intel_rapl.c +32 -12
@@ -103,6 +103,13 @@ static struct kobj_attribute format_attr_##_var = \#define RAPL_CNTR_WIDTH 32/* 32-bit rapl counters */ +#define RAPL_EVENT_ATTR_STR (_name, v, str) \ +static struct perf_pmu_events_attr event_attr_##v = { \ + .attr = __ATTR(_name, 0444, rapl_sysfs_show, NULL), \ + .id = 0, \ + .event_str = str, \ +}; +struct rapl_pmu {spinlock_t lock;int hw_unit;/* 1/2^hw_unit Joule */
@@ -379,23 +386,36 @@ static struct attribute_group rapl_pmu_attr_group = { .attrs = rapl_pmu_attrs, }; -EVENT_ATTR_STR (energy-cores, rapl_cores,"event=0x01" ); -EVENT_ATTR_STR (energy-pkg , rapl_pkg,"event=0x02" ); -EVENT_ATTR_STR (energy-ram , rapl_ram,"event=0x03" ); -EVENT_ATTR_STR (energy-gpu , rapl_gpu,"event=0x04" ); +static ssize_t rapl_sysfs_show (struct device *dev, +struct device_attribute *attr, +char *page) +{ +struct perf_pmu_events_attr *pmu_attr = \ + container_of(attr, struct perf_pmu_events_attr, attr); + +if (pmu_attr->event_str) +return sprintf (page,"%s" , pmu_attr->event_str); + +return 0 ; +} + +RAPL_EVENT_ATTR_STR (energy-cores, rapl_cores,"event=0x01" ); +RAPL_EVENT_ATTR_STR (energy-pkg , rapl_pkg,"event=0x02" ); +RAPL_EVENT_ATTR_STR (energy-ram , rapl_ram,"event=0x03" ); +RAPL_EVENT_ATTR_STR (energy-gpu , rapl_gpu,"event=0x04" ); -EVENT_ATTR_STR (energy-cores.unit, rapl_cores_unit,"Joules" ); -EVENT_ATTR_STR (energy-pkg.unit , rapl_pkg_unit,"Joules" ); -EVENT_ATTR_STR (energy-ram.unit , rapl_ram_unit,"Joules" ); -EVENT_ATTR_STR (energy-gpu.unit , rapl_gpu_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-cores.unit, rapl_cores_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-pkg.unit , rapl_pkg_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-ram.unit , rapl_ram_unit,"Joules" ); +RAPL_EVENT_ATTR_STR (energy-gpu.unit , rapl_gpu_unit,"Joules" );/* * we compute in 0.23 nJ increments regardless of MSR */ -EVENT_ATTR_STR (energy-cores.scale, rapl_cores_scale,"2.3283064365386962890625e-10" ); -EVENT_ATTR_STR (energy-pkg.scale, rapl_pkg_scale,"2.3283064365386962890625e-10" ); -EVENT_ATTR_STR (energy-ram.scale, rapl_ram_scale,"2.3283064365386962890625e-10" ); -EVENT_ATTR_STR (energy-gpu.scale, rapl_gpu_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-cores.scale, rapl_cores_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-pkg.scale, rapl_pkg_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-ram.scale, rapl_ram_scale,"2.3283064365386962890625e-10" ); +RAPL_EVENT_ATTR_STR (energy-gpu.scale, rapl_gpu_scale,"2.3283064365386962890625e-10" );static struct attribute *rapl_events_srv_attr[] = {EVENT_PTR (rapl_cores),