xref: /linux/tools/perf/util/record.c (revision e5cadb93d0839d268a7c4199e0fdef0f94722117)
1faf96706SAdrian Hunter #include "evlist.h"
2faf96706SAdrian Hunter #include "evsel.h"
3faf96706SAdrian Hunter #include "cpumap.h"
475562573SAdrian Hunter #include "parse-events.h"
5cd0cfad7SBorislav Petkov #include <api/fs/fs.h>
6714647bdSJiri Olsa #include "util.h"
757480d2cSYann Droneaud #include "cloexec.h"
875562573SAdrian Hunter 
975562573SAdrian Hunter typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
1075562573SAdrian Hunter 
1175562573SAdrian Hunter static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
1275562573SAdrian Hunter {
1375562573SAdrian Hunter 	struct perf_evlist *evlist;
1475562573SAdrian Hunter 	struct perf_evsel *evsel;
1557480d2cSYann Droneaud 	unsigned long flags = perf_event_open_cloexec_flag();
1675562573SAdrian Hunter 	int err = -EAGAIN, fd;
1746ec69adSAdrian Hunter 	static pid_t pid = -1;
1875562573SAdrian Hunter 
1975562573SAdrian Hunter 	evlist = perf_evlist__new();
2075562573SAdrian Hunter 	if (!evlist)
2175562573SAdrian Hunter 		return -ENOMEM;
2275562573SAdrian Hunter 
23b39b8393SJiri Olsa 	if (parse_events(evlist, str, NULL))
2475562573SAdrian Hunter 		goto out_delete;
2575562573SAdrian Hunter 
2675562573SAdrian Hunter 	evsel = perf_evlist__first(evlist);
2775562573SAdrian Hunter 
2846ec69adSAdrian Hunter 	while (1) {
2946ec69adSAdrian Hunter 		fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
3046ec69adSAdrian Hunter 		if (fd < 0) {
3146ec69adSAdrian Hunter 			if (pid == -1 && errno == EACCES) {
3246ec69adSAdrian Hunter 				pid = 0;
3346ec69adSAdrian Hunter 				continue;
3446ec69adSAdrian Hunter 			}
3575562573SAdrian Hunter 			goto out_delete;
3646ec69adSAdrian Hunter 		}
3746ec69adSAdrian Hunter 		break;
3846ec69adSAdrian Hunter 	}
3975562573SAdrian Hunter 	close(fd);
4075562573SAdrian Hunter 
4175562573SAdrian Hunter 	fn(evsel);
4275562573SAdrian Hunter 
4346ec69adSAdrian Hunter 	fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
4475562573SAdrian Hunter 	if (fd < 0) {
4575562573SAdrian Hunter 		if (errno == EINVAL)
4675562573SAdrian Hunter 			err = -EINVAL;
4775562573SAdrian Hunter 		goto out_delete;
4875562573SAdrian Hunter 	}
4975562573SAdrian Hunter 	close(fd);
5075562573SAdrian Hunter 	err = 0;
5175562573SAdrian Hunter 
5275562573SAdrian Hunter out_delete:
5375562573SAdrian Hunter 	perf_evlist__delete(evlist);
5475562573SAdrian Hunter 	return err;
5575562573SAdrian Hunter }
5675562573SAdrian Hunter 
5775562573SAdrian Hunter static bool perf_probe_api(setup_probe_fn_t fn)
5875562573SAdrian Hunter {
59c6fa3565SAdrian Hunter 	const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
6075562573SAdrian Hunter 	struct cpu_map *cpus;
6175562573SAdrian Hunter 	int cpu, ret, i = 0;
6275562573SAdrian Hunter 
6375562573SAdrian Hunter 	cpus = cpu_map__new(NULL);
6475562573SAdrian Hunter 	if (!cpus)
6575562573SAdrian Hunter 		return false;
6675562573SAdrian Hunter 	cpu = cpus->map[0];
67f30a79b0SJiri Olsa 	cpu_map__put(cpus);
6875562573SAdrian Hunter 
6975562573SAdrian Hunter 	do {
7075562573SAdrian Hunter 		ret = perf_do_probe_api(fn, cpu, try[i++]);
7175562573SAdrian Hunter 		if (!ret)
7275562573SAdrian Hunter 			return true;
7375562573SAdrian Hunter 	} while (ret == -EAGAIN && try[i]);
7475562573SAdrian Hunter 
7575562573SAdrian Hunter 	return false;
7675562573SAdrian Hunter }
7775562573SAdrian Hunter 
7875562573SAdrian Hunter static void perf_probe_sample_identifier(struct perf_evsel *evsel)
7975562573SAdrian Hunter {
8075562573SAdrian Hunter 	evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER;
8175562573SAdrian Hunter }
8275562573SAdrian Hunter 
8339e09d40SAdrian Hunter static void perf_probe_comm_exec(struct perf_evsel *evsel)
8439e09d40SAdrian Hunter {
8539e09d40SAdrian Hunter 	evsel->attr.comm_exec = 1;
8639e09d40SAdrian Hunter }
8739e09d40SAdrian Hunter 
88b757bb09SAdrian Hunter static void perf_probe_context_switch(struct perf_evsel *evsel)
89b757bb09SAdrian Hunter {
90b757bb09SAdrian Hunter 	evsel->attr.context_switch = 1;
91b757bb09SAdrian Hunter }
92b757bb09SAdrian Hunter 
9375562573SAdrian Hunter bool perf_can_sample_identifier(void)
9475562573SAdrian Hunter {
9575562573SAdrian Hunter 	return perf_probe_api(perf_probe_sample_identifier);
9675562573SAdrian Hunter }
97faf96706SAdrian Hunter 
9839e09d40SAdrian Hunter static bool perf_can_comm_exec(void)
9939e09d40SAdrian Hunter {
10039e09d40SAdrian Hunter 	return perf_probe_api(perf_probe_comm_exec);
10139e09d40SAdrian Hunter }
10239e09d40SAdrian Hunter 
103b757bb09SAdrian Hunter bool perf_can_record_switch_events(void)
104b757bb09SAdrian Hunter {
105b757bb09SAdrian Hunter 	return perf_probe_api(perf_probe_context_switch);
106b757bb09SAdrian Hunter }
107b757bb09SAdrian Hunter 
10883509565SAdrian Hunter bool perf_can_record_cpu_wide(void)
10983509565SAdrian Hunter {
11083509565SAdrian Hunter 	struct perf_event_attr attr = {
11183509565SAdrian Hunter 		.type = PERF_TYPE_SOFTWARE,
11283509565SAdrian Hunter 		.config = PERF_COUNT_SW_CPU_CLOCK,
11383509565SAdrian Hunter 		.exclude_kernel = 1,
11483509565SAdrian Hunter 	};
11583509565SAdrian Hunter 	struct cpu_map *cpus;
11683509565SAdrian Hunter 	int cpu, fd;
11783509565SAdrian Hunter 
11883509565SAdrian Hunter 	cpus = cpu_map__new(NULL);
11983509565SAdrian Hunter 	if (!cpus)
12083509565SAdrian Hunter 		return false;
12183509565SAdrian Hunter 	cpu = cpus->map[0];
12283509565SAdrian Hunter 	cpu_map__put(cpus);
12383509565SAdrian Hunter 
12483509565SAdrian Hunter 	fd = sys_perf_event_open(&attr, -1, cpu, -1, 0);
12583509565SAdrian Hunter 	if (fd < 0)
12683509565SAdrian Hunter 		return false;
12783509565SAdrian Hunter 	close(fd);
12883509565SAdrian Hunter 
12983509565SAdrian Hunter 	return true;
13083509565SAdrian Hunter }
13183509565SAdrian Hunter 
132e68ae9cfSArnaldo Carvalho de Melo void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
133e68ae9cfSArnaldo Carvalho de Melo 			 struct callchain_param *callchain)
134faf96706SAdrian Hunter {
135faf96706SAdrian Hunter 	struct perf_evsel *evsel;
13675562573SAdrian Hunter 	bool use_sample_identifier = false;
13739e09d40SAdrian Hunter 	bool use_comm_exec;
13875562573SAdrian Hunter 
139faf96706SAdrian Hunter 	/*
140faf96706SAdrian Hunter 	 * Set the evsel leader links before we configure attributes,
141faf96706SAdrian Hunter 	 * since some might depend on this info.
142faf96706SAdrian Hunter 	 */
143faf96706SAdrian Hunter 	if (opts->group)
144faf96706SAdrian Hunter 		perf_evlist__set_leader(evlist);
145faf96706SAdrian Hunter 
146faf96706SAdrian Hunter 	if (evlist->cpus->map[0] < 0)
147faf96706SAdrian Hunter 		opts->no_inherit = true;
148faf96706SAdrian Hunter 
14939e09d40SAdrian Hunter 	use_comm_exec = perf_can_comm_exec();
15039e09d40SAdrian Hunter 
151*e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
152e68ae9cfSArnaldo Carvalho de Melo 		perf_evsel__config(evsel, opts, callchain);
15360b0896cSAdrian Hunter 		if (evsel->tracking && use_comm_exec)
15439e09d40SAdrian Hunter 			evsel->attr.comm_exec = 1;
15539e09d40SAdrian Hunter 	}
156faf96706SAdrian Hunter 
1579e0cc4feSAdrian Hunter 	if (opts->full_auxtrace) {
1589e0cc4feSAdrian Hunter 		/*
1599e0cc4feSAdrian Hunter 		 * Need to be able to synthesize and parse selected events with
1609e0cc4feSAdrian Hunter 		 * arbitrary sample types, which requires always being able to
1619e0cc4feSAdrian Hunter 		 * match the id.
1629e0cc4feSAdrian Hunter 		 */
1639e0cc4feSAdrian Hunter 		use_sample_identifier = perf_can_sample_identifier();
164*e5cadb93SArnaldo Carvalho de Melo 		evlist__for_each_entry(evlist, evsel)
1659e0cc4feSAdrian Hunter 			perf_evsel__set_sample_id(evsel, use_sample_identifier);
1669e0cc4feSAdrian Hunter 	} else if (evlist->nr_entries > 1) {
16775562573SAdrian Hunter 		struct perf_evsel *first = perf_evlist__first(evlist);
16875562573SAdrian Hunter 
169*e5cadb93SArnaldo Carvalho de Melo 		evlist__for_each_entry(evlist, evsel) {
17075562573SAdrian Hunter 			if (evsel->attr.sample_type == first->attr.sample_type)
17175562573SAdrian Hunter 				continue;
17275562573SAdrian Hunter 			use_sample_identifier = perf_can_sample_identifier();
17375562573SAdrian Hunter 			break;
174faf96706SAdrian Hunter 		}
175*e5cadb93SArnaldo Carvalho de Melo 		evlist__for_each_entry(evlist, evsel)
17675562573SAdrian Hunter 			perf_evsel__set_sample_id(evsel, use_sample_identifier);
17775562573SAdrian Hunter 	}
17875562573SAdrian Hunter 
17975562573SAdrian Hunter 	perf_evlist__set_id_pos(evlist);
180faf96706SAdrian Hunter }
181714647bdSJiri Olsa 
182714647bdSJiri Olsa static int get_max_rate(unsigned int *rate)
183714647bdSJiri Olsa {
184ce27309fSArnaldo Carvalho de Melo 	return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate);
185714647bdSJiri Olsa }
186714647bdSJiri Olsa 
187b4006796SArnaldo Carvalho de Melo static int record_opts__config_freq(struct record_opts *opts)
188714647bdSJiri Olsa {
189714647bdSJiri Olsa 	bool user_freq = opts->user_freq != UINT_MAX;
190714647bdSJiri Olsa 	unsigned int max_rate;
191714647bdSJiri Olsa 
192714647bdSJiri Olsa 	if (opts->user_interval != ULLONG_MAX)
193714647bdSJiri Olsa 		opts->default_interval = opts->user_interval;
194714647bdSJiri Olsa 	if (user_freq)
195714647bdSJiri Olsa 		opts->freq = opts->user_freq;
196714647bdSJiri Olsa 
197714647bdSJiri Olsa 	/*
198714647bdSJiri Olsa 	 * User specified count overrides default frequency.
199714647bdSJiri Olsa 	 */
200714647bdSJiri Olsa 	if (opts->default_interval)
201714647bdSJiri Olsa 		opts->freq = 0;
202714647bdSJiri Olsa 	else if (opts->freq) {
203714647bdSJiri Olsa 		opts->default_interval = opts->freq;
204714647bdSJiri Olsa 	} else {
205714647bdSJiri Olsa 		pr_err("frequency and count are zero, aborting\n");
206714647bdSJiri Olsa 		return -1;
207714647bdSJiri Olsa 	}
208714647bdSJiri Olsa 
209714647bdSJiri Olsa 	if (get_max_rate(&max_rate))
210714647bdSJiri Olsa 		return 0;
211714647bdSJiri Olsa 
212714647bdSJiri Olsa 	/*
213714647bdSJiri Olsa 	 * User specified frequency is over current maximum.
214714647bdSJiri Olsa 	 */
215714647bdSJiri Olsa 	if (user_freq && (max_rate < opts->freq)) {
216714647bdSJiri Olsa 		pr_err("Maximum frequency rate (%u) reached.\n"
217714647bdSJiri Olsa 		   "Please use -F freq option with lower value or consider\n"
218714647bdSJiri Olsa 		   "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
219714647bdSJiri Olsa 		   max_rate);
220714647bdSJiri Olsa 		return -1;
221714647bdSJiri Olsa 	}
222714647bdSJiri Olsa 
223714647bdSJiri Olsa 	/*
224714647bdSJiri Olsa 	 * Default frequency is over current maximum.
225714647bdSJiri Olsa 	 */
226714647bdSJiri Olsa 	if (max_rate < opts->freq) {
227714647bdSJiri Olsa 		pr_warning("Lowering default frequency rate to %u.\n"
228714647bdSJiri Olsa 			   "Please consider tweaking "
229714647bdSJiri Olsa 			   "/proc/sys/kernel/perf_event_max_sample_rate.\n",
230714647bdSJiri Olsa 			   max_rate);
231714647bdSJiri Olsa 		opts->freq = max_rate;
232714647bdSJiri Olsa 	}
233714647bdSJiri Olsa 
234714647bdSJiri Olsa 	return 0;
235714647bdSJiri Olsa }
236714647bdSJiri Olsa 
237b4006796SArnaldo Carvalho de Melo int record_opts__config(struct record_opts *opts)
238714647bdSJiri Olsa {
239b4006796SArnaldo Carvalho de Melo 	return record_opts__config_freq(opts);
240714647bdSJiri Olsa }
241c09ec622SAdrian Hunter 
242c09ec622SAdrian Hunter bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
243c09ec622SAdrian Hunter {
244c09ec622SAdrian Hunter 	struct perf_evlist *temp_evlist;
245c09ec622SAdrian Hunter 	struct perf_evsel *evsel;
246c09ec622SAdrian Hunter 	int err, fd, cpu;
247c09ec622SAdrian Hunter 	bool ret = false;
24846ec69adSAdrian Hunter 	pid_t pid = -1;
249c09ec622SAdrian Hunter 
250c09ec622SAdrian Hunter 	temp_evlist = perf_evlist__new();
251c09ec622SAdrian Hunter 	if (!temp_evlist)
252c09ec622SAdrian Hunter 		return false;
253c09ec622SAdrian Hunter 
254b39b8393SJiri Olsa 	err = parse_events(temp_evlist, str, NULL);
255c09ec622SAdrian Hunter 	if (err)
256c09ec622SAdrian Hunter 		goto out_delete;
257c09ec622SAdrian Hunter 
258c09ec622SAdrian Hunter 	evsel = perf_evlist__last(temp_evlist);
259c09ec622SAdrian Hunter 
260c09ec622SAdrian Hunter 	if (!evlist || cpu_map__empty(evlist->cpus)) {
261c09ec622SAdrian Hunter 		struct cpu_map *cpus = cpu_map__new(NULL);
262c09ec622SAdrian Hunter 
263c09ec622SAdrian Hunter 		cpu =  cpus ? cpus->map[0] : 0;
264f30a79b0SJiri Olsa 		cpu_map__put(cpus);
265c09ec622SAdrian Hunter 	} else {
266c09ec622SAdrian Hunter 		cpu = evlist->cpus->map[0];
267c09ec622SAdrian Hunter 	}
268c09ec622SAdrian Hunter 
26946ec69adSAdrian Hunter 	while (1) {
27046ec69adSAdrian Hunter 		fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
27157480d2cSYann Droneaud 					 perf_event_open_cloexec_flag());
27246ec69adSAdrian Hunter 		if (fd < 0) {
27346ec69adSAdrian Hunter 			if (pid == -1 && errno == EACCES) {
27446ec69adSAdrian Hunter 				pid = 0;
27546ec69adSAdrian Hunter 				continue;
27646ec69adSAdrian Hunter 			}
27746ec69adSAdrian Hunter 			goto out_delete;
27846ec69adSAdrian Hunter 		}
27946ec69adSAdrian Hunter 		break;
28046ec69adSAdrian Hunter 	}
281c09ec622SAdrian Hunter 	close(fd);
282c09ec622SAdrian Hunter 	ret = true;
283c09ec622SAdrian Hunter 
284c09ec622SAdrian Hunter out_delete:
285c09ec622SAdrian Hunter 	perf_evlist__delete(temp_evlist);
286c09ec622SAdrian Hunter 	return ret;
287c09ec622SAdrian Hunter }
288