xref: /openbmc/linux/tools/perf/builtin-record.c (revision c5ff78c3092d0e7d14c82d2949e16fee063a83f1)
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 
233f77a9518SArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts);
234cac21425SJiri Olsa 
235dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
236dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
237dd7927f4SArnaldo Carvalho de Melo 		/*
238dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
239dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
240dd7927f4SArnaldo Carvalho de Melo 		 *
241dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
242dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
243dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
244dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
245dd7927f4SArnaldo Carvalho de Melo 		 *
246dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
247dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
248dd7927f4SArnaldo Carvalho de Melo 		 */
249dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
250dd7927f4SArnaldo Carvalho de Melo 
2510c978128SArnaldo Carvalho de Melo fallback_missing_features:
2520c978128SArnaldo Carvalho de Melo 		if (opts->exclude_guest_missing)
2530c978128SArnaldo Carvalho de Melo 			attr->exclude_guest = attr->exclude_host = 0;
2549c90a61cSArnaldo Carvalho de Melo retry_sample_id:
255808e1226SArnaldo Carvalho de Melo 		attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
2563da297a6SIngo Molnar try_again:
2576a4bb04cSJiri Olsa 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
25886470930SIngo Molnar 			int err = errno;
25986470930SIngo Molnar 
260c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
261b8631e6eSArnaldo Carvalho de Melo 				ui__error_paranoid();
2628d3eca20SDavid Ahern 				rc = -err;
2638d3eca20SDavid Ahern 				goto out;
264bea03405SNamhyung Kim 			} else if (err ==  ENODEV && opts->target.cpu_list) {
2658d3eca20SDavid Ahern 				pr_err("No such device - did you specify"
266d6d901c2SZhang, Yanmin 				       " an out-of-range profile CPU?\n");
2678d3eca20SDavid Ahern 				rc = -err;
2688d3eca20SDavid Ahern 				goto out;
2690c978128SArnaldo Carvalho de Melo 			} else if (err == EINVAL) {
2700c978128SArnaldo Carvalho de Melo 				if (!opts->exclude_guest_missing &&
2710c978128SArnaldo Carvalho de Melo 				    (attr->exclude_guest || attr->exclude_host)) {
2720c978128SArnaldo Carvalho de Melo 					pr_debug("Old kernel, cannot exclude "
2730c978128SArnaldo Carvalho de Melo 						 "guest or host samples.\n");
2740c978128SArnaldo Carvalho de Melo 					opts->exclude_guest_missing = true;
2750c978128SArnaldo Carvalho de Melo 					goto fallback_missing_features;
276808e1226SArnaldo Carvalho de Melo 				} else if (!opts->sample_id_all_missing) {
2779c90a61cSArnaldo Carvalho de Melo 					/*
2789c90a61cSArnaldo Carvalho de Melo 					 * Old kernel, no attr->sample_id_type_all field
2799c90a61cSArnaldo Carvalho de Melo 					 */
280808e1226SArnaldo Carvalho de Melo 					opts->sample_id_all_missing = true;
281d20deb64SArnaldo Carvalho de Melo 					if (!opts->sample_time && !opts->raw_samples && !time_needed)
2827be5ebe8SArnaldo Carvalho de Melo 						perf_evsel__reset_sample_bit(pos, TIME);
283eac23d1cSIan Munsie 
2849c90a61cSArnaldo Carvalho de Melo 					goto retry_sample_id;
285d6d901c2SZhang, Yanmin 				}
2860c978128SArnaldo Carvalho de Melo 			}
2873da297a6SIngo Molnar 
2883da297a6SIngo Molnar 			/*
2893da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
2903da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
291028d455bSDavid Ahern 			 * is always available even if no PMU support.
292028d455bSDavid Ahern 			 *
293028d455bSDavid Ahern 			 * PPC returns ENXIO until 2.6.37 (behavior changed
294028d455bSDavid Ahern 			 * with commit b0a873e).
2953da297a6SIngo Molnar 			 */
296028d455bSDavid Ahern 			if ((err == ENOENT || err == ENXIO)
297028d455bSDavid Ahern 					&& attr->type == PERF_TYPE_HARDWARE
298f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
2993da297a6SIngo Molnar 
3003da297a6SIngo Molnar 				if (verbose)
301ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
302ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
3033da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
304f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
305d1cae34dSDavid Ahern 				if (pos->name) {
306d1cae34dSDavid Ahern 					free(pos->name);
307d1cae34dSDavid Ahern 					pos->name = NULL;
308d1cae34dSDavid Ahern 				}
3093da297a6SIngo Molnar 				goto try_again;
3103da297a6SIngo Molnar 			}
311ca6a4258SDavid Ahern 
312ca6a4258SDavid Ahern 			if (err == ENOENT) {
3133780f488SNamhyung Kim 				ui__error("The %s event is not supported.\n",
3147289f83cSArnaldo Carvalho de Melo 					  perf_evsel__name(pos));
3158d3eca20SDavid Ahern 				rc = -err;
3168d3eca20SDavid Ahern 				goto out;
3172305c82fSDavid Ahern 			} else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
3182305c82fSDavid Ahern 				ui__error("\'precise\' request may not be supported. "
3192305c82fSDavid Ahern 					  "Try removing 'p' modifier\n");
3202305c82fSDavid Ahern 				rc = -err;
3212305c82fSDavid Ahern 				goto out;
322ca6a4258SDavid Ahern 			}
323ca6a4258SDavid Ahern 
32430c806a0SIngo Molnar 			printf("\n");
3251863fbbbSStephane Eranian 			error("sys_perf_event_open() syscall returned with %d "
3261863fbbbSStephane Eranian 			      "(%s) for event %s. /bin/dmesg may provide "
3271863fbbbSStephane Eranian 			      "additional information.\n",
3281863fbbbSStephane Eranian 			      err, strerror(err), perf_evsel__name(pos));
329bfd45118SSimon Kaempflein 
330bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
3318d3eca20SDavid Ahern 			if (attr->type == PERF_TYPE_HARDWARE &&
3328d3eca20SDavid Ahern 			    err == EOPNOTSUPP) {
3338d3eca20SDavid Ahern 				pr_err("No hardware sampling interrupt available."
334d6d901c2SZhang, Yanmin 				       " No APIC? If so then you can boot the kernel"
335d6d901c2SZhang, Yanmin 				       " with the \"lapic\" boot parameter to"
336d6d901c2SZhang, Yanmin 				       " force-enable it.\n");
3378d3eca20SDavid Ahern 				rc = -err;
3388d3eca20SDavid Ahern 				goto out;
3398d3eca20SDavid Ahern 			}
340bfd45118SSimon Kaempflein #endif
341bfd45118SSimon Kaempflein 
3428d3eca20SDavid Ahern 			pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
3438d3eca20SDavid Ahern 			rc = -err;
3448d3eca20SDavid Ahern 			goto out;
3457c6a1c65SPeter Zijlstra 		}
3467c6a1c65SPeter Zijlstra 	}
3477c6a1c65SPeter Zijlstra 
3481491a632SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist)) {
3490a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
3500a102479SFrederic Weisbecker 			strerror(errno));
3518d3eca20SDavid Ahern 		rc = -1;
3528d3eca20SDavid Ahern 		goto out;
3530a102479SFrederic Weisbecker 	}
3540a102479SFrederic Weisbecker 
35518e60939SNelson Elhage 	if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
3568d3eca20SDavid Ahern 		if (errno == EPERM) {
3578d3eca20SDavid Ahern 			pr_err("Permission error mapping pages.\n"
35818e60939SNelson Elhage 			       "Consider increasing "
35918e60939SNelson Elhage 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
36018e60939SNelson Elhage 			       "or try again with a smaller value of -m/--mmap_pages.\n"
36118e60939SNelson Elhage 			       "(current value: %d)\n", opts->mmap_pages);
3628d3eca20SDavid Ahern 			rc = -errno;
3630089fa98SJiri Olsa 		} else if (!is_power_of_2(opts->mmap_pages) &&
3640089fa98SJiri Olsa 			   (opts->mmap_pages != UINT_MAX)) {
3658d3eca20SDavid Ahern 			pr_err("--mmap_pages/-m value must be a power of two.");
3668d3eca20SDavid Ahern 			rc = -EINVAL;
3678d3eca20SDavid Ahern 		} else {
3688d3eca20SDavid Ahern 			pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
3698d3eca20SDavid Ahern 			rc = -errno;
3708d3eca20SDavid Ahern 		}
3718d3eca20SDavid Ahern 		goto out;
37218e60939SNelson Elhage 	}
3730a27d7f9SArnaldo Carvalho de Melo 
374d20deb64SArnaldo Carvalho de Melo 	if (rec->file_new)
375a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
376a91e5431SArnaldo Carvalho de Melo 	else {
377a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
378a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
3798d3eca20SDavid Ahern 			rc = -1;
3808d3eca20SDavid Ahern 			goto out;
381dd7927f4SArnaldo Carvalho de Melo 		}
38286470930SIngo Molnar  	}
38386470930SIngo Molnar 
3847b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
3858d3eca20SDavid Ahern out:
3868d3eca20SDavid Ahern 	return rc;
387a91e5431SArnaldo Carvalho de Melo }
388a91e5431SArnaldo Carvalho de Melo 
389d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec)
3906122e4e4SArnaldo Carvalho de Melo {
391d20deb64SArnaldo Carvalho de Melo 	u64 size = lseek(rec->output, 0, SEEK_CUR);
3926122e4e4SArnaldo Carvalho de Melo 
3939f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3949f591fd7SArnaldo Carvalho de Melo 		return 0;
3959f591fd7SArnaldo Carvalho de Melo 
396d20deb64SArnaldo Carvalho de Melo 	rec->session->fd = rec->output;
397d20deb64SArnaldo Carvalho de Melo 	return __perf_session__process_events(rec->session, rec->post_processing_offset,
398d20deb64SArnaldo Carvalho de Melo 					      size - rec->post_processing_offset,
3996122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
4006122e4e4SArnaldo Carvalho de Melo }
4016122e4e4SArnaldo Carvalho de Melo 
4028d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg)
403f5970550SPeter Zijlstra {
404d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = arg;
405f5970550SPeter Zijlstra 
4068d3eca20SDavid Ahern 	if (status != 0)
4078d3eca20SDavid Ahern 		return;
4088d3eca20SDavid Ahern 
409d20deb64SArnaldo Carvalho de Melo 	if (!rec->opts.pipe_output) {
410d20deb64SArnaldo Carvalho de Melo 		rec->session->header.data_size += rec->bytes_written;
411d20deb64SArnaldo Carvalho de Melo 
412d20deb64SArnaldo Carvalho de Melo 		if (!rec->no_buildid)
413d20deb64SArnaldo Carvalho de Melo 			process_buildids(rec);
414d20deb64SArnaldo Carvalho de Melo 		perf_session__write_header(rec->session, rec->evlist,
415d20deb64SArnaldo Carvalho de Melo 					   rec->output, true);
416d20deb64SArnaldo Carvalho de Melo 		perf_session__delete(rec->session);
417d20deb64SArnaldo Carvalho de Melo 		perf_evlist__delete(rec->evlist);
418d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
419c7929e47STom Zanussi 	}
420f5970550SPeter Zijlstra }
421f5970550SPeter Zijlstra 
4228115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
423a1645ce1SZhang, Yanmin {
424a1645ce1SZhang, Yanmin 	int err;
42545694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
426a1645ce1SZhang, Yanmin 
42723346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
428a1645ce1SZhang, Yanmin 		return;
429a1645ce1SZhang, Yanmin 
430a1645ce1SZhang, Yanmin 	/*
431a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
432a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
433a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
434a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
435a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
436a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
437a1645ce1SZhang, Yanmin 	 */
43845694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
439743eb868SArnaldo Carvalho de Melo 					     machine);
440a1645ce1SZhang, Yanmin 	if (err < 0)
441a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
44223346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
443a1645ce1SZhang, Yanmin 
444a1645ce1SZhang, Yanmin 	/*
445a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
446a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
447a1645ce1SZhang, Yanmin 	 */
44845694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
449743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
450a1645ce1SZhang, Yanmin 	if (err < 0)
45145694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
452743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
453a1645ce1SZhang, Yanmin 	if (err < 0)
454a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
45523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
456a1645ce1SZhang, Yanmin }
457a1645ce1SZhang, Yanmin 
45898402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
45998402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
46098402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
46198402807SFrederic Weisbecker };
46298402807SFrederic Weisbecker 
4638d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec)
46498402807SFrederic Weisbecker {
4650e2e63ddSPeter Zijlstra 	int i;
4668d3eca20SDavid Ahern 	int rc = 0;
46798402807SFrederic Weisbecker 
468d20deb64SArnaldo Carvalho de Melo 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
4698d3eca20SDavid Ahern 		if (rec->evlist->mmap[i].base) {
4708d3eca20SDavid Ahern 			if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
4718d3eca20SDavid Ahern 				rc = -1;
4728d3eca20SDavid Ahern 				goto out;
4738d3eca20SDavid Ahern 			}
4748d3eca20SDavid Ahern 		}
47598402807SFrederic Weisbecker 	}
47698402807SFrederic Weisbecker 
4772eeaaa09SStephane Eranian 	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
4788d3eca20SDavid Ahern 		rc = write_output(rec, &finished_round_event,
4798d3eca20SDavid Ahern 				  sizeof(finished_round_event));
4808d3eca20SDavid Ahern 
4818d3eca20SDavid Ahern out:
4828d3eca20SDavid Ahern 	return rc;
48398402807SFrederic Weisbecker }
48498402807SFrederic Weisbecker 
485d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
48686470930SIngo Molnar {
48786470930SIngo Molnar 	struct stat st;
48886470930SIngo Molnar 	int flags;
489781ba9d2SRobert Richter 	int err, output, feat;
4908b412664SPeter Zijlstra 	unsigned long waking = 0;
49146be604bSZhang, Yanmin 	const bool forks = argc > 0;
49223346f21SArnaldo Carvalho de Melo 	struct machine *machine;
49345694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
494d20deb64SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = &rec->opts;
495d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list = rec->evlist;
496d20deb64SArnaldo Carvalho de Melo 	const char *output_name = rec->output_name;
497d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
4982711926aSJiri Olsa 	bool disabled = false;
49986470930SIngo Molnar 
500d20deb64SArnaldo Carvalho de Melo 	rec->progname = argv[0];
50133e49ea7SAndi Kleen 
502d20deb64SArnaldo Carvalho de Melo 	rec->page_size = sysconf(_SC_PAGE_SIZE);
50386470930SIngo Molnar 
504d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__sig_exit, rec);
505f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
506f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
50718483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
508f5970550SPeter Zijlstra 
509d7065adbSFranck Bui-Huu 	if (!output_name) {
510d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
511d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
512d7065adbSFranck Bui-Huu 		else
513d20deb64SArnaldo Carvalho de Melo 			rec->output_name = output_name = "perf.data";
514d7065adbSFranck Bui-Huu 	}
515d7065adbSFranck Bui-Huu 	if (output_name) {
516529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
517d20deb64SArnaldo Carvalho de Melo 			opts->pipe_output = true;
518529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
519d20deb64SArnaldo Carvalho de Melo 			if (rec->write_mode == WRITE_FORCE) {
520b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
521b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
522b38d3464SArnaldo Carvalho de Melo 					 output_name);
523b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
524b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
525b38d3464SArnaldo Carvalho de Melo 			}
526d20deb64SArnaldo Carvalho de Melo 		} else if (rec->write_mode == WRITE_APPEND) {
527d20deb64SArnaldo Carvalho de Melo 			rec->write_mode = WRITE_FORCE;
528266e0e21SPierre Habouzit 		}
529d7065adbSFranck Bui-Huu 	}
53086470930SIngo Molnar 
531f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
532d20deb64SArnaldo Carvalho de Melo 	if (rec->write_mode == WRITE_APPEND)
533d20deb64SArnaldo Carvalho de Melo 		rec->file_new = 0;
53486470930SIngo Molnar 	else
53586470930SIngo Molnar 		flags |= O_TRUNC;
53686470930SIngo Molnar 
537d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output)
538529870e3STom Zanussi 		output = STDOUT_FILENO;
539529870e3STom Zanussi 	else
54086470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
54186470930SIngo Molnar 	if (output < 0) {
54286470930SIngo Molnar 		perror("failed to create output file");
5438d3eca20SDavid Ahern 		return -1;
54486470930SIngo Molnar 	}
54586470930SIngo Molnar 
546d20deb64SArnaldo Carvalho de Melo 	rec->output = output;
547d20deb64SArnaldo Carvalho de Melo 
5487865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
549d20deb64SArnaldo Carvalho de Melo 				    rec->write_mode == WRITE_FORCE, false, NULL);
55094c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
551a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
552a9a70bbcSArnaldo Carvalho de Melo 		return -1;
553a9a70bbcSArnaldo Carvalho de Melo 	}
554a9a70bbcSArnaldo Carvalho de Melo 
555d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
556d20deb64SArnaldo Carvalho de Melo 
557781ba9d2SRobert Richter 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
558781ba9d2SRobert Richter 		perf_header__set_feat(&session->header, feat);
559781ba9d2SRobert Richter 
560781ba9d2SRobert Richter 	if (rec->no_buildid)
561781ba9d2SRobert Richter 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
562781ba9d2SRobert Richter 
563781ba9d2SRobert Richter 	if (!have_tracepoints(&evsel_list->entries))
5642eeaaa09SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
565baa2f6ceSArnaldo Carvalho de Melo 
566330aa675SStephane Eranian 	if (!rec->opts.branch_stack)
567330aa675SStephane Eranian 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
568330aa675SStephane Eranian 
569d20deb64SArnaldo Carvalho de Melo 	if (!rec->file_new) {
570a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
5714dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
57239d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
5734dc0a04bSArnaldo Carvalho de Melo 	}
5744dc0a04bSArnaldo Carvalho de Melo 
575d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
576d20deb64SArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
57735b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
57835b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
57935b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
580856e9660SPeter Zijlstra 		}
581856e9660SPeter Zijlstra 	}
582856e9660SPeter Zijlstra 
5838d3eca20SDavid Ahern 	if (perf_record__open(rec) != 0) {
5848d3eca20SDavid Ahern 		err = -1;
5858d3eca20SDavid Ahern 		goto out_delete_session;
5868d3eca20SDavid Ahern 	}
58786470930SIngo Molnar 
588712a4b60SArnaldo Carvalho de Melo 	/*
589d20deb64SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at perf_record__exit()
590712a4b60SArnaldo Carvalho de Melo 	 */
591d20deb64SArnaldo Carvalho de Melo 	on_exit(perf_record__exit, rec);
592712a4b60SArnaldo Carvalho de Melo 
593d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
594529870e3STom Zanussi 		err = perf_header__write_pipe(output);
595529870e3STom Zanussi 		if (err < 0)
5968d3eca20SDavid Ahern 			goto out_delete_session;
597d20deb64SArnaldo Carvalho de Melo 	} else if (rec->file_new) {
598a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
599361c99a6SArnaldo Carvalho de Melo 						 output, false);
600d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
6018d3eca20SDavid Ahern 			goto out_delete_session;
602d5eed904SArnaldo Carvalho de Melo 	}
6037c6a1c65SPeter Zijlstra 
604d3665498SDavid Ahern 	if (!rec->no_buildid
605e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
606d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
607e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
6088d3eca20SDavid Ahern 		err = -1;
6098d3eca20SDavid Ahern 		goto out_delete_session;
610e20960c0SRobert Richter 	}
611e20960c0SRobert Richter 
612d20deb64SArnaldo Carvalho de Melo 	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
6136122e4e4SArnaldo Carvalho de Melo 
614743eb868SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
615743eb868SArnaldo Carvalho de Melo 	if (!machine) {
616743eb868SArnaldo Carvalho de Melo 		pr_err("Couldn't find native kernel information.\n");
6178d3eca20SDavid Ahern 		err = -1;
6188d3eca20SDavid Ahern 		goto out_delete_session;
619743eb868SArnaldo Carvalho de Melo 	}
620743eb868SArnaldo Carvalho de Melo 
621d20deb64SArnaldo Carvalho de Melo 	if (opts->pipe_output) {
62245694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_attrs(tool, session,
623a91e5431SArnaldo Carvalho de Melo 						   process_synthesized_event);
6242c46dbb5STom Zanussi 		if (err < 0) {
6252c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
6268d3eca20SDavid Ahern 			goto out_delete_session;
6272c46dbb5STom Zanussi 		}
628cd19a035STom Zanussi 
62945694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(tool, process_synthesized_event,
630743eb868SArnaldo Carvalho de Melo 							 machine);
631cd19a035STom Zanussi 		if (err < 0) {
632cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
6338d3eca20SDavid Ahern 			goto out_delete_session;
634cd19a035STom Zanussi 		}
6359215545eSTom Zanussi 
636361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
63763e0c771STom Zanussi 			/*
63863e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
63963e0c771STom Zanussi 			 * there were no tracepoints so its not really
64063e0c771STom Zanussi 			 * an error, just that we don't need to
64163e0c771STom Zanussi 			 * synthesize anything.  We really have to
64263e0c771STom Zanussi 			 * return this more properly and also
64363e0c771STom Zanussi 			 * propagate errors that now are calling die()
64463e0c771STom Zanussi 			 */
64545694aa7SArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
646743eb868SArnaldo Carvalho de Melo 								  process_synthesized_event);
64763e0c771STom Zanussi 			if (err <= 0) {
64863e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
6498d3eca20SDavid Ahern 				goto out_delete_session;
65063e0c771STom Zanussi 			}
651d20deb64SArnaldo Carvalho de Melo 			advance_output(rec, err);
6522c46dbb5STom Zanussi 		}
65363e0c771STom Zanussi 	}
6542c46dbb5STom Zanussi 
65545694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
656743eb868SArnaldo Carvalho de Melo 						 machine, "_text");
65770162138SArnaldo Carvalho de Melo 	if (err < 0)
65845694aa7SArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
659743eb868SArnaldo Carvalho de Melo 							 machine, "_stext");
660c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
661c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
662c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
663c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
66456b03f3cSArnaldo Carvalho de Melo 
66545694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
666743eb868SArnaldo Carvalho de Melo 					     machine);
667c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
668c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
669c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
670c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
671c1a3a4b9SArnaldo Carvalho de Melo 
672a1645ce1SZhang, Yanmin 	if (perf_guest)
67345694aa7SArnaldo Carvalho de Melo 		perf_session__process_machines(session, tool,
6748115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
675b7cece76SArnaldo Carvalho de Melo 
676bea03405SNamhyung Kim 	if (!opts->target.system_wide)
6778d3eca20SDavid Ahern 		err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
6788115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
679743eb868SArnaldo Carvalho de Melo 						  machine);
680234fbbf5SArnaldo Carvalho de Melo 	else
6818d3eca20SDavid Ahern 		err = perf_event__synthesize_threads(tool, process_synthesized_event,
682743eb868SArnaldo Carvalho de Melo 					       machine);
6837c6a1c65SPeter Zijlstra 
6848d3eca20SDavid Ahern 	if (err != 0)
6858d3eca20SDavid Ahern 		goto out_delete_session;
6868d3eca20SDavid Ahern 
687d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
68886470930SIngo Molnar 		struct sched_param param;
68986470930SIngo Molnar 
690d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
69186470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6926beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
6938d3eca20SDavid Ahern 			err = -1;
6948d3eca20SDavid Ahern 			goto out_delete_session;
69586470930SIngo Molnar 		}
69686470930SIngo Molnar 	}
69786470930SIngo Molnar 
698774cb499SJiri Olsa 	/*
699774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
700774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
701774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
702774cb499SJiri Olsa 	 */
703774cb499SJiri Olsa 	if (!perf_target__none(&opts->target))
704764e16a3SDavid Ahern 		perf_evlist__enable(evsel_list);
705764e16a3SDavid Ahern 
706856e9660SPeter Zijlstra 	/*
707856e9660SPeter Zijlstra 	 * Let the child rip
708856e9660SPeter Zijlstra 	 */
709d4db3f16SArnaldo Carvalho de Melo 	if (forks)
71035b9d88eSArnaldo Carvalho de Melo 		perf_evlist__start_workload(evsel_list);
711856e9660SPeter Zijlstra 
712649c48a9SPeter Zijlstra 	for (;;) {
713d20deb64SArnaldo Carvalho de Melo 		int hits = rec->samples;
71486470930SIngo Molnar 
7158d3eca20SDavid Ahern 		if (perf_record__mmap_read_all(rec) < 0) {
7168d3eca20SDavid Ahern 			err = -1;
7178d3eca20SDavid Ahern 			goto out_delete_session;
7188d3eca20SDavid Ahern 		}
71986470930SIngo Molnar 
720d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
721649c48a9SPeter Zijlstra 			if (done)
722649c48a9SPeter Zijlstra 				break;
7235c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
7248b412664SPeter Zijlstra 			waking++;
7258b412664SPeter Zijlstra 		}
7268b412664SPeter Zijlstra 
727774cb499SJiri Olsa 		/*
728774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
729774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
730774cb499SJiri Olsa 		 * disable events in this case.
731774cb499SJiri Olsa 		 */
7322711926aSJiri Olsa 		if (done && !disabled && !perf_target__none(&opts->target)) {
7334152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
7342711926aSJiri Olsa 			disabled = true;
7352711926aSJiri Olsa 		}
7368b412664SPeter Zijlstra 	}
7378b412664SPeter Zijlstra 
73818483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
739b44308f5SArnaldo Carvalho de Melo 		return 0;
740b44308f5SArnaldo Carvalho de Melo 
7418b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
74286470930SIngo Molnar 
74386470930SIngo Molnar 	/*
74486470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
74586470930SIngo Molnar 	 */
74686470930SIngo Molnar 	fprintf(stderr,
7479486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
748d20deb64SArnaldo Carvalho de Melo 		(double)rec->bytes_written / 1024.0 / 1024.0,
74986470930SIngo Molnar 		output_name,
750d20deb64SArnaldo Carvalho de Melo 		rec->bytes_written / 24);
75186470930SIngo Molnar 
75286470930SIngo Molnar 	return 0;
75339d17dacSArnaldo Carvalho de Melo 
75439d17dacSArnaldo Carvalho de Melo out_delete_session:
75539d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
75639d17dacSArnaldo Carvalho de Melo 	return err;
75786470930SIngo Molnar }
75886470930SIngo Molnar 
759bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \
760bdfebd84SRoberto Agostino Vitillo 	{ .name = n, .mode = (m) }
761bdfebd84SRoberto Agostino Vitillo 
762bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL }
763bdfebd84SRoberto Agostino Vitillo 
764bdfebd84SRoberto Agostino Vitillo struct branch_mode {
765bdfebd84SRoberto Agostino Vitillo 	const char *name;
766bdfebd84SRoberto Agostino Vitillo 	int mode;
767bdfebd84SRoberto Agostino Vitillo };
768bdfebd84SRoberto Agostino Vitillo 
769bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = {
770bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
771bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
772bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
773bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
774bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
775bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
776bdfebd84SRoberto Agostino Vitillo 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
777bdfebd84SRoberto Agostino Vitillo 	BRANCH_END
778bdfebd84SRoberto Agostino Vitillo };
779bdfebd84SRoberto Agostino Vitillo 
780bdfebd84SRoberto Agostino Vitillo static int
781a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset)
782bdfebd84SRoberto Agostino Vitillo {
783bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \
784bdfebd84SRoberto Agostino Vitillo 	(PERF_SAMPLE_BRANCH_USER	|\
785bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_KERNEL	|\
786bdfebd84SRoberto Agostino Vitillo 	 PERF_SAMPLE_BRANCH_HV)
787bdfebd84SRoberto Agostino Vitillo 
788bdfebd84SRoberto Agostino Vitillo 	uint64_t *mode = (uint64_t *)opt->value;
789bdfebd84SRoberto Agostino Vitillo 	const struct branch_mode *br;
790a5aabdacSStephane Eranian 	char *s, *os = NULL, *p;
791bdfebd84SRoberto Agostino Vitillo 	int ret = -1;
792bdfebd84SRoberto Agostino Vitillo 
793a5aabdacSStephane Eranian 	if (unset)
794a5aabdacSStephane Eranian 		return 0;
795bdfebd84SRoberto Agostino Vitillo 
796a5aabdacSStephane Eranian 	/*
797a5aabdacSStephane Eranian 	 * cannot set it twice, -b + --branch-filter for instance
798a5aabdacSStephane Eranian 	 */
799a5aabdacSStephane Eranian 	if (*mode)
800a5aabdacSStephane Eranian 		return -1;
801a5aabdacSStephane Eranian 
802a5aabdacSStephane Eranian 	/* str may be NULL in case no arg is passed to -b */
803a5aabdacSStephane Eranian 	if (str) {
804bdfebd84SRoberto Agostino Vitillo 		/* because str is read-only */
805bdfebd84SRoberto Agostino Vitillo 		s = os = strdup(str);
806bdfebd84SRoberto Agostino Vitillo 		if (!s)
807bdfebd84SRoberto Agostino Vitillo 			return -1;
808bdfebd84SRoberto Agostino Vitillo 
809bdfebd84SRoberto Agostino Vitillo 		for (;;) {
810bdfebd84SRoberto Agostino Vitillo 			p = strchr(s, ',');
811bdfebd84SRoberto Agostino Vitillo 			if (p)
812bdfebd84SRoberto Agostino Vitillo 				*p = '\0';
813bdfebd84SRoberto Agostino Vitillo 
814bdfebd84SRoberto Agostino Vitillo 			for (br = branch_modes; br->name; br++) {
815bdfebd84SRoberto Agostino Vitillo 				if (!strcasecmp(s, br->name))
816bdfebd84SRoberto Agostino Vitillo 					break;
817bdfebd84SRoberto Agostino Vitillo 			}
818a5aabdacSStephane Eranian 			if (!br->name) {
819a5aabdacSStephane Eranian 				ui__warning("unknown branch filter %s,"
820a5aabdacSStephane Eranian 					    " check man page\n", s);
821bdfebd84SRoberto Agostino Vitillo 				goto error;
822a5aabdacSStephane Eranian 			}
823bdfebd84SRoberto Agostino Vitillo 
824bdfebd84SRoberto Agostino Vitillo 			*mode |= br->mode;
825bdfebd84SRoberto Agostino Vitillo 
826bdfebd84SRoberto Agostino Vitillo 			if (!p)
827bdfebd84SRoberto Agostino Vitillo 				break;
828bdfebd84SRoberto Agostino Vitillo 
829bdfebd84SRoberto Agostino Vitillo 			s = p + 1;
830bdfebd84SRoberto Agostino Vitillo 		}
831a5aabdacSStephane Eranian 	}
832bdfebd84SRoberto Agostino Vitillo 	ret = 0;
833bdfebd84SRoberto Agostino Vitillo 
834a5aabdacSStephane Eranian 	/* default to any branch */
835bdfebd84SRoberto Agostino Vitillo 	if ((*mode & ~ONLY_PLM) == 0) {
836a5aabdacSStephane Eranian 		*mode = PERF_SAMPLE_BRANCH_ANY;
837bdfebd84SRoberto Agostino Vitillo 	}
838bdfebd84SRoberto Agostino Vitillo error:
839bdfebd84SRoberto Agostino Vitillo 	free(os);
840bdfebd84SRoberto Agostino Vitillo 	return ret;
841bdfebd84SRoberto Agostino Vitillo }
842bdfebd84SRoberto Agostino Vitillo 
84395485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
84426d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size)
84526d33022SJiri Olsa {
84626d33022SJiri Olsa 	char *endptr;
84726d33022SJiri Olsa 	unsigned long size;
84826d33022SJiri Olsa 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
84926d33022SJiri Olsa 
85026d33022SJiri Olsa 	size = strtoul(str, &endptr, 0);
85126d33022SJiri Olsa 
85226d33022SJiri Olsa 	do {
85326d33022SJiri Olsa 		if (*endptr)
85426d33022SJiri Olsa 			break;
85526d33022SJiri Olsa 
85626d33022SJiri Olsa 		size = round_up(size, sizeof(u64));
85726d33022SJiri Olsa 		if (!size || size > max_size)
85826d33022SJiri Olsa 			break;
85926d33022SJiri Olsa 
86026d33022SJiri Olsa 		*_size = size;
86126d33022SJiri Olsa 		return 0;
86226d33022SJiri Olsa 
86326d33022SJiri Olsa 	} while (0);
86426d33022SJiri Olsa 
86526d33022SJiri Olsa 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
86626d33022SJiri Olsa 	       max_size, str);
86726d33022SJiri Olsa 	return -1;
86826d33022SJiri Olsa }
86995485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
87026d33022SJiri Olsa 
871*c5ff78c3SArnaldo Carvalho de Melo static int parse_callchain_opt(const struct option *opt, const char *arg, int unset)
87226d33022SJiri Olsa {
873*c5ff78c3SArnaldo Carvalho de Melo 	struct perf_record_opts *opts = opt->value;
87426d33022SJiri Olsa 	char *tok, *name, *saveptr = NULL;
87526d33022SJiri Olsa 	char *buf;
87626d33022SJiri Olsa 	int ret = -1;
87726d33022SJiri Olsa 
87826d33022SJiri Olsa 	/* --no-call-graph */
87926d33022SJiri Olsa 	if (unset)
88026d33022SJiri Olsa 		return 0;
88126d33022SJiri Olsa 
88226d33022SJiri Olsa 	/* We specified default option if none is provided. */
88326d33022SJiri Olsa 	BUG_ON(!arg);
88426d33022SJiri Olsa 
88526d33022SJiri Olsa 	/* We need buffer that we know we can write to. */
88626d33022SJiri Olsa 	buf = malloc(strlen(arg) + 1);
88726d33022SJiri Olsa 	if (!buf)
88826d33022SJiri Olsa 		return -ENOMEM;
88926d33022SJiri Olsa 
89026d33022SJiri Olsa 	strcpy(buf, arg);
89126d33022SJiri Olsa 
89226d33022SJiri Olsa 	tok = strtok_r((char *)buf, ",", &saveptr);
89326d33022SJiri Olsa 	name = tok ? : (char *)buf;
89426d33022SJiri Olsa 
89526d33022SJiri Olsa 	do {
89626d33022SJiri Olsa 		/* Framepointer style */
89726d33022SJiri Olsa 		if (!strncmp(name, "fp", sizeof("fp"))) {
89826d33022SJiri Olsa 			if (!strtok_r(NULL, ",", &saveptr)) {
899*c5ff78c3SArnaldo Carvalho de Melo 				opts->call_graph = CALLCHAIN_FP;
90026d33022SJiri Olsa 				ret = 0;
90126d33022SJiri Olsa 			} else
90226d33022SJiri Olsa 				pr_err("callchain: No more arguments "
90326d33022SJiri Olsa 				       "needed for -g fp\n");
90426d33022SJiri Olsa 			break;
90526d33022SJiri Olsa 
90695485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT
90726d33022SJiri Olsa 		/* Dwarf style */
90826d33022SJiri Olsa 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
90961eaa3beSArnaldo Carvalho de Melo 			const unsigned long default_stack_dump_size = 8192;
91061eaa3beSArnaldo Carvalho de Melo 
91126d33022SJiri Olsa 			ret = 0;
912*c5ff78c3SArnaldo Carvalho de Melo 			opts->call_graph = CALLCHAIN_DWARF;
913*c5ff78c3SArnaldo Carvalho de Melo 			opts->stack_dump_size = default_stack_dump_size;
91426d33022SJiri Olsa 
91526d33022SJiri Olsa 			tok = strtok_r(NULL, ",", &saveptr);
91626d33022SJiri Olsa 			if (tok) {
91726d33022SJiri Olsa 				unsigned long size = 0;
91826d33022SJiri Olsa 
91926d33022SJiri Olsa 				ret = get_stack_size(tok, &size);
920*c5ff78c3SArnaldo Carvalho de Melo 				opts->stack_dump_size = size;
92126d33022SJiri Olsa 			}
92226d33022SJiri Olsa 
92326d33022SJiri Olsa 			if (!ret)
92426d33022SJiri Olsa 				pr_debug("callchain: stack dump size %d\n",
925*c5ff78c3SArnaldo Carvalho de Melo 					 opts->stack_dump_size);
92695485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */
92726d33022SJiri Olsa 		} else {
92826d33022SJiri Olsa 			pr_err("callchain: Unknown -g option "
92926d33022SJiri Olsa 			       "value: %s\n", arg);
93026d33022SJiri Olsa 			break;
93126d33022SJiri Olsa 		}
93226d33022SJiri Olsa 
93326d33022SJiri Olsa 	} while (0);
93426d33022SJiri Olsa 
93526d33022SJiri Olsa 	free(buf);
93626d33022SJiri Olsa 
93726d33022SJiri Olsa 	if (!ret)
938*c5ff78c3SArnaldo Carvalho de Melo 		pr_debug("callchain: type %d\n", opts->call_graph);
93926d33022SJiri Olsa 
94026d33022SJiri Olsa 	return ret;
94126d33022SJiri Olsa }
94226d33022SJiri Olsa 
94386470930SIngo Molnar static const char * const record_usage[] = {
94486470930SIngo Molnar 	"perf record [<options>] [<command>]",
94586470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
94686470930SIngo Molnar 	NULL
94786470930SIngo Molnar };
94886470930SIngo Molnar 
949d20deb64SArnaldo Carvalho de Melo /*
950d20deb64SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
951d20deb64SArnaldo Carvalho de Melo  * because we need to have access to it in perf_record__exit, that is called
952d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
953d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
954d20deb64SArnaldo Carvalho de Melo  *
955d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
956d20deb64SArnaldo Carvalho de Melo  *
957d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
958d20deb64SArnaldo Carvalho de Melo  */
959d20deb64SArnaldo Carvalho de Melo static struct perf_record record = {
960d20deb64SArnaldo Carvalho de Melo 	.opts = {
961d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
962d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
963d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
964447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
965d1cb9fceSNamhyung Kim 		.target		     = {
966d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
967d1cb9fceSNamhyung Kim 		},
968d20deb64SArnaldo Carvalho de Melo 	},
969d20deb64SArnaldo Carvalho de Melo 	.write_mode = WRITE_FORCE,
970d20deb64SArnaldo Carvalho de Melo 	.file_new   = true,
971d20deb64SArnaldo Carvalho de Melo };
9727865e817SFrederic Weisbecker 
97361eaa3beSArnaldo Carvalho de Melo #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
97461eaa3beSArnaldo Carvalho de Melo 
97561eaa3beSArnaldo Carvalho de Melo #ifdef LIBUNWIND_SUPPORT
97661eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
97761eaa3beSArnaldo Carvalho de Melo #else
97861eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
97961eaa3beSArnaldo Carvalho de Melo #endif
98061eaa3beSArnaldo Carvalho de Melo 
981d20deb64SArnaldo Carvalho de Melo /*
982d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
983d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
984d20deb64SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use perf_record_opts,
985d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
986d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
987d20deb64SArnaldo Carvalho de Melo  */
988bca647aaSTom Zanussi const struct option record_options[] = {
989d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
99086470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
991f120f9d5SJiri Olsa 		     parse_events_option),
992d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
993c171b552SLi Zefan 		     "event filter", parse_filter),
994bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
995d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
996bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
997d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
998d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
99986470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
1000d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
1001acac03faSKirill Smelkov 		    "collect data without buffering"),
1002d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
1003daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
1004bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
100586470930SIngo Molnar 			    "system-wide collection from all CPUs"),
1006d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('A', "append", &record.append_file,
100786470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
1008bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
1009c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
1010d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('f', "force", &record.force,
10117865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
1012d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
1013d20deb64SArnaldo Carvalho de Melo 	OPT_STRING('o', "output", &record.output_name, "file",
101486470930SIngo Molnar 		    "output file name"),
1015d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
10162e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
1017d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1018d20deb64SArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
101901c2d99bSArnaldo Carvalho de Melo 		     "number of mmap data pages"),
1020d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
102143bece79SLin Ming 		    "put the counters into a counter group"),
1022*c5ff78c3SArnaldo Carvalho de Melo 	OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
1023*c5ff78c3SArnaldo Carvalho de Melo 			     "mode[,dump_size]", callchain_help,
1024*c5ff78c3SArnaldo Carvalho de Melo 			     &parse_callchain_opt, "fp"),
1025c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
10263da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
1027b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
1028d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1029649c48a9SPeter Zijlstra 		    "per thread counts"),
1030d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record.opts.sample_address,
10314bba828dSAnton Blanchard 		    "Sample addresses"),
1032d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
10333e76ac78SAndrew Vagin 	OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
1034d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
1035649c48a9SPeter Zijlstra 		    "don't sample"),
1036d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
1037a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
1038d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
1039baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
1040d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
1041023695d9SStephane Eranian 		     "monitor event in cgroup name only",
1042023695d9SStephane Eranian 		     parse_cgroups),
1043bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
1044bea03405SNamhyung Kim 		   "user to profile"),
1045a5aabdacSStephane Eranian 
1046a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
1047a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
1048a5aabdacSStephane Eranian 		     parse_branch_stack),
1049a5aabdacSStephane Eranian 
1050a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
1051a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
1052bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
105386470930SIngo Molnar 	OPT_END()
105486470930SIngo Molnar };
105586470930SIngo Molnar 
10561d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
105786470930SIngo Molnar {
105869aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
105969aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
1060d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evsel_list;
1061d20deb64SArnaldo Carvalho de Melo 	struct perf_record *rec = &record;
106216ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
106386470930SIngo Molnar 
10647e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
1065361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
1066361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
1067361c99a6SArnaldo Carvalho de Melo 
1068d20deb64SArnaldo Carvalho de Melo 	rec->evlist = evsel_list;
1069d20deb64SArnaldo Carvalho de Melo 
1070bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
1071a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
1072d67356e7SNamhyung Kim 	if (!argc && perf_target__none(&rec->opts.target))
1073bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
107486470930SIngo Molnar 
1075d20deb64SArnaldo Carvalho de Melo 	if (rec->force && rec->append_file) {
10763780f488SNamhyung Kim 		ui__error("Can't overwrite and append at the same time."
10777865e817SFrederic Weisbecker 			  " You need to choose between -f and -A");
1078bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
1079d20deb64SArnaldo Carvalho de Melo 	} else if (rec->append_file) {
1080d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_APPEND;
10817865e817SFrederic Weisbecker 	} else {
1082d20deb64SArnaldo Carvalho de Melo 		rec->write_mode = WRITE_FORCE;
10837865e817SFrederic Weisbecker 	}
10847865e817SFrederic Weisbecker 
1085bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
10863780f488SNamhyung Kim 		ui__error("cgroup monitoring only available in"
1087023695d9SStephane Eranian 			  " system-wide mode\n");
1088023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
1089023695d9SStephane Eranian 	}
1090023695d9SStephane Eranian 
1091655000e7SArnaldo Carvalho de Melo 	symbol__init();
1092baa2f6ceSArnaldo Carvalho de Melo 
1093ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
1094646aaea6SArnaldo Carvalho de Melo 		pr_warning(
1095646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
1096ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
1097646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
1098646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
1099646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
1100646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1101646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
1102ec80fde7SArnaldo Carvalho de Melo 
1103d20deb64SArnaldo Carvalho de Melo 	if (rec->no_buildid_cache || rec->no_buildid)
1104a1ac1d3cSStephane Eranian 		disable_buildid_cache();
1105655000e7SArnaldo Carvalho de Melo 
1106361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
1107361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
110869aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
110969aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
1110bbd36e5eSPeter Zijlstra 	}
111186470930SIngo Molnar 
111216ad2ffbSNamhyung Kim 	err = perf_target__validate(&rec->opts.target);
111316ad2ffbSNamhyung Kim 	if (err) {
111416ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
111516ad2ffbSNamhyung Kim 		ui__warning("%s", errbuf);
111616ad2ffbSNamhyung Kim 	}
11174bd0f2d2SNamhyung Kim 
111816ad2ffbSNamhyung Kim 	err = perf_target__parse_uid(&rec->opts.target);
111916ad2ffbSNamhyung Kim 	if (err) {
112016ad2ffbSNamhyung Kim 		int saved_errno = errno;
112116ad2ffbSNamhyung Kim 
112216ad2ffbSNamhyung Kim 		perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
11233780f488SNamhyung Kim 		ui__error("%s", errbuf);
112416ad2ffbSNamhyung Kim 
112516ad2ffbSNamhyung Kim 		err = -saved_errno;
11260d37aa34SArnaldo Carvalho de Melo 		goto out_free_fd;
112716ad2ffbSNamhyung Kim 	}
11280d37aa34SArnaldo Carvalho de Melo 
112916ad2ffbSNamhyung Kim 	err = -ENOMEM;
1130b809ac10SNamhyung Kim 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
1131dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
113269aad6f1SArnaldo Carvalho de Melo 
1133361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
11347289f83cSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
1135ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
1136d6d901c2SZhang, Yanmin 	}
11375c581041SArnaldo Carvalho de Melo 
1138d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_interval != ULLONG_MAX)
1139d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.user_interval;
1140d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.user_freq != UINT_MAX)
1141d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = rec->opts.user_freq;
1142f9212819SFrederic Weisbecker 
11437e4ff9e3SMike Galbraith 	/*
11447e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
11457e4ff9e3SMike Galbraith 	 */
1146d20deb64SArnaldo Carvalho de Melo 	if (rec->opts.default_interval)
1147d20deb64SArnaldo Carvalho de Melo 		rec->opts.freq = 0;
1148d20deb64SArnaldo Carvalho de Melo 	else if (rec->opts.freq) {
1149d20deb64SArnaldo Carvalho de Melo 		rec->opts.default_interval = rec->opts.freq;
11507e4ff9e3SMike Galbraith 	} else {
11513780f488SNamhyung Kim 		ui__error("frequency and count are zero, aborting\n");
115239d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
11535c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
11547e4ff9e3SMike Galbraith 	}
11557e4ff9e3SMike Galbraith 
1156d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
115739d17dacSArnaldo Carvalho de Melo out_free_fd:
11587e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
1159d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
1160d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
116139d17dacSArnaldo Carvalho de Melo 	return err;
116286470930SIngo Molnar }
1163