11// SPDX-License-Identifier: GPL-2.0
22#include <linux/perf_event.h>
3+ #include <linux/sysfs.h>
34#include <linux/nospec.h>
45#include <asm/intel-family.h>
6+ #include "probe.h"
57
68enum perf_msr_id {
79 PERF_MSR_TSC = 0 ,
@@ -12,32 +14,30 @@ enum perf_msr_id {
1214 PERF_MSR_PTSC = 5 ,
1315 PERF_MSR_IRPERF = 6 ,
1416 PERF_MSR_THERM = 7 ,
15- PERF_MSR_THERM_SNAP = 8 ,
16- PERF_MSR_THERM_UNIT = 9 ,
1717 PERF_MSR_EVENT_MAX ,
1818};
1919
20- static bool test_aperfmperf (int idx )
20+ static bool test_aperfmperf (int idx , void * data )
2121{
2222 return boot_cpu_has (X86_FEATURE_APERFMPERF );
2323}
2424
25- static bool test_ptsc (int idx )
25+ static bool test_ptsc (int idx , void * data )
2626{
2727 return boot_cpu_has (X86_FEATURE_PTSC );
2828}
2929
30- static bool test_irperf (int idx )
30+ static bool test_irperf (int idx , void * data )
3131{
3232 return boot_cpu_has (X86_FEATURE_IRPERF );
3333}
3434
35- static bool test_therm_status (int idx )
35+ static bool test_therm_status (int idx , void * data )
3636{
3737 return boot_cpu_has (X86_FEATURE_DTHERM );
3838}
3939
40- static bool test_intel (int idx )
40+ static bool test_intel (int idx , void * data )
4141{
4242 if (boot_cpu_data .x86_vendor != X86_VENDOR_INTEL ||
4343 boot_cpu_data .x86 != 6 )
@@ -98,37 +98,51 @@ static bool test_intel(int idx)
9898 return false;
9999}
100100
101- struct perf_msr {
102- u64 msr ;
103- struct perf_pmu_events_attr * attr ;
104- bool (* test )(int idx );
101+ PMU_EVENT_ATTR_STRING (tsc , attr_tsc , "event=0x00" );
102+ PMU_EVENT_ATTR_STRING (aperf , attr_aperf , "event=0x01" );
103+ PMU_EVENT_ATTR_STRING (mperf , attr_mperf , "event=0x02" );
104+ PMU_EVENT_ATTR_STRING (pperf , attr_pperf , "event=0x03" );
105+ PMU_EVENT_ATTR_STRING (smi , attr_smi , "event=0x04" );
106+ PMU_EVENT_ATTR_STRING (ptsc , attr_ptsc , "event=0x05" );
107+ PMU_EVENT_ATTR_STRING (irperf , attr_irperf , "event=0x06" );
108+ PMU_EVENT_ATTR_STRING (cpu_thermal_margin , attr_therm , "event=0x07" );
109+ PMU_EVENT_ATTR_STRING (cpu_thermal_margin .snapshot , attr_therm_snap , "1" );
110+ PMU_EVENT_ATTR_STRING (cpu_thermal_margin .unit , attr_therm_unit , "C" );
111+
112+ static unsigned long msr_mask ;
113+
114+ PMU_EVENT_GROUP (events , aperf );
115+ PMU_EVENT_GROUP (events , mperf );
116+ PMU_EVENT_GROUP (events , pperf );
117+ PMU_EVENT_GROUP (events , smi );
118+ PMU_EVENT_GROUP (events , ptsc );
119+ PMU_EVENT_GROUP (events , irperf );
120+
121+ static struct attribute * attrs_therm [] = {
122+ & attr_therm .attr .attr ,
123+ & attr_therm_snap .attr .attr ,
124+ & attr_therm_unit .attr .attr ,
125+ NULL ,
105126};
106127
107- PMU_EVENT_ATTR_STRING (tsc , evattr_tsc , "event=0x00" );
108- PMU_EVENT_ATTR_STRING (aperf , evattr_aperf , "event=0x01" );
109- PMU_EVENT_ATTR_STRING (mperf , evattr_mperf , "event=0x02" );
110- PMU_EVENT_ATTR_STRING (pperf , evattr_pperf , "event=0x03" );
111- PMU_EVENT_ATTR_STRING (smi , evattr_smi , "event=0x04" );
112- PMU_EVENT_ATTR_STRING (ptsc , evattr_ptsc , "event=0x05" );
113- PMU_EVENT_ATTR_STRING (irperf , evattr_irperf , "event=0x06" );
114- PMU_EVENT_ATTR_STRING (cpu_thermal_margin , evattr_therm , "event=0x07" );
115- PMU_EVENT_ATTR_STRING (cpu_thermal_margin .snapshot , evattr_therm_snap , "1" );
116- PMU_EVENT_ATTR_STRING (cpu_thermal_margin .unit , evattr_therm_unit , "C" );
128+ static struct attribute_group group_therm = {
129+ .name = "events" ,
130+ .attrs = attrs_therm ,
131+ };
117132
118133static struct perf_msr msr [] = {
119- [PERF_MSR_TSC ] = { 0 , & evattr_tsc , NULL , },
120- [PERF_MSR_APERF ] = { MSR_IA32_APERF , & evattr_aperf , test_aperfmperf , },
121- [PERF_MSR_MPERF ] = { MSR_IA32_MPERF , & evattr_mperf , test_aperfmperf , },
122- [PERF_MSR_PPERF ] = { MSR_PPERF , & evattr_pperf , test_intel , },
123- [PERF_MSR_SMI ] = { MSR_SMI_COUNT , & evattr_smi , test_intel , },
124- [PERF_MSR_PTSC ] = { MSR_F15H_PTSC , & evattr_ptsc , test_ptsc , },
125- [PERF_MSR_IRPERF ] = { MSR_F17H_IRPERF , & evattr_irperf , test_irperf , },
126- [PERF_MSR_THERM ] = { MSR_IA32_THERM_STATUS , & evattr_therm , test_therm_status , },
127- [PERF_MSR_THERM_SNAP ] = { MSR_IA32_THERM_STATUS , & evattr_therm_snap , test_therm_status , },
128- [PERF_MSR_THERM_UNIT ] = { MSR_IA32_THERM_STATUS , & evattr_therm_unit , test_therm_status , },
134+ [PERF_MSR_TSC ] = { .no_check = true, },
135+ [PERF_MSR_APERF ] = { MSR_IA32_APERF , & group_aperf , test_aperfmperf , },
136+ [PERF_MSR_MPERF ] = { MSR_IA32_MPERF , & group_mperf , test_aperfmperf , },
137+ [PERF_MSR_PPERF ] = { MSR_PPERF , & group_pperf , test_intel , },
138+ [PERF_MSR_SMI ] = { MSR_SMI_COUNT , & group_smi , test_intel , },
139+ [PERF_MSR_PTSC ] = { MSR_F15H_PTSC , & group_ptsc , test_ptsc , },
140+ [PERF_MSR_IRPERF ] = { MSR_F17H_IRPERF , & group_irperf , test_irperf , },
141+ [PERF_MSR_THERM ] = { MSR_IA32_THERM_STATUS , & group_therm , test_therm_status , },
129142};
130143
131- static struct attribute * events_attrs [PERF_MSR_EVENT_MAX + 1 ] = {
144+ static struct attribute * events_attrs [] = {
145+ & attr_tsc .attr .attr ,
132146 NULL ,
133147};
134148
@@ -153,6 +167,17 @@ static const struct attribute_group *attr_groups[] = {
153167 NULL ,
154168};
155169
170+ const struct attribute_group * attr_update [] = {
171+ & group_aperf ,
172+ & group_mperf ,
173+ & group_pperf ,
174+ & group_smi ,
175+ & group_ptsc ,
176+ & group_irperf ,
177+ & group_therm ,
178+ NULL ,
179+ };
180+
156181static int msr_event_init (struct perf_event * event )
157182{
158183 u64 cfg = event -> attr .config ;
@@ -169,7 +194,7 @@ static int msr_event_init(struct perf_event *event)
169194
170195 cfg = array_index_nospec ((unsigned long )cfg , PERF_MSR_EVENT_MAX );
171196
172- if (!msr [ cfg ]. attr )
197+ if (!( msr_mask & ( 1 << cfg )) )
173198 return - EINVAL ;
174199
175200 event -> hw .idx = -1 ;
@@ -252,32 +277,17 @@ static struct pmu pmu_msr = {
252277 .stop = msr_event_stop ,
253278 .read = msr_event_update ,
254279 .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE ,
280+ .attr_update = attr_update ,
255281};
256282
257283static int __init msr_init (void )
258284{
259- int i , j = 0 ;
260-
261285 if (!boot_cpu_has (X86_FEATURE_TSC )) {
262286 pr_cont ("no MSR PMU driver.\n" );
263287 return 0 ;
264288 }
265289
266- /* Probe the MSRs. */
267- for (i = PERF_MSR_TSC + 1 ; i < PERF_MSR_EVENT_MAX ; i ++ ) {
268- u64 val ;
269-
270- /* Virt sucks; you cannot tell if a R/O MSR is present :/ */
271- if (!msr [i ].test (i ) || rdmsrl_safe (msr [i ].msr , & val ))
272- msr [i ].attr = NULL ;
273- }
274-
275- /* List remaining MSRs in the sysfs attrs. */
276- for (i = 0 ; i < PERF_MSR_EVENT_MAX ; i ++ ) {
277- if (msr [i ].attr )
278- events_attrs [j ++ ] = & msr [i ].attr -> attr .attr ;
279- }
280- events_attrs [j ] = NULL ;
290+ msr_mask = perf_msr_probe (msr , PERF_MSR_EVENT_MAX , true, NULL );
281291
282292 perf_pmu_register (& pmu_msr , "msr" , -1 );
283293
0 commit comments