3636#include "events.h"
3737#include "util.h"
3838
39+
40+ static int
41+ setup_msr_perf_event_attr_type (struct perf_event_attr * attr )
42+ {
43+ const char pmu_type_path [PATH_MAX ] = "/sys/devices/msr/type" ;
44+ FILE * f = NULL ;
45+ char buffer [16 ] = {0 }; /* uint32 expected */
46+ unsigned int pmu_type = 0 ;
47+ int ret = -1 ;
48+
49+ f = fopen (pmu_type_path , "r" );
50+ if (f ) {
51+ if (fgets (buffer , sizeof (buffer ), f )) {
52+ if (!str_to_uint (buffer , & pmu_type )) {
53+ attr -> type = pmu_type ;
54+ ret = 0 ;
55+ }
56+ }
57+
58+ fclose (f );
59+ }
60+
61+ return ret ;
62+ }
63+
64+ static int
65+ setup_msr_perf_event_attr_config (const char * event_name , struct perf_event_attr * attr )
66+ {
67+ /* events config from: https://github.com/torvalds/linux/blob/master/arch/x86/events/msr.c */
68+ const char * msr_events_name [] = {"tsc" , "aperf" , "mperf" , "pperf" , "smi" , "ptsc" , "irperf" , "cpu_thermal_margin" };
69+ const uint64_t msr_events_config [] = {0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 };
70+ const size_t num_msr_events = sizeof (msr_events_name ) / sizeof (msr_events_name [0 ]);
71+ char event_path [PATH_MAX ] = {0 };
72+
73+ for (size_t i = 0 ; i < num_msr_events ; i ++ ) {
74+ if (!strcasecmp (event_name , msr_events_name [i ])) {
75+ snprintf (event_path , PATH_MAX , "/sys/devices/msr/events/%s" , msr_events_name [i ]);
76+ if (!access (event_path , F_OK )) {
77+ attr -> config = msr_events_config [i ];
78+ return 0 ;
79+ }
80+ }
81+ }
82+
83+ return -1 ;
84+ }
85+
86+ static int
87+ get_msr_pmu_event_encoding (const char * event_name , struct perf_event_attr * attr )
88+ {
89+ attr -> size = sizeof (struct perf_event_attr );
90+ attr -> disabled = 1 ;
91+ attr -> read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_GROUP ;
92+
93+ if (setup_msr_perf_event_attr_type (attr )) return -1 ;
94+ if (setup_msr_perf_event_attr_config (event_name , attr )) return -1 ;
95+
96+ return 0 ;
97+ }
98+
3999static int
40100setup_perf_event_attr (const char * event_name , struct perf_event_attr * attr )
41101{
@@ -48,7 +108,10 @@ setup_perf_event_attr(const char *event_name, struct perf_event_attr *attr)
48108 arg .size = sizeof (pfm_perf_encode_arg_t );
49109 arg .attr = attr ;
50110 if (pfm_get_os_event_encoding (event_name , PFM_PLM0 | PFM_PLM3 , PFM_OS_PERF_EVENT_EXT , & arg ) != PFM_SUCCESS ) {
51- return -1 ;
111+ /* fallback to MSR PMU event encoding if libpfm fails */
112+ if (get_msr_pmu_event_encoding (event_name , attr )) {
113+ return -1 ;
114+ }
52115 }
53116
54117 return 0 ;
0 commit comments