xref: /linux/tools/perf/util/record.c (revision b39b839309ce8c5dd15cd95d26af153fa392c3e6)
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 
23*b39b8393SJiri 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];
6775562573SAdrian Hunter 	cpu_map__delete(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 
8875562573SAdrian Hunter bool perf_can_sample_identifier(void)
8975562573SAdrian Hunter {
9075562573SAdrian Hunter 	return perf_probe_api(perf_probe_sample_identifier);
9175562573SAdrian Hunter }
92faf96706SAdrian Hunter 
9339e09d40SAdrian Hunter static bool perf_can_comm_exec(void)
9439e09d40SAdrian Hunter {
9539e09d40SAdrian Hunter 	return perf_probe_api(perf_probe_comm_exec);
9639e09d40SAdrian Hunter }
9739e09d40SAdrian Hunter 
98b4006796SArnaldo Carvalho de Melo void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
99faf96706SAdrian Hunter {
100faf96706SAdrian Hunter 	struct perf_evsel *evsel;
10175562573SAdrian Hunter 	bool use_sample_identifier = false;
10239e09d40SAdrian Hunter 	bool use_comm_exec;
10375562573SAdrian Hunter 
104faf96706SAdrian Hunter 	/*
105faf96706SAdrian Hunter 	 * Set the evsel leader links before we configure attributes,
106faf96706SAdrian Hunter 	 * since some might depend on this info.
107faf96706SAdrian Hunter 	 */
108faf96706SAdrian Hunter 	if (opts->group)
109faf96706SAdrian Hunter 		perf_evlist__set_leader(evlist);
110faf96706SAdrian Hunter 
111faf96706SAdrian Hunter 	if (evlist->cpus->map[0] < 0)
112faf96706SAdrian Hunter 		opts->no_inherit = true;
113faf96706SAdrian Hunter 
11439e09d40SAdrian Hunter 	use_comm_exec = perf_can_comm_exec();
11539e09d40SAdrian Hunter 
11639e09d40SAdrian Hunter 	evlist__for_each(evlist, evsel) {
117faf96706SAdrian Hunter 		perf_evsel__config(evsel, opts);
11860b0896cSAdrian Hunter 		if (evsel->tracking && use_comm_exec)
11939e09d40SAdrian Hunter 			evsel->attr.comm_exec = 1;
12039e09d40SAdrian Hunter 	}
121faf96706SAdrian Hunter 
1229e0cc4feSAdrian Hunter 	if (opts->full_auxtrace) {
1239e0cc4feSAdrian Hunter 		/*
1249e0cc4feSAdrian Hunter 		 * Need to be able to synthesize and parse selected events with
1259e0cc4feSAdrian Hunter 		 * arbitrary sample types, which requires always being able to
1269e0cc4feSAdrian Hunter 		 * match the id.
1279e0cc4feSAdrian Hunter 		 */
1289e0cc4feSAdrian Hunter 		use_sample_identifier = perf_can_sample_identifier();
1299e0cc4feSAdrian Hunter 		evlist__for_each(evlist, evsel)
1309e0cc4feSAdrian Hunter 			perf_evsel__set_sample_id(evsel, use_sample_identifier);
1319e0cc4feSAdrian Hunter 	} else if (evlist->nr_entries > 1) {
13275562573SAdrian Hunter 		struct perf_evsel *first = perf_evlist__first(evlist);
13375562573SAdrian Hunter 
1340050f7aaSArnaldo Carvalho de Melo 		evlist__for_each(evlist, evsel) {
13575562573SAdrian Hunter 			if (evsel->attr.sample_type == first->attr.sample_type)
13675562573SAdrian Hunter 				continue;
13775562573SAdrian Hunter 			use_sample_identifier = perf_can_sample_identifier();
13875562573SAdrian Hunter 			break;
139faf96706SAdrian Hunter 		}
1400050f7aaSArnaldo Carvalho de Melo 		evlist__for_each(evlist, evsel)
14175562573SAdrian Hunter 			perf_evsel__set_sample_id(evsel, use_sample_identifier);
14275562573SAdrian Hunter 	}
14375562573SAdrian Hunter 
14475562573SAdrian Hunter 	perf_evlist__set_id_pos(evlist);
145faf96706SAdrian Hunter }
146714647bdSJiri Olsa 
147714647bdSJiri Olsa static int get_max_rate(unsigned int *rate)
148714647bdSJiri Olsa {
149ce27309fSArnaldo Carvalho de Melo 	return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate);
150714647bdSJiri Olsa }
151714647bdSJiri Olsa 
152b4006796SArnaldo Carvalho de Melo static int record_opts__config_freq(struct record_opts *opts)
153714647bdSJiri Olsa {
154714647bdSJiri Olsa 	bool user_freq = opts->user_freq != UINT_MAX;
155714647bdSJiri Olsa 	unsigned int max_rate;
156714647bdSJiri Olsa 
157714647bdSJiri Olsa 	if (opts->user_interval != ULLONG_MAX)
158714647bdSJiri Olsa 		opts->default_interval = opts->user_interval;
159714647bdSJiri Olsa 	if (user_freq)
160714647bdSJiri Olsa 		opts->freq = opts->user_freq;
161714647bdSJiri Olsa 
162714647bdSJiri Olsa 	/*
163714647bdSJiri Olsa 	 * User specified count overrides default frequency.
164714647bdSJiri Olsa 	 */
165714647bdSJiri Olsa 	if (opts->default_interval)
166714647bdSJiri Olsa 		opts->freq = 0;
167714647bdSJiri Olsa 	else if (opts->freq) {
168714647bdSJiri Olsa 		opts->default_interval = opts->freq;
169714647bdSJiri Olsa 	} else {
170714647bdSJiri Olsa 		pr_err("frequency and count are zero, aborting\n");
171714647bdSJiri Olsa 		return -1;
172714647bdSJiri Olsa 	}
173714647bdSJiri Olsa 
174714647bdSJiri Olsa 	if (get_max_rate(&max_rate))
175714647bdSJiri Olsa 		return 0;
176714647bdSJiri Olsa 
177714647bdSJiri Olsa 	/*
178714647bdSJiri Olsa 	 * User specified frequency is over current maximum.
179714647bdSJiri Olsa 	 */
180714647bdSJiri Olsa 	if (user_freq && (max_rate < opts->freq)) {
181714647bdSJiri Olsa 		pr_err("Maximum frequency rate (%u) reached.\n"
182714647bdSJiri Olsa 		   "Please use -F freq option with lower value or consider\n"
183714647bdSJiri Olsa 		   "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
184714647bdSJiri Olsa 		   max_rate);
185714647bdSJiri Olsa 		return -1;
186714647bdSJiri Olsa 	}
187714647bdSJiri Olsa 
188714647bdSJiri Olsa 	/*
189714647bdSJiri Olsa 	 * Default frequency is over current maximum.
190714647bdSJiri Olsa 	 */
191714647bdSJiri Olsa 	if (max_rate < opts->freq) {
192714647bdSJiri Olsa 		pr_warning("Lowering default frequency rate to %u.\n"
193714647bdSJiri Olsa 			   "Please consider tweaking "
194714647bdSJiri Olsa 			   "/proc/sys/kernel/perf_event_max_sample_rate.\n",
195714647bdSJiri Olsa 			   max_rate);
196714647bdSJiri Olsa 		opts->freq = max_rate;
197714647bdSJiri Olsa 	}
198714647bdSJiri Olsa 
199714647bdSJiri Olsa 	return 0;
200714647bdSJiri Olsa }
201714647bdSJiri Olsa 
202b4006796SArnaldo Carvalho de Melo int record_opts__config(struct record_opts *opts)
203714647bdSJiri Olsa {
204b4006796SArnaldo Carvalho de Melo 	return record_opts__config_freq(opts);
205714647bdSJiri Olsa }
206c09ec622SAdrian Hunter 
207c09ec622SAdrian Hunter bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
208c09ec622SAdrian Hunter {
209c09ec622SAdrian Hunter 	struct perf_evlist *temp_evlist;
210c09ec622SAdrian Hunter 	struct perf_evsel *evsel;
211c09ec622SAdrian Hunter 	int err, fd, cpu;
212c09ec622SAdrian Hunter 	bool ret = false;
21346ec69adSAdrian Hunter 	pid_t pid = -1;
214c09ec622SAdrian Hunter 
215c09ec622SAdrian Hunter 	temp_evlist = perf_evlist__new();
216c09ec622SAdrian Hunter 	if (!temp_evlist)
217c09ec622SAdrian Hunter 		return false;
218c09ec622SAdrian Hunter 
219*b39b8393SJiri Olsa 	err = parse_events(temp_evlist, str, NULL);
220c09ec622SAdrian Hunter 	if (err)
221c09ec622SAdrian Hunter 		goto out_delete;
222c09ec622SAdrian Hunter 
223c09ec622SAdrian Hunter 	evsel = perf_evlist__last(temp_evlist);
224c09ec622SAdrian Hunter 
225c09ec622SAdrian Hunter 	if (!evlist || cpu_map__empty(evlist->cpus)) {
226c09ec622SAdrian Hunter 		struct cpu_map *cpus = cpu_map__new(NULL);
227c09ec622SAdrian Hunter 
228c09ec622SAdrian Hunter 		cpu =  cpus ? cpus->map[0] : 0;
229c09ec622SAdrian Hunter 		cpu_map__delete(cpus);
230c09ec622SAdrian Hunter 	} else {
231c09ec622SAdrian Hunter 		cpu = evlist->cpus->map[0];
232c09ec622SAdrian Hunter 	}
233c09ec622SAdrian Hunter 
23446ec69adSAdrian Hunter 	while (1) {
23546ec69adSAdrian Hunter 		fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
23657480d2cSYann Droneaud 					 perf_event_open_cloexec_flag());
23746ec69adSAdrian Hunter 		if (fd < 0) {
23846ec69adSAdrian Hunter 			if (pid == -1 && errno == EACCES) {
23946ec69adSAdrian Hunter 				pid = 0;
24046ec69adSAdrian Hunter 				continue;
24146ec69adSAdrian Hunter 			}
24246ec69adSAdrian Hunter 			goto out_delete;
24346ec69adSAdrian Hunter 		}
24446ec69adSAdrian Hunter 		break;
24546ec69adSAdrian Hunter 	}
246c09ec622SAdrian Hunter 	close(fd);
247c09ec622SAdrian Hunter 	ret = true;
248c09ec622SAdrian Hunter 
249c09ec622SAdrian Hunter out_delete:
250c09ec622SAdrian Hunter 	perf_evlist__delete(temp_evlist);
251c09ec622SAdrian Hunter 	return ret;
252c09ec622SAdrian Hunter }
253