xref: /openbmc/linux/tools/perf/builtin-record.c (revision 2711926a416733b853977a0e014c713955ad0d8a)
186470930SIngo Molnar /*
286470930SIngo Molnar  * builtin-record.c
386470930SIngo Molnar  *
486470930SIngo Molnar  * Builtin record command: Record the profile of a workload
586470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
686470930SIngo Molnar  * later analysis via perf report.
786470930SIngo Molnar  */
8b8f46c5aSXiao Guangrong #define _FILE_OFFSET_BITS 64
9b8f46c5aSXiao Guangrong 
1086470930SIngo Molnar #include "builtin.h"
1186470930SIngo Molnar 
1286470930SIngo Molnar #include "perf.h"
1386470930SIngo Molnar 
146122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1586470930SIngo Molnar #include "util/util.h"
1686470930SIngo Molnar #include "util/parse-options.h"
1786470930SIngo Molnar #include "util/parse-events.h"
1886470930SIngo Molnar 
197c6a1c65SPeter Zijlstra #include "util/header.h"
2066e274f3SFrederic Weisbecker #include "util/event.h"
21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
238f28827aSFrederic Weisbecker #include "util/debug.h"
2494c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
27a12b51c4SPaul Mackerras #include "util/cpumap.h"
28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
297c6a1c65SPeter Zijlstra 
3086470930SIngo Molnar #include <unistd.h>
3186470930SIngo Molnar #include <sched.h>
32a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
3386470930SIngo Molnar 
3478da39faSBernhard Rosenkraenzer #ifndef HAVE_ON_EXIT
3578da39faSBernhard Rosenkraenzer #ifndef ATEXIT_MAX
3678da39faSBernhard Rosenkraenzer #define ATEXIT_MAX 32
3778da39faSBernhard Rosenkraenzer #endif
3878da39faSBernhard Rosenkraenzer static int __on_exit_count = 0;
3978da39faSBernhard Rosenkraenzer typedef void (*on_exit_func_t) (int, void *);
4078da39faSBernhard Rosenkraenzer static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
4178da39faSBernhard Rosenkraenzer static void *__on_exit_args[ATEXIT_MAX];
4278da39faSBernhard Rosenkraenzer static int __exitcode = 0;
4378da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void);
4478da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg);
4578da39faSBernhard Rosenkraenzer #define exit(x) (exit)(__exitcode = (x))
4678da39faSBernhard Rosenkraenzer 
4778da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg)
4878da39faSBernhard Rosenkraenzer {
4978da39faSBernhard Rosenkraenzer 	if (__on_exit_count == ATEXIT_MAX)
5078da39faSBernhard Rosenkraenzer 		return -ENOMEM;
5178da39faSBernhard Rosenkraenzer 	else if (__on_exit_count == 0)
5278da39faSBernhard Rosenkraenzer 		atexit(__handle_on_exit_funcs);
5378da39faSBernhard Rosenkraenzer 	__on_exit_funcs[__on_exit_count] = function;
5478da39faSBernhard Rosenkraenzer 	__on_exit_args[__on_exit_count++] = arg;
5578da39faSBernhard Rosenkraenzer 	return 0;
5678da39faSBernhard Rosenkraenzer }
5778da39faSBernhard Rosenkraenzer 
5878da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void)
5978da39faSBernhard Rosenkraenzer {
6078da39faSBernhard Rosenkraenzer 	int i;
6178da39faSBernhard Rosenkraenzer 	for (i = 0; i < __on_exit_count; i++)
6278da39faSBernhard Rosenkraenzer 		__on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
6378da39faSBernhard Rosenkraenzer }
6478da39faSBernhard Rosenkraenzer #endif
6578da39faSBernhard Rosenkraenzer 
667865e817SFrederic Weisbecker enum write_mode_t {
677865e817SFrederic Weisbecker 	WRITE_FORCE,
687865e817SFrederic Weisbecker 	WRITE_APPEND
697865e817SFrederic Weisbecker };
707865e817SFrederic Weisbecker 
71d20deb64SArnaldo Carvalho de Melo struct perf_record {
7245694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
73d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts	opts;
74d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
75d20deb64SArnaldo Carvalho de Melo 	const char		*output_name;
76d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
77d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
78d20deb64SArnaldo Carvalho de Melo 	const char		*progname;
79d20deb64SArnaldo Carvalho de Melo 	int			output;
80d20deb64SArnaldo Carvalho de Melo 	unsigned int		page_size;
81d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
82d20deb64SArnaldo Carvalho de Melo 	enum write_mode_t	write_mode;
83d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
84d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
85d20deb64SArnaldo Carvalho de Melo 	bool			force;
86d20deb64SArnaldo Carvalho de Melo 	bool			file_new;
87d20deb64SArnaldo Carvalho de Melo 	bool			append_file;
88d20deb64SArnaldo Carvalho de Melo 	long			samples;
89d20deb64SArnaldo Carvalho de Melo 	off_t			post_processing_offset;
900f82ebc4SArnaldo Carvalho de Melo };
9186470930SIngo Molnar 
92d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size)
939215545eSTom Zanussi {
94d20deb64SArnaldo Carvalho de Melo 	rec->bytes_written += size;
959215545eSTom Zanussi }
969215545eSTom Zanussi 
978d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size)
98f5970550SPeter Zijlstra {
99f5970550SPeter Zijlstra 	while (size) {
100d20deb64SArnaldo Carvalho de Melo 		int ret = write(rec->output, buf, size);
101f5970550SPeter Zijlstra 
1028d3eca20SDavid Ahern 		if (ret < 0) {
1038d3eca20SDavid Ahern 			pr_err("failed to write\n");
1048d3eca20SDavid Ahern 			return -1;
1058d3eca20SDavid Ahern 		}
106f5970550SPeter Zijlstra 
107f5970550SPeter Zijlstra 		size -= ret;
108f5970550SPeter Zijlstra 		buf += ret;
109f5970550SPeter Zijlstra 
110d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written += ret;
111f5970550SPeter Zijlstra 	}
1128d3eca20SDavid Ahern 
1138d3eca20SDavid Ahern 	return 0;
114f5970550SPeter Zijlstra }
115f5970550SPeter Zijlstra 
11645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
117d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
1181d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
1191d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
120234fbbf5SArnaldo Carvalho de Melo {
12145694aa7SArnaldo Carvalho de Melo 	struct perf_record *rec = container_of(tool, struct perf_record, tool);
1228d3eca20SDavid Ahern 	if (write_output(rec, event, event->header.size) < 0)
1238d3eca20SDavid Ahern 		return -1;
1248d3eca20SDavid Ahern 
125234fbbf5SArnaldo Carvalho de Melo 	return 0;
126234fbbf5SArnaldo Carvalho de Melo }
127234fbbf5SArnaldo Carvalho de Melo 
1288d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec,
129d20deb64SArnaldo Carvalho de Melo 				   struct perf_mmap *md)
13086470930SIngo Molnar {
131744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
13286470930SIngo Molnar 	unsigned int old = md->prev;
133d20deb64SArnaldo Carvalho de Melo 	unsigned char *data = md->base + rec->page_size;
13486470930SIngo Molnar 	unsigned long size;
13586470930SIngo Molnar 	void *buf;
1368d3eca20SDavid Ahern 	int rc = 0;
13786470930SIngo Molnar 
138dc82009aSArnaldo Carvalho de Melo 	if (old == head)
1398d3eca20SDavid Ahern 		return 0;
14086470930SIngo Molnar 
141d20deb64SArnaldo Carvalho de Melo 	rec->samples++;
14286470930SIngo Molnar 
14386470930SIngo Molnar 	size = head - old;
14486470930SIngo Molnar 
14586470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
14686470930SIngo Molnar 		buf = &data[old & md->mask];
14786470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
14886470930SIngo Molnar 		old += size;
14986470930SIngo Molnar 
1508d3eca20SDavid Ahern 		if (write_output(rec, buf, size) < 0) {
1518d3eca20SDavid Ahern 			rc = -1;
1528d3eca20SDavid Ahern 			goto out;
1538d3eca20SDavid Ahern 		}
15486470930SIngo Molnar 	}
15586470930SIngo Molnar 
15686470930SIngo Molnar 	buf = &data[old & md->mask];
15786470930SIngo Molnar 	size = head - old;
15886470930SIngo Molnar 	old += size;
15986470930SIngo Molnar 
1608d3eca20SDavid Ahern 	if (write_output(rec, buf, size) < 0) {
1618d3eca20SDavid Ahern 		rc = -1;
1628d3eca20SDavid Ahern 		goto out;
1638d3eca20SDavid Ahern 	}
16486470930SIngo Molnar 
16586470930SIngo Molnar 	md->prev = old;
166115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
1678d3eca20SDavid Ahern 
1688d3eca20SDavid Ahern out:
1698d3eca20SDavid Ahern 	return rc;
17086470930SIngo Molnar }
17186470930SIngo Molnar 
17286470930SIngo Molnar static volatile int done = 0;
173f7b7c26eSPeter Zijlstra static volatile int signr = -1;
17433e49ea7SAndi Kleen static volatile int child_finished = 0;
17586470930SIngo Molnar 
17686470930SIngo Molnar static void sig_handler(int sig)
17786470930SIngo Molnar {
17833e49ea7SAndi Kleen 	if (sig == SIGCHLD)
17933e49ea7SAndi Kleen 		child_finished = 1;
18033e49ea7SAndi Kleen 
18186470930SIngo Molnar 	done = 1;
182f7b7c26eSPeter Zijlstra 	signr = sig;
183f7b7c26eSPeter Zijlstra }
184f7b7c26eSPeter Zijlstra 
1851d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
186f7b7c26eSPeter Zijlstra {
187d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
18833e49ea7SAndi Kleen 	int status;
18933e49ea7SAndi Kleen 
190d20deb64SArnaldo Carvalho de Melo 	if (rec->evlist->workload.pid > 0) {
19133e49ea7SAndi Kleen 		if (!child_finished)
192d20deb64SArnaldo Carvalho de Melo 			kill(rec->evlist->workload.pid, SIGTERM);
193933da83aSChris Wilson 
19433e49ea7SAndi Kleen 		wait(&status);
19533e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
196d20deb64SArnaldo Carvalho de Melo 			psignal(WTERMSIG(status), rec->progname);
19733e49ea7SAndi Kleen 	}
19833e49ea7SAndi Kleen 
19918483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
200f7b7c26eSPeter Zijlstra 		return;
201f7b7c26eSPeter Zijlstra 
202f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
203f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
20486470930SIngo Molnar }
20586470930SIngo Molnar 
206a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
207a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
208a91e5431SArnaldo Carvalho de Melo {
209a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
210a91e5431SArnaldo Carvalho de Melo 
211a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
212a91e5431SArnaldo Carvalho de Melo 		return false;
213a91e5431SArnaldo Carvalho de Melo 
2140c21f736SArnaldo Carvalho de Melo 	pair = perf_evlist__first(other);
215a91e5431SArnaldo Carvalho de Melo 
216a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
217a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
218a91e5431SArnaldo Carvalho de Melo 			return false;
2190c21f736SArnaldo Carvalho de Melo 		pair = perf_evsel__next(pair);
220a91e5431SArnaldo Carvalho de Melo 	}
221a91e5431SArnaldo Carvalho de Melo 
222a91e5431SArnaldo Carvalho de Melo 	return true;
223a91e5431SArnaldo Carvalho de Melo }
224a91e5431SArnaldo Carvalho de Melo 
2258d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec)
226dd7927f4SArnaldo Carvalho de Melo {
2276a4bb04cSJiri Olsa 	struct perf_evsel *pos;
228d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
229d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
230d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
2318d3eca20SDavid Ahern 	int rc = 0;
232dd7927f4SArnaldo Carvalho de Melo 
233cac21425SJiri Olsa 	/*
234cac21425SJiri Olsa 	 * Set the evsel leader links before we configure attributes,
235cac21425SJiri Olsa 	 * since some might depend on this info.
236cac21425SJiri Olsa 	 */
2376a4bb04cSJiri Olsa 	if (opts->group)
23863dab225SArnaldo Carvalho de Melo 		perf_evlist__set_leader(evlist);
2396a4bb04cSJiri Olsa 
240cac21425SJiri Olsa 	perf_evlist__config_attrs(evlist, opts);
241cac21425SJiri Olsa 
242dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
243dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
244dd7927f4SArnaldo Carvalho de Melo 		/*
245dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
246dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
247dd7927f4SArnaldo Carvalho de Melo 		 *
248dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
249dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
250dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
251dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
252dd7927f4SArnaldo Carvalho de Melo 		 *
253dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
254dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
255dd7927f4SArnaldo Carvalho de Melo 		 */
256dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
257dd7927f4SArnaldo Carvalho de Melo 
2580c978128SArnaldo Carvalho de Melo fallback_missing_features:
2590c978128SArnaldo Carvalho de Melo 		if (opts->exclude_guest_missing)
2600c978128SArnaldo Carvalho de Melo 			attr->exclude_guest = attr->exclude_host = 0;
2619c90a61cSArnaldo Carvalho de Melo retry_sample_id:
262808e1226SArnaldo Carvalho de Melo 		attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
2633da297a6SIngo Molnar try_again:
2646a4bb04cSJiri Olsa 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
26586470930SIngo Molnar 			int err = errno;
26686470930SIngo Molnar 
267c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
268b8631e6eSArnaldo Carvalho de Melo 				ui__error_paranoid();
2698d3eca20SDavid Ahern 				rc = -err;
2708d3eca20SDavid Ahern 				goto out;
271bea03405SNamhyung Kim 			} else if (err ==  ENODEV && opts->target.cpu_list) {
2728d3eca20SDavid Ahern 				pr_err("No such device - did you specify"
273d6d901c2SZhang, Yanmin 				       " an out-of-range profile CPU?\n");
2748d3eca20SDavid Ahern 				rc = -err;
2758d3eca20SDavid Ahern 				goto out;
2760c978128SArnaldo Carvalho de Melo 			} else if (err == EINVAL) {
2770c978128SArnaldo Carvalho de Melo 				if (!opts->exclude_guest_missing &&
2780c978128SArnaldo Carvalho de Melo 				    (attr->exclude_guest || attr->exclude_host)) {
2790c978128SArnaldo Carvalho de Melo 					pr_debug("Old kernel, cannot exclude "
2800c978128SArnaldo Carvalho de Melo 						 "guest or host samples.\n");
2810c978128SArnaldo Carvalho de Melo 					opts->exclude_guest_missing = true;
2820c978128SArnaldo Carvalho de Melo 					goto fallback_missing_features;
283808e1226SArnaldo Carvalho de Melo 				} else if (!opts->sample_id_all_missing) {
2849c90a61cSArnaldo Carvalho de Melo 					/*
2859c90a61cSArnaldo Carvalho de Melo 					 * Old kernel, no attr->sample_id_type_all field
2869c90a61cSArnaldo Carvalho de Melo 					 */
287808e1226SArnaldo Carvalho de Melo 					opts->sample_id_all_missing = true;
288d20deb64SArnaldo Carvalho de Melo 					if (!opts->sample_time && !opts->raw_samples && !time_needed)
289eac23d1cSIan Munsie 						attr->sample_type &= ~PERF_SAMPLE_TIME;
290eac23d1cSIan Munsie 
2919c90a61cSArnaldo Carvalho de Melo 					goto retry_sample_id;
292d6d901c2SZhang, Yanmin 				}
2930c978128SArnaldo Carvalho de Melo 			}
2943da297a6SIngo Molnar 
2953da297a6SIngo Molnar 			/*
2963da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
2973da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
298028d455bSDavid Ahern 			 * is always available even if no PMU support.
299028d455bSDavid Ahern 			 *
300028d455bSDavid Ahern 			 * PPC returns ENXIO until 2.6.37 (behavior changed
301028d455bSDavid Ahern 			 * with commit b0a873e).
3023da297a6SIngo Molnar 			 */
303028d455bSDavid Ahern 			if ((err == ENOENT || err == ENXIO)
304028d455bSDavid Ahern 					&& attr->type == PERF_TYPE_HARDWARE
305f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
3063da297a6SIngo Molnar 
3073da297a6SIngo Molnar 				if (verbose)
308ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
309ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
3103da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
311f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
312d1cae34dSDavid Ahern 				if (pos->name) {
313d1cae34dSDavid Ahern 					free(pos->name);
314d1cae34dSDavid Ahern 					pos->name = NULL;
315d1cae34dSDavid Ahern 				}
3163da297a6SIngo Molnar 				goto try_again;
3173da297a6SIngo Molnar 			}
318ca6a4258SDavid Ahern 
319ca6a4258SDavid Ahern 			if (err == ENOENT) {
3203780f488SNamhyung Kim 				ui__error("The %s event is not supported.\n",
3217289f83cSArnaldo Carvalho de Melo 					  perf_evsel__name(pos));
3228d3eca20SDavid Ahern 				rc = -err;
3238d3eca20SDavid Ahern 				goto out;
3242305c82fSDavid Ahern 			} else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
3252305c82fSDavid Ahern 				ui__error("\'precise\' request may not be supported. "
3262305c82fSDavid Ahern 					  "Try removing 'p' modifier\n");
3272305c82fSDavid Ahern 				rc = -err;
3282305c82fSDavid Ahern 				goto out;
329ca6a4258SDavid Ahern 			}
330ca6a4258SDavid Ahern 
33130c806a0SIngo Molnar 			printf("\n");
3321863fbbbSStephane Eranian 			error("sys_perf_event_open() syscall returned with %d "
3331863fbbbSStephane Eranian 			      "(%s) for event %s. /bin/dmesg may provide "
3341863fbbbSStephane Eranian 			      "additional information.\n",
3351863fbbbSStephane Eranian 			      err, strerror(err), perf_evsel__name(pos));
336bfd45118SSimon Kaempflein 
337bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
3388d3eca20SDavid Ahern 			if (attr->type == PERF_TYPE_HARDWARE &&
3398d3eca20SDavid Ahern 			    err == EOPNOTSUPP) {
3408d3eca20SDavid Ahern 				pr_err("No hardware sampling interrupt available."
341d6d901c2SZhang, Yanmin 				       " No APIC? If so then you can boot the kernel"
342d6d901c2SZhang, Yanmin 				       " with the \"lapic\" boot parameter to"
343d6d901c2SZhang, Yanmin 				       " force-enable it.\n");
3448d3eca20SDavid Ahern 				rc = -err;
3458d3eca20SDavid Ahern 				goto out;
3468d3eca20SDavid Ahern 			}
347bfd45118SSimon Kaempflein #endif
348bfd45118SSimon Kaempflein 
3498d3eca20SDavid Ahern 			pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
3508d3eca20SDavid Ahern 			rc = -err;
3518d3eca20SDavid Ahern 			goto out;
3527c6a1c65SPeter Zijlstra 		}
3537c6a1c65SPeter Zijlstra 	}
3547c6a1c65SPeter Zijlstra 
3551491a632SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist)) {
3560a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
3570a102479SFrederic Weisbecker 			strerror(errno));
3588d3eca20SDavid Ahern 		rc = -1;
3598d3eca20SDavid Ahern 		goto out;
3600a102479SFrederic Weisbecker 	}
3610a102479SFrederic Weisbecker 
36218e60939SNelson Elhage 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
3638d3eca20SDavid Ahern 		if (errno == EPERM) {
3648d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
36518e60939SNelson Elhage 			       "Consider increasing "
36618e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
36718e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
36818e60939SNelson Elhage 			       "(current value: %d)\n", opts->mmap_pages);
3698d3eca20SDavid Ahern 			rc = -errno;
3700089fa98SJiri Olsa 		} else if (!is_power_of_2(opts->mmap_pages) &&
3710089fa98SJiri Olsa 			   (opts->mmap_pages != UINT_MAX)) {
3728d3eca20SDavid Ahern 			pr_err("--mmap_pages/-m value must be a power of two.");
3738d3eca20SDavid Ahern 			rc = -EINVAL;
3748d3eca20SDavid Ahern 		} else {
3758d3eca20SDavid Ahern 			pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
3768d3eca20SDavid Ahern 			rc = -errno;
3778d3eca20SDavid Ahern 		}
3788d3eca20SDavid Ahern 		goto out;
37918e60939SNelson Elhage 	}
3800a27d7f9SArnaldo Carvalho de Melo 
381d20deb64SArnaldo Carvalho de Melo 	if (rec->file_new)
382a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
383a91e5431SArnaldo Carvalho de Melo 	else {
384a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
385a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
3868d3eca20SDavid Ahern 			rc = -1;
3878d3eca20SDavid Ahern 			goto out;
388dd7927f4SArnaldo Carvalho de Melo 		}
38986470930SIngo Molnar  	}
39086470930SIngo Molnar 
3917b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3928d3eca20SDavid Ahern out:
3938d3eca20SDavid Ahern 	return rc;
394a91e5431SArnaldo Carvalho de Melo }
395a91e5431SArnaldo Carvalho de Melo 
396d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec)
3976122e4e4SArnaldo Carvalho de Melo {
398d20deb64SArnaldo Carvalho de Melo 	u64 size = lseek(rec->output, 0, SEEK_CUR);
3996122e4e4SArnaldo Carvalho de Melo 
4009f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
4019f591fd7SArnaldo Carvalho de Melo 		return 0;
4029f591fd7SArnaldo Carvalho de Melo 
403d20deb64SArnaldo Carvalho de Melo 	rec->session->fd = rec->output;
404d20deb64SArnaldo Carvalho de Melo 	return __perf_session__process_events(rec->session, rec->post_processing_offset,
405d20deb64SArnaldo Carvalho de Melo 					      size - rec->post_processing_offset,
4066122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
4076122e4e4SArnaldo Carvalho de Melo }
4086122e4e4SArnaldo Carvalho de Melo 
4098d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg)
410f5970550SPeter Zijlstra {
411d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
412f5970550SPeter Zijlstra 
4138d3eca20SDavid Ahern 	if (status != 0)
4148d3eca20SDavid Ahern 		return;
4158d3eca20SDavid Ahern 
416d20deb64SArnaldo Carvalho de Melo 	if (!rec->opts.pipe_output) {
417d20deb64SArnaldo Carvalho de Melo 		rec->session->header.data_size += rec->bytes_written;
418d20deb64SArnaldo Carvalho de Melo 
419d20deb64SArnaldo Carvalho de Melo 		if (!rec->no_buildid)
420d20deb64SArnaldo Carvalho de Melo 			process_buildids(rec);
421d20deb64SArnaldo Carvalho de Melo 		perf_session__write_header(rec->session, rec->evlist,
422d20deb64SArnaldo Carvalho de Melo 					   rec->output, true);
423d20deb64SArnaldo Carvalho de Melo 		perf_session__delete(rec->session);
424d20deb64SArnaldo Carvalho de Melo 		perf_evlist__delete(rec->evlist);
425d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
426c7929e47STom Zanussi 	}
427f5970550SPeter Zijlstra }
428f5970550SPeter Zijlstra 
4298115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
430a1645ce1SZhang, Yanmin {
431a1645ce1SZhang, Yanmin 	int err;
43245694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
433a1645ce1SZhang, Yanmin 
43423346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
435a1645ce1SZhang, Yanmin 		return;
436a1645ce1SZhang, Yanmin 
437a1645ce1SZhang, Yanmin 	/*
438a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
439a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
440a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
441a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
442a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
443a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
444a1645ce1SZhang, Yanmin 	 */
44545694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
446743eb868SArnaldo Carvalho de Melo 					     machine);
447a1645ce1SZhang, Yanmin 	if (err < 0)
448a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
44923346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
450a1645ce1SZhang, Yanmin 
451a1645ce1SZhang, Yanmin 	/*
452a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
453a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
454a1645ce1SZhang, Yanmin 	 */
45545694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
456743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
457a1645ce1SZhang, Yanmin 	if (err < 0)
45845694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
459743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
460a1645ce1SZhang, Yanmin 	if (err < 0)
461a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
46223346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
463a1645ce1SZhang, Yanmin }
464a1645ce1SZhang, Yanmin 
46598402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
46698402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
46798402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
46898402807SFrederic Weisbecker };
46998402807SFrederic Weisbecker 
4708d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec)
47198402807SFrederic Weisbecker {
4720e2e63ddSPeter Zijlstra 	int i;
4738d3eca20SDavid Ahern 	int rc = 0;
47498402807SFrederic Weisbecker 
475d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
4768d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
4778d3eca20SDavid Ahern 			if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
4788d3eca20SDavid Ahern 				rc = -1;
4798d3eca20SDavid Ahern 				goto out;
4808d3eca20SDavid Ahern 			}
4818d3eca20SDavid Ahern 		}
48298402807SFrederic Weisbecker 	}
48398402807SFrederic Weisbecker 
4842eeaaa09SStephane Eranian 	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
4858d3eca20SDavid Ahern 		rc = write_output(rec, &finished_round_event,
4868d3eca20SDavid Ahern 				  sizeof(finished_round_event));
4878d3eca20SDavid Ahern 
4888d3eca20SDavid Ahern out:
4898d3eca20SDavid Ahern 	return rc;
49098402807SFrederic Weisbecker }
49198402807SFrederic Weisbecker 
492d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
49386470930SIngo Molnar {
49486470930SIngo Molnar 	struct stat st;
49586470930SIngo Molnar 	int flags;
496781ba9d2SRobert Richter 	int err, output, feat;
4978b412664SPeter Zijlstra 	unsigned long waking = 0;
49846be604bSZhang, Yanmin 	const bool forks = argc > 0;
49923346f21SArnaldo Carvalho de Melo 	struct machine *machine;
50045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
501d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
502d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list = rec->evlist;
503d20deb64SArnaldo Carvalho de Melo 	const char *output_name = rec->output_name;
504d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
505*2711926aSJiri Olsa 	bool disabled = false;
50686470930SIngo Molnar 
507d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
50833e49ea7SAndi Kleen 
509d20deb64SArnaldo Carvalho de Melo 	rec->page_size = sysconf(_SC_PAGE_SIZE);
51086470930SIngo Molnar 
511d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__sig_exit, rec);
512f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
513f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
51418483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
515f5970550SPeter Zijlstra 
516d7065adbSFranck Bui-Huu 	if (!output_name) {
517d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
518d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
519d7065adbSFranck Bui-Huu 		else
520d20deb64SArnaldo Carvalho de Melo 			rec->output_name = output_name = "perf.data";
521d7065adbSFranck Bui-Huu 	}
522d7065adbSFranck Bui-Huu 	if (output_name) {
523529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
524d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
525529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
526d20deb64SArnaldo Carvalho de Melo 			if (rec->write_mode == WRITE_FORCE) {
527b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
528b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
529b38d3464SArnaldo Carvalho de Melo 					 output_name);
530b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
531b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
532b38d3464SArnaldo Carvalho de Melo 			}
533d20deb64SArnaldo Carvalho de Melo 		} else if (rec->write_mode == WRITE_APPEND) {
534d20deb64SArnaldo Carvalho de Melo 			rec->write_mode = WRITE_FORCE;
535266e0e21SPierre Habouzit 		}
536d7065adbSFranck Bui-Huu 	}
53786470930SIngo Molnar 
538f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
539d20deb64SArnaldo Carvalho de Melo 	if (rec->write_mode == WRITE_APPEND)
540d20deb64SArnaldo Carvalho de Melo 		rec->file_new = 0;
54186470930SIngo Molnar 	else
54286470930SIngo Molnar 		flags |= O_TRUNC;
54386470930SIngo Molnar 
544d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output)
545529870e3STom Zanussi 		output = STDOUT_FILENO;
546529870e3STom Zanussi 	else
54786470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
54886470930SIngo Molnar 	if (output < 0) {
54986470930SIngo Molnar 		perror("failed to create output file");
5508d3eca20SDavid Ahern 		return -1;
55186470930SIngo Molnar 	}
55286470930SIngo Molnar 
553d20deb64SArnaldo Carvalho de Melo 	rec->output = output;
554d20deb64SArnaldo Carvalho de Melo 
5557865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
556d20deb64SArnaldo Carvalho de Melo 				    rec->write_mode == WRITE_FORCE, false, NULL);
55794c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
558a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
559a9a70bbcSArnaldo Carvalho de Melo 		return -1;
560a9a70bbcSArnaldo Carvalho de Melo 	}
561a9a70bbcSArnaldo Carvalho de Melo 
562d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
563d20deb64SArnaldo Carvalho de Melo 
564781ba9d2SRobert Richter 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
565781ba9d2SRobert Richter 		perf_header__set_feat(&session->header, feat);
566781ba9d2SRobert Richter 
567781ba9d2SRobert Richter 	if (rec->no_buildid)
568781ba9d2SRobert Richter 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
569781ba9d2SRobert Richter 
570781ba9d2SRobert Richter 	if (!have_tracepoints(&evsel_list->entries))
5712eeaaa09SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
572baa2f6ceSArnaldo Carvalho de Melo 
573330aa675SStephane Eranian 	if (!rec->opts.branch_stack)
574330aa675SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
575330aa675SStephane Eranian 
576d20deb64SArnaldo Carvalho de Melo 	if (!rec->file_new) {
577a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
5784dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
57939d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
5804dc0a04bSArnaldo Carvalho de Melo 	}
5814dc0a04bSArnaldo Carvalho de Melo 
582d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
583d20deb64SArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
58435b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
58535b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
58635b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
587856e9660SPeter Zijlstra 		}
588856e9660SPeter Zijlstra 	}
589856e9660SPeter Zijlstra 
5908d3eca20SDavid Ahern 	if (perf_record__open(rec) != 0) {
5918d3eca20SDavid Ahern 		err = -1;
5928d3eca20SDavid Ahern 		goto out_delete_session;
5938d3eca20SDavid Ahern 	}
59486470930SIngo Molnar 
595712a4b60SArnaldo Carvalho de Melo 	/*
596d20deb64SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at perf_record__exit()
597712a4b60SArnaldo Carvalho de Melo 	 */
598d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__exit, rec);
599712a4b60SArnaldo Carvalho de Melo 
600d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
601529870e3STom Zanussi 		err = perf_header__write_pipe(output);
602529870e3STom Zanussi 		if (err < 0)
6038d3eca20SDavid Ahern 			goto out_delete_session;
604d20deb64SArnaldo Carvalho de Melo 	} else if (rec->file_new) {
605a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
606361c99a6SArnaldo Carvalho de Melo 						 output, false);
607d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
6088d3eca20SDavid Ahern 			goto out_delete_session;
609d5eed904SArnaldo Carvalho de Melo 	}
6107c6a1c65SPeter Zijlstra 
611d3665498SDavid Ahern 	if (!rec->no_buildid
612e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
613d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
614e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
6158d3eca20SDavid Ahern 		err = -1;
6168d3eca20SDavid Ahern 		goto out_delete_session;
617e20960c0SRobert Richter 	}
618e20960c0SRobert Richter 
619d20deb64SArnaldo Carvalho de Melo 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
6206122e4e4SArnaldo Carvalho de Melo 
621743eb868SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
622743eb868SArnaldo Carvalho de Melo 	if (!machine) {
623743eb868SArnaldo Carvalho de Melo 		pr_err("Couldn't find native kernel information.\n");
6248d3eca20SDavid Ahern 		err = -1;
6258d3eca20SDavid Ahern 		goto out_delete_session;
626743eb868SArnaldo Carvalho de Melo 	}
627743eb868SArnaldo Carvalho de Melo 
628d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
62945694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
630a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
6312c46dbb5STom Zanussi 		if (err < 0) {
6322c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
6338d3eca20SDavid Ahern 			goto out_delete_session;
6342c46dbb5STom Zanussi 		}
635cd19a035STom Zanussi 
63645694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
637743eb868SArnaldo Carvalho de Melo 							 machine);
638cd19a035STom Zanussi 		if (err < 0) {
639cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
6408d3eca20SDavid Ahern 			goto out_delete_session;
641cd19a035STom Zanussi 		}
6429215545eSTom Zanussi 
643361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
64463e0c771STom Zanussi 			/*
64563e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
64663e0c771STom Zanussi 			 * there were no tracepoints so its not really
64763e0c771STom Zanussi 			 * an error, just that we don't need to
64863e0c771STom Zanussi 			 * synthesize anything.  We really have to
64963e0c771STom Zanussi 			 * return this more properly and also
65063e0c771STom Zanussi 			 * propagate errors that now are calling die()
65163e0c771STom Zanussi 			 */
65245694aa7SArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
653743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
65463e0c771STom Zanussi 			if (err <= 0) {
65563e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
6568d3eca20SDavid Ahern 				goto out_delete_session;
65763e0c771STom Zanussi 			}
658d20deb64SArnaldo Carvalho de Melo 			advance_output(rec, err);
6592c46dbb5STom Zanussi 		}
66063e0c771STom Zanussi 	}
6612c46dbb5STom Zanussi 
66245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
663743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
66470162138SArnaldo Carvalho de Melo 	if (err < 0)
66545694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
666743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
667c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
668c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
669c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
670c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
67156b03f3cSArnaldo Carvalho de Melo 
67245694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
673743eb868SArnaldo Carvalho de Melo 					     machine);
674c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
675c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
676c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
677c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
678c1a3a4b9SArnaldo Carvalho de Melo 
679a1645ce1SZhang, Yanmin 	if (perf_guest)
68045694aa7SArnaldo Carvalho de Melo 		perf_session__process_machines(session, tool,
6818115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
682b7cece76SArnaldo Carvalho de Melo 
683bea03405SNamhyung Kim 	if (!opts->target.system_wide)
6848d3eca20SDavid Ahern 		err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
6858115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
686743eb868SArnaldo Carvalho de Melo 						  machine);
687234fbbf5SArnaldo Carvalho de Melo 	else
6888d3eca20SDavid Ahern 		err = perf_event__synthesize_threads(tool, process_synthesized_event,
689743eb868SArnaldo Carvalho de Melo 					       machine);
6907c6a1c65SPeter Zijlstra 
6918d3eca20SDavid Ahern 	if (err != 0)
6928d3eca20SDavid Ahern 		goto out_delete_session;
6938d3eca20SDavid Ahern 
694d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
69586470930SIngo Molnar 		struct sched_param param;
69686470930SIngo Molnar 
697d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
69886470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6996beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
7008d3eca20SDavid Ahern 			err = -1;
7018d3eca20SDavid Ahern 			goto out_delete_session;
70286470930SIngo Molnar 		}
70386470930SIngo Molnar 	}
70486470930SIngo Molnar 
705774cb499SJiri Olsa 	/*
706774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
707774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
708774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
709774cb499SJiri Olsa 	 */
710774cb499SJiri Olsa 	if (!perf_target__none(&opts->target))
711764e16a3SDavid Ahern 		perf_evlist__enable(evsel_list);
712764e16a3SDavid Ahern 
713856e9660SPeter Zijlstra 	/*
714856e9660SPeter Zijlstra 	 * Let the child rip
715856e9660SPeter Zijlstra 	 */
716d4db3f16SArnaldo Carvalho de Melo 	if (forks)
71735b9d88eSArnaldo Carvalho de Melo 		perf_evlist__start_workload(evsel_list);
718856e9660SPeter Zijlstra 
719649c48a9SPeter Zijlstra 	for (;;) {
720d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
72186470930SIngo Molnar 
7228d3eca20SDavid Ahern 		if (perf_record__mmap_read_all(rec) < 0) {
7238d3eca20SDavid Ahern 			err = -1;
7248d3eca20SDavid Ahern 			goto out_delete_session;
7258d3eca20SDavid Ahern 		}
72686470930SIngo Molnar 
727d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
728649c48a9SPeter Zijlstra 			if (done)
729649c48a9SPeter Zijlstra 				break;
7305c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
7318b412664SPeter Zijlstra 			waking++;
7328b412664SPeter Zijlstra 		}
7338b412664SPeter Zijlstra 
734774cb499SJiri Olsa 		/*
735774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
736774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
737774cb499SJiri Olsa 		 * disable events in this case.
738774cb499SJiri Olsa 		 */
739*2711926aSJiri Olsa 		if (done && !disabled && !perf_target__none(&opts->target)) {
7404152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
741*2711926aSJiri Olsa 			disabled = true;
742*2711926aSJiri Olsa 		}
7438b412664SPeter Zijlstra 	}
7448b412664SPeter Zijlstra 
74518483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
746b44308f5SArnaldo Carvalho de Melo 		return 0;
747b44308f5SArnaldo Carvalho de Melo 
7488b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
74986470930SIngo Molnar 
75086470930SIngo Molnar 	/*
75186470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
75286470930SIngo Molnar 	 */
75386470930SIngo Molnar 	fprintf(stderr,
7549486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
755d20deb64SArnaldo Carvalho de Melo 		(double)rec->bytes_written / 1024.0 / 1024.0,
75686470930SIngo Molnar 		output_name,
757d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written / 24);
75886470930SIngo Molnar 
75986470930SIngo Molnar 	return 0;
76039d17dacSArnaldo Carvalho de Melo 
76139d17dacSArnaldo Carvalho de Melo out_delete_session:
76239d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
76339d17dacSArnaldo Carvalho de Melo 	return err;
76486470930SIngo Molnar }
76586470930SIngo Molnar 
766bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
767bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
768bdfebd84SRoberto Agostino Vitillo 
769bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
770bdfebd84SRoberto Agostino Vitillo 
771bdfebd84SRoberto Agostino Vitillo struct branch_mode {
772bdfebd84SRoberto Agostino Vitillo 	const char *name;
773bdfebd84SRoberto Agostino Vitillo 	int mode;
774bdfebd84SRoberto Agostino Vitillo };
775bdfebd84SRoberto Agostino Vitillo 
776bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
777bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
778bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
779bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
780bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
781bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
782bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
783bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
784bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
785bdfebd84SRoberto Agostino Vitillo };
786bdfebd84SRoberto Agostino Vitillo 
787bdfebd84SRoberto Agostino Vitillo static int
788a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
789bdfebd84SRoberto Agostino Vitillo {
790bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
791bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
792bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
793bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
794bdfebd84SRoberto Agostino Vitillo 
795bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
796bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
797a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
798bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
799bdfebd84SRoberto Agostino Vitillo 
800a5aabdacSStephane Eranian 	if (unset)
801a5aabdacSStephane Eranian 		return 0;
802bdfebd84SRoberto Agostino Vitillo 
803a5aabdacSStephane Eranian 	/*
804a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
805a5aabdacSStephane Eranian 	 */
806a5aabdacSStephane Eranian 	if (*mode)
807a5aabdacSStephane Eranian 		return -1;
808a5aabdacSStephane Eranian 
809a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
810a5aabdacSStephane Eranian 	if (str) {
811bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
812bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
813bdfebd84SRoberto Agostino Vitillo 		if (!s)
814bdfebd84SRoberto Agostino Vitillo 			return -1;
815bdfebd84SRoberto Agostino Vitillo 
816bdfebd84SRoberto Agostino Vitillo 		for (;;) {
817bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
818bdfebd84SRoberto Agostino Vitillo 			if (p)
819bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
820bdfebd84SRoberto Agostino Vitillo 
821bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
822bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
823bdfebd84SRoberto Agostino Vitillo 					break;
824bdfebd84SRoberto Agostino Vitillo 			}
825a5aabdacSStephane Eranian 			if (!br->name) {
826a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
827a5aabdacSStephane Eranian 					    " check man page\n", s);
828bdfebd84SRoberto Agostino Vitillo 				goto error;
829a5aabdacSStephane Eranian 			}
830bdfebd84SRoberto Agostino Vitillo 
831bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
832bdfebd84SRoberto Agostino Vitillo 
833bdfebd84SRoberto Agostino Vitillo 			if (!p)
834bdfebd84SRoberto Agostino Vitillo 				break;
835bdfebd84SRoberto Agostino Vitillo 
836bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
837bdfebd84SRoberto Agostino Vitillo 		}
838a5aabdacSStephane Eranian 	}
839bdfebd84SRoberto Agostino Vitillo 	ret = 0;
840bdfebd84SRoberto Agostino Vitillo 
841a5aabdacSStephane Eranian 	/* default to any branch */
842bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
843a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
844bdfebd84SRoberto Agostino Vitillo 	}
845bdfebd84SRoberto Agostino Vitillo error:
846bdfebd84SRoberto Agostino Vitillo 	free(os);
847bdfebd84SRoberto Agostino Vitillo 	return ret;
848bdfebd84SRoberto Agostino Vitillo }
849bdfebd84SRoberto Agostino Vitillo 
85095485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
85126d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size)
85226d33022SJiri Olsa {
85326d33022SJiri Olsa 	char *endptr;
85426d33022SJiri Olsa 	unsigned long size;
85526d33022SJiri Olsa 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
85626d33022SJiri Olsa 
85726d33022SJiri Olsa 	size = strtoul(str, &endptr, 0);
85826d33022SJiri Olsa 
85926d33022SJiri Olsa 	do {
86026d33022SJiri Olsa 		if (*endptr)
86126d33022SJiri Olsa 			break;
86226d33022SJiri Olsa 
86326d33022SJiri Olsa 		size = round_up(size, sizeof(u64));
86426d33022SJiri Olsa 		if (!size || size > max_size)
86526d33022SJiri Olsa 			break;
86626d33022SJiri Olsa 
86726d33022SJiri Olsa 		*_size = size;
86826d33022SJiri Olsa 		return 0;
86926d33022SJiri Olsa 
87026d33022SJiri Olsa 	} while (0);
87126d33022SJiri Olsa 
87226d33022SJiri Olsa 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
87326d33022SJiri Olsa 	       max_size, str);
87426d33022SJiri Olsa 	return -1;
87526d33022SJiri Olsa }
87695485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
87726d33022SJiri Olsa 
87826d33022SJiri Olsa static int
8791d037ca1SIrina Tirdea parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
88026d33022SJiri Olsa 		    int unset)
88126d33022SJiri Olsa {
88226d33022SJiri Olsa 	struct perf_record *rec = (struct perf_record *)opt->value;
88326d33022SJiri Olsa 	char *tok, *name, *saveptr = NULL;
88426d33022SJiri Olsa 	char *buf;
88526d33022SJiri Olsa 	int ret = -1;
88626d33022SJiri Olsa 
88726d33022SJiri Olsa 	/* --no-call-graph */
88826d33022SJiri Olsa 	if (unset)
88926d33022SJiri Olsa 		return 0;
89026d33022SJiri Olsa 
89126d33022SJiri Olsa 	/* We specified default option if none is provided. */
89226d33022SJiri Olsa 	BUG_ON(!arg);
89326d33022SJiri Olsa 
89426d33022SJiri Olsa 	/* We need buffer that we know we can write to. */
89526d33022SJiri Olsa 	buf = malloc(strlen(arg) + 1);
89626d33022SJiri Olsa 	if (!buf)
89726d33022SJiri Olsa 		return -ENOMEM;
89826d33022SJiri Olsa 
89926d33022SJiri Olsa 	strcpy(buf, arg);
90026d33022SJiri Olsa 
90126d33022SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
90226d33022SJiri Olsa 	name = tok ? : (char *)buf;
90326d33022SJiri Olsa 
90426d33022SJiri Olsa 	do {
90526d33022SJiri Olsa 		/* Framepointer style */
90626d33022SJiri Olsa 		if (!strncmp(name, "fp", sizeof("fp"))) {
90726d33022SJiri Olsa 			if (!strtok_r(NULL, ",", &saveptr)) {
90826d33022SJiri Olsa 				rec->opts.call_graph = CALLCHAIN_FP;
90926d33022SJiri Olsa 				ret = 0;
91026d33022SJiri Olsa 			} else
91126d33022SJiri Olsa 				pr_err("callchain: No more arguments "
91226d33022SJiri Olsa 				       "needed for -g fp\n");
91326d33022SJiri Olsa 			break;
91426d33022SJiri Olsa 
91595485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
91626d33022SJiri Olsa 		/* Dwarf style */
91726d33022SJiri Olsa 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
91861eaa3beSArnaldo Carvalho de Melo 			const unsigned long default_stack_dump_size = 8192;
91961eaa3beSArnaldo Carvalho de Melo 
92026d33022SJiri Olsa 			ret = 0;
92126d33022SJiri Olsa 			rec->opts.call_graph = CALLCHAIN_DWARF;
92226d33022SJiri Olsa 			rec->opts.stack_dump_size = default_stack_dump_size;
92326d33022SJiri Olsa 
92426d33022SJiri Olsa 			tok = strtok_r(NULL, ",", &saveptr);
92526d33022SJiri Olsa 			if (tok) {
92626d33022SJiri Olsa 				unsigned long size = 0;
92726d33022SJiri Olsa 
92826d33022SJiri Olsa 				ret = get_stack_size(tok, &size);
92926d33022SJiri Olsa 				rec->opts.stack_dump_size = size;
93026d33022SJiri Olsa 			}
93126d33022SJiri Olsa 
93226d33022SJiri Olsa 			if (!ret)
93326d33022SJiri Olsa 				pr_debug("callchain: stack dump size %d\n",
93426d33022SJiri Olsa 					 rec->opts.stack_dump_size);
93595485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
93626d33022SJiri Olsa 		} else {
93726d33022SJiri Olsa 			pr_err("callchain: Unknown -g option "
93826d33022SJiri Olsa 			       "value: %s\n", arg);
93926d33022SJiri Olsa 			break;
94026d33022SJiri Olsa 		}
94126d33022SJiri Olsa 
94226d33022SJiri Olsa 	} while (0);
94326d33022SJiri Olsa 
94426d33022SJiri Olsa 	free(buf);
94526d33022SJiri Olsa 
94626d33022SJiri Olsa 	if (!ret)
94726d33022SJiri Olsa 		pr_debug("callchain: type %d\n", rec->opts.call_graph);
94826d33022SJiri Olsa 
94926d33022SJiri Olsa 	return ret;
95026d33022SJiri Olsa }
95126d33022SJiri Olsa 
95286470930SIngo Molnar static const char * const record_usage[] = {
95386470930SIngo Molnar 	"perf record [<options>] [<command>]",
95486470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
95586470930SIngo Molnar 	NULL
95686470930SIngo Molnar };
95786470930SIngo Molnar 
958d20deb64SArnaldo Carvalho de Melo /*
959d20deb64SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
960d20deb64SArnaldo Carvalho de Melo  * because we need to have access to it in perf_record__exit, that is called
961d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
962d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
963d20deb64SArnaldo Carvalho de Melo  *
964d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
965d20deb64SArnaldo Carvalho de Melo  *
966d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
967d20deb64SArnaldo Carvalho de Melo  */
968d20deb64SArnaldo Carvalho de Melo static struct perf_record record = {
969d20deb64SArnaldo Carvalho de Melo 	.opts = {
970d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
971d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
972d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
973447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
974d1cb9fceSNamhyung Kim 		.target		     = {
975d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
976d1cb9fceSNamhyung Kim 		},
977d20deb64SArnaldo Carvalho de Melo 	},
978d20deb64SArnaldo Carvalho de Melo 	.write_mode = WRITE_FORCE,
979d20deb64SArnaldo Carvalho de Melo 	.file_new   = true,
980d20deb64SArnaldo Carvalho de Melo };
9817865e817SFrederic Weisbecker 
98261eaa3beSArnaldo Carvalho de Melo #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
98361eaa3beSArnaldo Carvalho de Melo 
98461eaa3beSArnaldo Carvalho de Melo #ifdef LIBUNWIND_SUPPORT
98561eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
98661eaa3beSArnaldo Carvalho de Melo #else
98761eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
98861eaa3beSArnaldo Carvalho de Melo #endif
98961eaa3beSArnaldo Carvalho de Melo 
990d20deb64SArnaldo Carvalho de Melo /*
991d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
992d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
993d20deb64SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use perf_record_opts,
994d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
995d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
996d20deb64SArnaldo Carvalho de Melo  */
997bca647aaSTom Zanussi const struct option record_options[] = {
998d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
99986470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1000f120f9d5SJiri Olsa 		     parse_events_option),
1001d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1002c171b552SLi Zefan 		     "event filter", parse_filter),
1003bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
1004d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
1005bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
1006d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
1007d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
100886470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1009d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
1010acac03faSKirill Smelkov 		    "collect data without buffering"),
1011d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1012daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1013bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
101486470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1015d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('A', "append", &record.append_file,
101686470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
1017bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1018c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1019d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &record.force,
10207865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
1021d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1022d20deb64SArnaldo Carvalho de Melo 	OPT_STRING('o', "output", &record.output_name, "file",
102386470930SIngo Molnar 		    "output file name"),
1024d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
10252e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
1026d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1027d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
102801c2d99bSArnaldo Carvalho de Melo 		     "number of mmap data pages"),
1029d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
103043bece79SLin Ming 		    "put the counters into a counter group"),
103126d33022SJiri Olsa 	OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]",
103226d33022SJiri Olsa 			     callchain_help, &parse_callchain_opt,
103326d33022SJiri Olsa 			     "fp"),
1034c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
10353da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1036b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1037d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1038649c48a9SPeter Zijlstra 		    "per thread counts"),
1039d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
10404bba828dSAnton Blanchard 		    "Sample addresses"),
1041d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
10423e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
1043d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1044649c48a9SPeter Zijlstra 		    "don't sample"),
1045d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
1046a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
1047d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
1048baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
1049d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1050023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1051023695d9SStephane Eranian 		     parse_cgroups),
1052bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1053bea03405SNamhyung Kim 		   "user to profile"),
1054a5aabdacSStephane Eranian 
1055a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1056a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1057a5aabdacSStephane Eranian 		     parse_branch_stack),
1058a5aabdacSStephane Eranian 
1059a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1060a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1061bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
106286470930SIngo Molnar 	OPT_END()
106386470930SIngo Molnar };
106486470930SIngo Molnar 
10651d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
106686470930SIngo Molnar {
106769aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
106869aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
1069d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list;
1070d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = &record;
107116ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
107286470930SIngo Molnar 
10737e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
1074361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
1075361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1076361c99a6SArnaldo Carvalho de Melo 
1077d20deb64SArnaldo Carvalho de Melo 	rec->evlist = evsel_list;
1078d20deb64SArnaldo Carvalho de Melo 
1079bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1080a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1081d67356e7SNamhyung Kim 	if (!argc && perf_target__none(&rec->opts.target))
1082bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
108386470930SIngo Molnar 
1084d20deb64SArnaldo Carvalho de Melo 	if (rec->force && rec->append_file) {
10853780f488SNamhyung Kim 		ui__error("Can't overwrite and append at the same time."
10867865e817SFrederic Weisbecker 			  " You need to choose between -f and -A");
1087bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
1088d20deb64SArnaldo Carvalho de Melo 	} else if (rec->append_file) {
1089d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_APPEND;
10907865e817SFrederic Weisbecker 	} else {
1091d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_FORCE;
10927865e817SFrederic Weisbecker 	}
10937865e817SFrederic Weisbecker 
1094bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
10953780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
1096023695d9SStephane Eranian 			  " system-wide mode\n");
1097023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
1098023695d9SStephane Eranian 	}
1099023695d9SStephane Eranian 
1100655000e7SArnaldo Carvalho de Melo 	symbol__init();
1101baa2f6ceSArnaldo Carvalho de Melo 
1102ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1103646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1104646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1105ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1106646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1107646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1108646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1109646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1110646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1111ec80fde7SArnaldo Carvalho de Melo 
1112d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1113a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1114655000e7SArnaldo Carvalho de Melo 
1115361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
1116361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
111769aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
111869aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1119bbd36e5eSPeter Zijlstra 	}
112086470930SIngo Molnar 
112116ad2ffbSNamhyung Kim 	err = perf_target__validate(&rec->opts.target);
112216ad2ffbSNamhyung Kim 	if (err) {
112316ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
112416ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
112516ad2ffbSNamhyung Kim 	}
11264bd0f2d2SNamhyung Kim 
112716ad2ffbSNamhyung Kim 	err = perf_target__parse_uid(&rec->opts.target);
112816ad2ffbSNamhyung Kim 	if (err) {
112916ad2ffbSNamhyung Kim 		int saved_errno = errno;
113016ad2ffbSNamhyung Kim 
113116ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
11323780f488SNamhyung Kim 		ui__error("%s", errbuf);
113316ad2ffbSNamhyung Kim 
113416ad2ffbSNamhyung Kim 		err = -saved_errno;
11350d37aa34SArnaldo Carvalho de Melo 		goto out_free_fd;
113616ad2ffbSNamhyung Kim 	}
11370d37aa34SArnaldo Carvalho de Melo 
113816ad2ffbSNamhyung Kim 	err = -ENOMEM;
1139b809ac10SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
1140dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
114169aad6f1SArnaldo Carvalho de Melo 
1142361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
11437289f83cSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
1144ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
1145d6d901c2SZhang, Yanmin 	}
11465c581041SArnaldo Carvalho de Melo 
1147d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_interval != ULLONG_MAX)
1148d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.user_interval;
1149d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_freq != UINT_MAX)
1150d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = rec->opts.user_freq;
1151f9212819SFrederic Weisbecker 
11527e4ff9e3SMike Galbraith 	/*
11537e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
11547e4ff9e3SMike Galbraith 	 */
1155d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.default_interval)
1156d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = 0;
1157d20deb64SArnaldo Carvalho de Melo 	else if (rec->opts.freq) {
1158d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.freq;
11597e4ff9e3SMike Galbraith 	} else {
11603780f488SNamhyung Kim 		ui__error("frequency and count are zero, aborting\n");
116139d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
11625c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
11637e4ff9e3SMike Galbraith 	}
11647e4ff9e3SMike Galbraith 
1165d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
116639d17dacSArnaldo Carvalho de Melo out_free_fd:
11677e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
1168d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
1169d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
117039d17dacSArnaldo Carvalho de Melo 	return err;
117186470930SIngo Molnar }
1172