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