1 // SPDX-License-Identifier: GPL-2.0 2 #include "debug.h" 3 #include "evlist.h" 4 #include "evsel.h" 5 #include "cpumap.h" 6 #include "parse-events.h" 7 #include <errno.h> 8 #include <limits.h> 9 #include <stdlib.h> 10 #include <api/fs/fs.h> 11 #include <subcmd/parse-options.h> 12 #include <perf/cpumap.h> 13 #include "util.h" 14 #include "cloexec.h" 15 #include "record.h" 16 #include "../perf-sys.h" 17 18 typedef void (*setup_probe_fn_t)(struct evsel *evsel); 19 20 static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) 21 { 22 struct evlist *evlist; 23 struct evsel *evsel; 24 unsigned long flags = perf_event_open_cloexec_flag(); 25 int err = -EAGAIN, fd; 26 static pid_t pid = -1; 27 28 evlist = evlist__new(); 29 if (!evlist) 30 return -ENOMEM; 31 32 if (parse_events(evlist, str, NULL)) 33 goto out_delete; 34 35 evsel = perf_evlist__first(evlist); 36 37 while (1) { 38 fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags); 39 if (fd < 0) { 40 if (pid == -1 && errno == EACCES) { 41 pid = 0; 42 continue; 43 } 44 goto out_delete; 45 } 46 break; 47 } 48 close(fd); 49 50 fn(evsel); 51 52 fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, flags); 53 if (fd < 0) { 54 if (errno == EINVAL) 55 err = -EINVAL; 56 goto out_delete; 57 } 58 close(fd); 59 err = 0; 60 61 out_delete: 62 evlist__delete(evlist); 63 return err; 64 } 65 66 static bool perf_probe_api(setup_probe_fn_t fn) 67 { 68 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL}; 69 struct perf_cpu_map *cpus; 70 int cpu, ret, i = 0; 71 72 cpus = perf_cpu_map__new(NULL); 73 if (!cpus) 74 return false; 75 cpu = cpus->map[0]; 76 perf_cpu_map__put(cpus); 77 78 do { 79 ret = perf_do_probe_api(fn, cpu, try[i++]); 80 if (!ret) 81 return true; 82 } while (ret == -EAGAIN && try[i]); 83 84 return false; 85 } 86 87 static void perf_probe_sample_identifier(struct evsel *evsel) 88 { 89 evsel->core.attr.sample_type |= PERF_SAMPLE_IDENTIFIER; 90 } 91 92 static void perf_probe_comm_exec(struct evsel *evsel) 93 { 94 evsel->core.attr.comm_exec = 1; 95 } 96 97 static void perf_probe_context_switch(struct evsel *evsel) 98 { 99 evsel->core.attr.context_switch = 1; 100 } 101 102 bool perf_can_sample_identifier(void) 103 { 104 return perf_probe_api(perf_probe_sample_identifier); 105 } 106 107 static bool perf_can_comm_exec(void) 108 { 109 return perf_probe_api(perf_probe_comm_exec); 110 } 111 112 bool perf_can_record_switch_events(void) 113 { 114 return perf_probe_api(perf_probe_context_switch); 115 } 116 117 bool perf_can_record_cpu_wide(void) 118 { 119 struct perf_event_attr attr = { 120 .type = PERF_TYPE_SOFTWARE, 121 .config = PERF_COUNT_SW_CPU_CLOCK, 122 .exclude_kernel = 1, 123 }; 124 struct perf_cpu_map *cpus; 125 int cpu, fd; 126 127 cpus = perf_cpu_map__new(NULL); 128 if (!cpus) 129 return false; 130 cpu = cpus->map[0]; 131 perf_cpu_map__put(cpus); 132 133 fd = sys_perf_event_open(&attr, -1, cpu, -1, 0); 134 if (fd < 0) 135 return false; 136 close(fd); 137 138 return true; 139 } 140 141 void perf_evlist__config(struct evlist *evlist, struct record_opts *opts, 142 struct callchain_param *callchain) 143 { 144 struct evsel *evsel; 145 bool use_sample_identifier = false; 146 bool use_comm_exec; 147 bool sample_id = opts->sample_id; 148 149 /* 150 * Set the evsel leader links before we configure attributes, 151 * since some might depend on this info. 152 */ 153 if (opts->group) 154 perf_evlist__set_leader(evlist); 155 156 if (evlist->core.cpus->map[0] < 0) 157 opts->no_inherit = true; 158 159 use_comm_exec = perf_can_comm_exec(); 160 161 evlist__for_each_entry(evlist, evsel) { 162 perf_evsel__config(evsel, opts, callchain); 163 if (evsel->tracking && use_comm_exec) 164 evsel->core.attr.comm_exec = 1; 165 } 166 167 if (opts->full_auxtrace) { 168 /* 169 * Need to be able to synthesize and parse selected events with 170 * arbitrary sample types, which requires always being able to 171 * match the id. 172 */ 173 use_sample_identifier = perf_can_sample_identifier(); 174 sample_id = true; 175 } else if (evlist->core.nr_entries > 1) { 176 struct evsel *first = perf_evlist__first(evlist); 177 178 evlist__for_each_entry(evlist, evsel) { 179 if (evsel->core.attr.sample_type == first->core.attr.sample_type) 180 continue; 181 use_sample_identifier = perf_can_sample_identifier(); 182 break; 183 } 184 sample_id = true; 185 } 186 187 if (sample_id) { 188 evlist__for_each_entry(evlist, evsel) 189 perf_evsel__set_sample_id(evsel, use_sample_identifier); 190 } 191 192 perf_evlist__set_id_pos(evlist); 193 } 194 195 static int get_max_rate(unsigned int *rate) 196 { 197 return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate); 198 } 199 200 static int record_opts__config_freq(struct record_opts *opts) 201 { 202 bool user_freq = opts->user_freq != UINT_MAX; 203 unsigned int max_rate; 204 205 if (opts->user_interval != ULLONG_MAX) 206 opts->default_interval = opts->user_interval; 207 if (user_freq) 208 opts->freq = opts->user_freq; 209 210 /* 211 * User specified count overrides default frequency. 212 */ 213 if (opts->default_interval) 214 opts->freq = 0; 215 else if (opts->freq) { 216 opts->default_interval = opts->freq; 217 } else { 218 pr_err("frequency and count are zero, aborting\n"); 219 return -1; 220 } 221 222 if (get_max_rate(&max_rate)) 223 return 0; 224 225 /* 226 * User specified frequency is over current maximum. 227 */ 228 if (user_freq && (max_rate < opts->freq)) { 229 if (opts->strict_freq) { 230 pr_err("error: Maximum frequency rate (%'u Hz) exceeded.\n" 231 " Please use -F freq option with a lower value or consider\n" 232 " tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", 233 max_rate); 234 return -1; 235 } else { 236 pr_warning("warning: Maximum frequency rate (%'u Hz) exceeded, throttling from %'u Hz to %'u Hz.\n" 237 " The limit can be raised via /proc/sys/kernel/perf_event_max_sample_rate.\n" 238 " The kernel will lower it when perf's interrupts take too long.\n" 239 " Use --strict-freq to disable this throttling, refusing to record.\n", 240 max_rate, opts->freq, max_rate); 241 242 opts->freq = max_rate; 243 } 244 } 245 246 /* 247 * Default frequency is over current maximum. 248 */ 249 if (max_rate < opts->freq) { 250 pr_warning("Lowering default frequency rate to %u.\n" 251 "Please consider tweaking " 252 "/proc/sys/kernel/perf_event_max_sample_rate.\n", 253 max_rate); 254 opts->freq = max_rate; 255 } 256 257 return 0; 258 } 259 260 int record_opts__config(struct record_opts *opts) 261 { 262 return record_opts__config_freq(opts); 263 } 264 265 bool perf_evlist__can_select_event(struct evlist *evlist, const char *str) 266 { 267 struct evlist *temp_evlist; 268 struct evsel *evsel; 269 int err, fd, cpu; 270 bool ret = false; 271 pid_t pid = -1; 272 273 temp_evlist = evlist__new(); 274 if (!temp_evlist) 275 return false; 276 277 err = parse_events(temp_evlist, str, NULL); 278 if (err) 279 goto out_delete; 280 281 evsel = perf_evlist__last(temp_evlist); 282 283 if (!evlist || perf_cpu_map__empty(evlist->core.cpus)) { 284 struct perf_cpu_map *cpus = perf_cpu_map__new(NULL); 285 286 cpu = cpus ? cpus->map[0] : 0; 287 perf_cpu_map__put(cpus); 288 } else { 289 cpu = evlist->core.cpus->map[0]; 290 } 291 292 while (1) { 293 fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1, 294 perf_event_open_cloexec_flag()); 295 if (fd < 0) { 296 if (pid == -1 && errno == EACCES) { 297 pid = 0; 298 continue; 299 } 300 goto out_delete; 301 } 302 break; 303 } 304 close(fd); 305 ret = true; 306 307 out_delete: 308 evlist__delete(temp_evlist); 309 return ret; 310 } 311 312 int record__parse_freq(const struct option *opt, const char *str, int unset __maybe_unused) 313 { 314 unsigned int freq; 315 struct record_opts *opts = opt->value; 316 317 if (!str) 318 return -EINVAL; 319 320 if (strcasecmp(str, "max") == 0) { 321 if (get_max_rate(&freq)) { 322 pr_err("couldn't read /proc/sys/kernel/perf_event_max_sample_rate\n"); 323 return -1; 324 } 325 pr_info("info: Using a maximum frequency rate of %'d Hz\n", freq); 326 } else { 327 freq = atoi(str); 328 } 329 330 opts->user_freq = freq; 331 return 0; 332 } 333