xref: /openbmc/linux/tools/perf/builtin-record.c (revision 33e49ea70df066651a17061c62118fc3f075d21f)
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"
258d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
26a12b51c4SPaul Mackerras #include "util/cpumap.h"
27fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
287c6a1c65SPeter Zijlstra 
2986470930SIngo Molnar #include <unistd.h>
3086470930SIngo Molnar #include <sched.h>
31a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
3286470930SIngo Molnar 
337865e817SFrederic Weisbecker enum write_mode_t {
347865e817SFrederic Weisbecker 	WRITE_FORCE,
357865e817SFrederic Weisbecker 	WRITE_APPEND
367865e817SFrederic Weisbecker };
377865e817SFrederic Weisbecker 
383de29cabSStephane Eranian static u64			user_interval			= ULLONG_MAX;
393de29cabSStephane Eranian static u64			default_interval		=      0;
4086470930SIngo Molnar 
4186470930SIngo Molnar static unsigned int		page_size;
42800cd25cSFrederic Weisbecker static unsigned int		mmap_pages			= UINT_MAX;
43f9212819SFrederic Weisbecker static unsigned int		user_freq 			= UINT_MAX;
4442e59d7dSIngo Molnar static int			freq				=   1000;
4586470930SIngo Molnar static int			output;
46529870e3STom Zanussi static int			pipe_output			=      0;
47d7065adbSFranck Bui-Huu static const char		*output_name			= NULL;
4843bece79SLin Ming static bool			group				=  false;
491967936dSArnaldo Carvalho de Melo static int			realtime_prio			=      0;
50acac03faSKirill Smelkov static bool			nodelay				=  false;
51c0555642SIan Munsie static bool			raw_samples			=  false;
529c90a61cSArnaldo Carvalho de Melo static bool			sample_id_all_avail		=   true;
53c0555642SIan Munsie static bool			system_wide			=  false;
5486470930SIngo Molnar static pid_t			target_pid			=     -1;
55d6d901c2SZhang, Yanmin static pid_t			target_tid			=     -1;
56933da83aSChris Wilson static pid_t			child_pid			=     -1;
572e6cdf99SStephane Eranian static bool			no_inherit			=  false;
587865e817SFrederic Weisbecker static enum write_mode_t	write_mode			= WRITE_FORCE;
59c0555642SIan Munsie static bool			call_graph			=  false;
60c0555642SIan Munsie static bool			inherit_stat			=  false;
61c0555642SIan Munsie static bool			no_samples			=  false;
62c0555642SIan Munsie static bool			sample_address			=  false;
639c90a61cSArnaldo Carvalho de Melo static bool			sample_time			=  false;
64a1ac1d3cSStephane Eranian static bool			no_buildid			=  false;
65baa2f6ceSArnaldo Carvalho de Melo static bool			no_buildid_cache		=  false;
66361c99a6SArnaldo Carvalho de Melo static struct perf_evlist	*evsel_list;
6786470930SIngo Molnar 
6842e59d7dSIngo Molnar static long			samples				=      0;
6942e59d7dSIngo Molnar static u64			bytes_written			=      0;
7086470930SIngo Molnar 
71f5970550SPeter Zijlstra static int			file_new			=      1;
726122e4e4SArnaldo Carvalho de Melo static off_t			post_processing_offset;
737c6a1c65SPeter Zijlstra 
7494c744b6SArnaldo Carvalho de Melo static struct perf_session	*session;
75c45c6ea2SStephane Eranian static const char		*cpu_list;
76*33e49ea7SAndi Kleen static const char               *progname;
77f5970550SPeter Zijlstra 
789215545eSTom Zanussi static void advance_output(size_t size)
799215545eSTom Zanussi {
809215545eSTom Zanussi 	bytes_written += size;
819215545eSTom Zanussi }
829215545eSTom Zanussi 
83f5970550SPeter Zijlstra static void write_output(void *buf, size_t size)
84f5970550SPeter Zijlstra {
85f5970550SPeter Zijlstra 	while (size) {
86f5970550SPeter Zijlstra 		int ret = write(output, buf, size);
87f5970550SPeter Zijlstra 
88f5970550SPeter Zijlstra 		if (ret < 0)
89f5970550SPeter Zijlstra 			die("failed to write");
90f5970550SPeter Zijlstra 
91f5970550SPeter Zijlstra 		size -= ret;
92f5970550SPeter Zijlstra 		buf += ret;
93f5970550SPeter Zijlstra 
94f5970550SPeter Zijlstra 		bytes_written += ret;
95f5970550SPeter Zijlstra 	}
96f5970550SPeter Zijlstra }
97f5970550SPeter Zijlstra 
988115d60cSArnaldo Carvalho de Melo static int process_synthesized_event(union perf_event *event,
998d50e5b4SArnaldo Carvalho de Melo 				     struct perf_sample *sample __used,
100d8f66248SArnaldo Carvalho de Melo 				     struct perf_session *self __used)
101234fbbf5SArnaldo Carvalho de Melo {
1026122e4e4SArnaldo Carvalho de Melo 	write_output(event, event->header.size);
103234fbbf5SArnaldo Carvalho de Melo 	return 0;
104234fbbf5SArnaldo Carvalho de Melo }
105234fbbf5SArnaldo Carvalho de Melo 
106744bd8aaSArnaldo Carvalho de Melo static void mmap_read(struct perf_mmap *md)
10786470930SIngo Molnar {
108744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
10986470930SIngo Molnar 	unsigned int old = md->prev;
11086470930SIngo Molnar 	unsigned char *data = md->base + page_size;
11186470930SIngo Molnar 	unsigned long size;
11286470930SIngo Molnar 	void *buf;
11386470930SIngo Molnar 
114dc82009aSArnaldo Carvalho de Melo 	if (old == head)
115dc82009aSArnaldo Carvalho de Melo 		return;
11686470930SIngo Molnar 
11786470930SIngo Molnar 	samples++;
11886470930SIngo Molnar 
11986470930SIngo Molnar 	size = head - old;
12086470930SIngo Molnar 
12186470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
12286470930SIngo Molnar 		buf = &data[old & md->mask];
12386470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
12486470930SIngo Molnar 		old += size;
12586470930SIngo Molnar 
1266122e4e4SArnaldo Carvalho de Melo 		write_output(buf, size);
12786470930SIngo Molnar 	}
12886470930SIngo Molnar 
12986470930SIngo Molnar 	buf = &data[old & md->mask];
13086470930SIngo Molnar 	size = head - old;
13186470930SIngo Molnar 	old += size;
13286470930SIngo Molnar 
1336122e4e4SArnaldo Carvalho de Melo 	write_output(buf, size);
13486470930SIngo Molnar 
13586470930SIngo Molnar 	md->prev = old;
136115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
13786470930SIngo Molnar }
13886470930SIngo Molnar 
13986470930SIngo Molnar static volatile int done = 0;
140f7b7c26eSPeter Zijlstra static volatile int signr = -1;
141*33e49ea7SAndi Kleen static volatile int child_finished = 0;
14286470930SIngo Molnar 
14386470930SIngo Molnar static void sig_handler(int sig)
14486470930SIngo Molnar {
145*33e49ea7SAndi Kleen 	if (sig == SIGCHLD)
146*33e49ea7SAndi Kleen 		child_finished = 1;
147*33e49ea7SAndi Kleen 
14886470930SIngo Molnar 	done = 1;
149f7b7c26eSPeter Zijlstra 	signr = sig;
150f7b7c26eSPeter Zijlstra }
151f7b7c26eSPeter Zijlstra 
152f7b7c26eSPeter Zijlstra static void sig_atexit(void)
153f7b7c26eSPeter Zijlstra {
154*33e49ea7SAndi Kleen 	int status;
155*33e49ea7SAndi Kleen 
156*33e49ea7SAndi Kleen 	if (child_pid > 0) {
157*33e49ea7SAndi Kleen 		if (!child_finished)
158933da83aSChris Wilson 			kill(child_pid, SIGTERM);
159933da83aSChris Wilson 
160*33e49ea7SAndi Kleen 		wait(&status);
161*33e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
162*33e49ea7SAndi Kleen 			psignal(WTERMSIG(status), progname);
163*33e49ea7SAndi Kleen 	}
164*33e49ea7SAndi Kleen 
16518483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
166f7b7c26eSPeter Zijlstra 		return;
167f7b7c26eSPeter Zijlstra 
168f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
169f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
17086470930SIngo Molnar }
17186470930SIngo Molnar 
172dd7927f4SArnaldo Carvalho de Melo static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
173dd7927f4SArnaldo Carvalho de Melo {
174dd7927f4SArnaldo Carvalho de Melo 	struct perf_event_attr *attr = &evsel->attr;
175dd7927f4SArnaldo Carvalho de Melo 	int track = !evsel->idx; /* only the first counter needs these */
1767c6a1c65SPeter Zijlstra 
1775d2cd909SArnaldo Carvalho de Melo 	attr->inherit		= !no_inherit;
1787c6a1c65SPeter Zijlstra 	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
1797c6a1c65SPeter Zijlstra 				  PERF_FORMAT_TOTAL_TIME_RUNNING |
1807c6a1c65SPeter Zijlstra 				  PERF_FORMAT_ID;
18186470930SIngo Molnar 
1823a9f131fSFrederic Weisbecker 	attr->sample_type	|= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1833efa1cc9SIngo Molnar 
184361c99a6SArnaldo Carvalho de Melo 	if (evlist->nr_entries > 1)
1858907fd60SEric B Munson 		attr->sample_type |= PERF_SAMPLE_ID;
1868907fd60SEric B Munson 
187f9212819SFrederic Weisbecker 	/*
188f9212819SFrederic Weisbecker 	 * We default some events to a 1 default interval. But keep
189f9212819SFrederic Weisbecker 	 * it a weak assumption overridable by the user.
190f9212819SFrederic Weisbecker 	 */
191f9212819SFrederic Weisbecker 	if (!attr->sample_period || (user_freq != UINT_MAX &&
1923de29cabSStephane Eranian 				     user_interval != ULLONG_MAX)) {
19386470930SIngo Molnar 		if (freq) {
194ea1900e5SPeter Zijlstra 			attr->sample_type	|= PERF_SAMPLE_PERIOD;
19586470930SIngo Molnar 			attr->freq		= 1;
19686470930SIngo Molnar 			attr->sample_freq	= freq;
197f9212819SFrederic Weisbecker 		} else {
198f9212819SFrederic Weisbecker 			attr->sample_period = default_interval;
199f9212819SFrederic Weisbecker 		}
20086470930SIngo Molnar 	}
2013efa1cc9SIngo Molnar 
202649c48a9SPeter Zijlstra 	if (no_samples)
203649c48a9SPeter Zijlstra 		attr->sample_freq = 0;
204649c48a9SPeter Zijlstra 
205649c48a9SPeter Zijlstra 	if (inherit_stat)
206649c48a9SPeter Zijlstra 		attr->inherit_stat = 1;
207649c48a9SPeter Zijlstra 
2083af9e859SEric B Munson 	if (sample_address) {
2094bba828dSAnton Blanchard 		attr->sample_type	|= PERF_SAMPLE_ADDR;
2103af9e859SEric B Munson 		attr->mmap_data = track;
2113af9e859SEric B Munson 	}
2124bba828dSAnton Blanchard 
2133efa1cc9SIngo Molnar 	if (call_graph)
2143efa1cc9SIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN;
2153efa1cc9SIngo Molnar 
216f60f3593SArun Sharma 	if (system_wide)
217f60f3593SArun Sharma 		attr->sample_type	|= PERF_SAMPLE_CPU;
218f60f3593SArun Sharma 
219a43d3f08SArnaldo Carvalho de Melo 	if (sample_id_all_avail &&
220a43d3f08SArnaldo Carvalho de Melo 	    (sample_time || system_wide || !no_inherit || cpu_list))
2219c90a61cSArnaldo Carvalho de Melo 		attr->sample_type	|= PERF_SAMPLE_TIME;
2229c90a61cSArnaldo Carvalho de Melo 
223cd6feeeaSIngo Molnar 	if (raw_samples) {
2246ddf259dSIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_TIME;
225daac07b2SFrederic Weisbecker 		attr->sample_type	|= PERF_SAMPLE_RAW;
226cd6feeeaSIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_CPU;
227cd6feeeaSIngo Molnar 	}
228f413cdb8SFrederic Weisbecker 
229acac03faSKirill Smelkov 	if (nodelay) {
230acac03faSKirill Smelkov 		attr->watermark = 0;
231acac03faSKirill Smelkov 		attr->wakeup_events = 1;
232acac03faSKirill Smelkov 	}
233acac03faSKirill Smelkov 
23486470930SIngo Molnar 	attr->mmap		= track;
23586470930SIngo Molnar 	attr->comm		= track;
236dd7927f4SArnaldo Carvalho de Melo 
2372e6cdf99SStephane Eranian 	if (target_pid == -1 && target_tid == -1 && !system_wide) {
2384502d77cSPeter Zijlstra 		attr->disabled = 1;
239bedbfdeaSEric B Munson 		attr->enable_on_exec = 1;
24046be604bSZhang, Yanmin 	}
241dd7927f4SArnaldo Carvalho de Melo }
242dd7927f4SArnaldo Carvalho de Melo 
243a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
244a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
245a91e5431SArnaldo Carvalho de Melo {
246a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
247a91e5431SArnaldo Carvalho de Melo 
248a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
249a91e5431SArnaldo Carvalho de Melo 		return false;
250a91e5431SArnaldo Carvalho de Melo 
251a91e5431SArnaldo Carvalho de Melo 	pair = list_entry(other->entries.next, struct perf_evsel, node);
252a91e5431SArnaldo Carvalho de Melo 
253a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
254a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
255a91e5431SArnaldo Carvalho de Melo 			return false;
256a91e5431SArnaldo Carvalho de Melo 		pair = list_entry(pair->node.next, struct perf_evsel, node);
257a91e5431SArnaldo Carvalho de Melo 	}
258a91e5431SArnaldo Carvalho de Melo 
259a91e5431SArnaldo Carvalho de Melo 	return true;
260a91e5431SArnaldo Carvalho de Melo }
261a91e5431SArnaldo Carvalho de Melo 
262dd7927f4SArnaldo Carvalho de Melo static void open_counters(struct perf_evlist *evlist)
263dd7927f4SArnaldo Carvalho de Melo {
264dd7927f4SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
265dd7927f4SArnaldo Carvalho de Melo 
2665d2cd909SArnaldo Carvalho de Melo 	if (evlist->cpus->map[0] < 0)
2675d2cd909SArnaldo Carvalho de Melo 		no_inherit = true;
2685d2cd909SArnaldo Carvalho de Melo 
269dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
270dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
271dd7927f4SArnaldo Carvalho de Melo 		/*
272dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
273dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
274dd7927f4SArnaldo Carvalho de Melo 		 *
275dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
276dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
277dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
278dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
279dd7927f4SArnaldo Carvalho de Melo 		 *
280dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
281dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
282dd7927f4SArnaldo Carvalho de Melo 		 */
283dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
284dd7927f4SArnaldo Carvalho de Melo 
285dd7927f4SArnaldo Carvalho de Melo 		config_attr(pos, evlist);
2869c90a61cSArnaldo Carvalho de Melo retry_sample_id:
2879c90a61cSArnaldo Carvalho de Melo 		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
2883da297a6SIngo Molnar try_again:
2895d2cd909SArnaldo Carvalho de Melo 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
29086470930SIngo Molnar 			int err = errno;
29186470930SIngo Molnar 
292c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
293c286c419SArnaldo Carvalho de Melo 				ui__warning_paranoid();
294c286c419SArnaldo Carvalho de Melo 				exit(EXIT_FAILURE);
295c286c419SArnaldo Carvalho de Melo 			} else if (err ==  ENODEV && cpu_list) {
296d6d901c2SZhang, Yanmin 				die("No such device - did you specify"
297d6d901c2SZhang, Yanmin 					" an out-of-range profile CPU?\n");
2989c90a61cSArnaldo Carvalho de Melo 			} else if (err == EINVAL && sample_id_all_avail) {
2999c90a61cSArnaldo Carvalho de Melo 				/*
3009c90a61cSArnaldo Carvalho de Melo 				 * Old kernel, no attr->sample_id_type_all field
3019c90a61cSArnaldo Carvalho de Melo 				 */
3029c90a61cSArnaldo Carvalho de Melo 				sample_id_all_avail = false;
303a43d3f08SArnaldo Carvalho de Melo 				if (!sample_time && !raw_samples && !time_needed)
304eac23d1cSIan Munsie 					attr->sample_type &= ~PERF_SAMPLE_TIME;
305eac23d1cSIan Munsie 
3069c90a61cSArnaldo Carvalho de Melo 				goto retry_sample_id;
307d6d901c2SZhang, Yanmin 			}
3083da297a6SIngo Molnar 
3093da297a6SIngo Molnar 			/*
3103da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
3113da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
3123da297a6SIngo Molnar 			 * is always available even if no PMU support:
3133da297a6SIngo Molnar 			 */
3143da297a6SIngo Molnar 			if (attr->type == PERF_TYPE_HARDWARE
315f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
3163da297a6SIngo Molnar 
3173da297a6SIngo Molnar 				if (verbose)
318ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
319ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
3203da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
321f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
3223da297a6SIngo Molnar 				goto try_again;
3233da297a6SIngo Molnar 			}
324ca6a4258SDavid Ahern 
325ca6a4258SDavid Ahern 			if (err == ENOENT) {
326ca6a4258SDavid Ahern 				ui__warning("The %s event is not supported.\n",
327ca6a4258SDavid Ahern 					    event_name(pos));
328ca6a4258SDavid Ahern 				exit(EXIT_FAILURE);
329ca6a4258SDavid Ahern 			}
330ca6a4258SDavid Ahern 
33130c806a0SIngo Molnar 			printf("\n");
332d9cf837eSCorey Ashford 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
333dd7927f4SArnaldo Carvalho de Melo 			      err, strerror(err));
334bfd45118SSimon Kaempflein 
335bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
336bfd45118SSimon Kaempflein 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
337d6d901c2SZhang, Yanmin 				die("No hardware sampling interrupt available."
338d6d901c2SZhang, Yanmin 				    " No APIC? If so then you can boot the kernel"
339d6d901c2SZhang, Yanmin 				    " with the \"lapic\" boot parameter to"
340d6d901c2SZhang, Yanmin 				    " force-enable it.\n");
341bfd45118SSimon Kaempflein #endif
342bfd45118SSimon Kaempflein 
343cdd6c482SIngo Molnar 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
3447c6a1c65SPeter Zijlstra 		}
3457c6a1c65SPeter Zijlstra 	}
3467c6a1c65SPeter Zijlstra 
3470a102479SFrederic Weisbecker 	if (perf_evlist__set_filters(evlist)) {
3480a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
3490a102479SFrederic Weisbecker 			strerror(errno));
3500a102479SFrederic Weisbecker 		exit(-1);
3510a102479SFrederic Weisbecker 	}
3520a102479SFrederic Weisbecker 
3537e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
3540a27d7f9SArnaldo Carvalho de Melo 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
3550a27d7f9SArnaldo Carvalho de Melo 
356a91e5431SArnaldo Carvalho de Melo 	if (file_new)
357a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
358a91e5431SArnaldo Carvalho de Melo 	else {
359a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
360a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
361a91e5431SArnaldo Carvalho de Melo 			exit(-1);
362dd7927f4SArnaldo Carvalho de Melo 		}
36386470930SIngo Molnar  	}
36486470930SIngo Molnar 
365a91e5431SArnaldo Carvalho de Melo 	perf_session__update_sample_type(session);
366a91e5431SArnaldo Carvalho de Melo }
367a91e5431SArnaldo Carvalho de Melo 
3686122e4e4SArnaldo Carvalho de Melo static int process_buildids(void)
3696122e4e4SArnaldo Carvalho de Melo {
3706122e4e4SArnaldo Carvalho de Melo 	u64 size = lseek(output, 0, SEEK_CUR);
3716122e4e4SArnaldo Carvalho de Melo 
3729f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3739f591fd7SArnaldo Carvalho de Melo 		return 0;
3749f591fd7SArnaldo Carvalho de Melo 
3756122e4e4SArnaldo Carvalho de Melo 	session->fd = output;
3766122e4e4SArnaldo Carvalho de Melo 	return __perf_session__process_events(session, post_processing_offset,
3776122e4e4SArnaldo Carvalho de Melo 					      size - post_processing_offset,
3786122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3796122e4e4SArnaldo Carvalho de Melo }
3806122e4e4SArnaldo Carvalho de Melo 
381f5970550SPeter Zijlstra static void atexit_header(void)
382f5970550SPeter Zijlstra {
383c7929e47STom Zanussi 	if (!pipe_output) {
38494c744b6SArnaldo Carvalho de Melo 		session->header.data_size += bytes_written;
385f5970550SPeter Zijlstra 
386baa2f6ceSArnaldo Carvalho de Melo 		if (!no_buildid)
3876122e4e4SArnaldo Carvalho de Melo 			process_buildids();
388a91e5431SArnaldo Carvalho de Melo 		perf_session__write_header(session, evsel_list, output, true);
38939d17dacSArnaldo Carvalho de Melo 		perf_session__delete(session);
390361c99a6SArnaldo Carvalho de Melo 		perf_evlist__delete(evsel_list);
391d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
392c7929e47STom Zanussi 	}
393f5970550SPeter Zijlstra }
394f5970550SPeter Zijlstra 
3958115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
396a1645ce1SZhang, Yanmin {
397a1645ce1SZhang, Yanmin 	int err;
39823346f21SArnaldo Carvalho de Melo 	struct perf_session *psession = data;
399a1645ce1SZhang, Yanmin 
40023346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
401a1645ce1SZhang, Yanmin 		return;
402a1645ce1SZhang, Yanmin 
403a1645ce1SZhang, Yanmin 	/*
404a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
405a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
406a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
407a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
408a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
409a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
410a1645ce1SZhang, Yanmin 	 */
4118115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
41223346f21SArnaldo Carvalho de Melo 					     psession, machine);
413a1645ce1SZhang, Yanmin 	if (err < 0)
414a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41523346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
416a1645ce1SZhang, Yanmin 
417a1645ce1SZhang, Yanmin 	/*
418a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
419a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
420a1645ce1SZhang, Yanmin 	 */
4218115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
42223346f21SArnaldo Carvalho de Melo 						 psession, machine, "_text");
423a1645ce1SZhang, Yanmin 	if (err < 0)
4248115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
4258115d60cSArnaldo Carvalho de Melo 							 psession, machine,
4268115d60cSArnaldo Carvalho de Melo 							 "_stext");
427a1645ce1SZhang, Yanmin 	if (err < 0)
428a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
42923346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
430a1645ce1SZhang, Yanmin }
431a1645ce1SZhang, Yanmin 
43298402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
43398402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
43498402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
43598402807SFrederic Weisbecker };
43698402807SFrederic Weisbecker 
43798402807SFrederic Weisbecker static void mmap_read_all(void)
43898402807SFrederic Weisbecker {
4390e2e63ddSPeter Zijlstra 	int i;
44098402807SFrederic Weisbecker 
441aece948fSArnaldo Carvalho de Melo 	for (i = 0; i < evsel_list->nr_mmaps; i++) {
4420a27d7f9SArnaldo Carvalho de Melo 		if (evsel_list->mmap[i].base)
4430a27d7f9SArnaldo Carvalho de Melo 			mmap_read(&evsel_list->mmap[i]);
44498402807SFrederic Weisbecker 	}
44598402807SFrederic Weisbecker 
44698402807SFrederic Weisbecker 	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
44798402807SFrederic Weisbecker 		write_output(&finished_round_event, sizeof(finished_round_event));
44898402807SFrederic Weisbecker }
44998402807SFrederic Weisbecker 
450d4db3f16SArnaldo Carvalho de Melo static int __cmd_record(int argc, const char **argv)
45186470930SIngo Molnar {
45286470930SIngo Molnar 	struct stat st;
45386470930SIngo Molnar 	int flags;
4544dc0a04bSArnaldo Carvalho de Melo 	int err;
4558b412664SPeter Zijlstra 	unsigned long waking = 0;
456856e9660SPeter Zijlstra 	int child_ready_pipe[2], go_pipe[2];
45746be604bSZhang, Yanmin 	const bool forks = argc > 0;
458856e9660SPeter Zijlstra 	char buf;
45923346f21SArnaldo Carvalho de Melo 	struct machine *machine;
46086470930SIngo Molnar 
461*33e49ea7SAndi Kleen 	progname = argv[0];
462*33e49ea7SAndi Kleen 
46386470930SIngo Molnar 	page_size = sysconf(_SC_PAGE_SIZE);
46486470930SIngo Molnar 
465f5970550SPeter Zijlstra 	atexit(sig_atexit);
466f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
467f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
46818483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
469f5970550SPeter Zijlstra 
470d4db3f16SArnaldo Carvalho de Melo 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
471856e9660SPeter Zijlstra 		perror("failed to create pipes");
472856e9660SPeter Zijlstra 		exit(-1);
473856e9660SPeter Zijlstra 	}
474856e9660SPeter Zijlstra 
475d7065adbSFranck Bui-Huu 	if (!output_name) {
476d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
477d7065adbSFranck Bui-Huu 			pipe_output = 1;
478d7065adbSFranck Bui-Huu 		else
479d7065adbSFranck Bui-Huu 			output_name = "perf.data";
480d7065adbSFranck Bui-Huu 	}
481d7065adbSFranck Bui-Huu 	if (output_name) {
482529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
483529870e3STom Zanussi 			pipe_output = 1;
484529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
4857865e817SFrederic Weisbecker 			if (write_mode == WRITE_FORCE) {
486b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
487b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
488b38d3464SArnaldo Carvalho de Melo 					 output_name);
489b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
490b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
491b38d3464SArnaldo Carvalho de Melo 			}
4927865e817SFrederic Weisbecker 		} else if (write_mode == WRITE_APPEND) {
4937865e817SFrederic Weisbecker 			write_mode = WRITE_FORCE;
494266e0e21SPierre Habouzit 		}
495d7065adbSFranck Bui-Huu 	}
49686470930SIngo Molnar 
497f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
4987865e817SFrederic Weisbecker 	if (write_mode == WRITE_APPEND)
499f5970550SPeter Zijlstra 		file_new = 0;
50086470930SIngo Molnar 	else
50186470930SIngo Molnar 		flags |= O_TRUNC;
50286470930SIngo Molnar 
503529870e3STom Zanussi 	if (pipe_output)
504529870e3STom Zanussi 		output = STDOUT_FILENO;
505529870e3STom Zanussi 	else
50686470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
50786470930SIngo Molnar 	if (output < 0) {
50886470930SIngo Molnar 		perror("failed to create output file");
50986470930SIngo Molnar 		exit(-1);
51086470930SIngo Molnar 	}
51186470930SIngo Molnar 
5127865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
51321ef97f0SIan Munsie 				    write_mode == WRITE_FORCE, false, NULL);
51494c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
515a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
516a9a70bbcSArnaldo Carvalho de Melo 		return -1;
517a9a70bbcSArnaldo Carvalho de Melo 	}
518a9a70bbcSArnaldo Carvalho de Melo 
519baa2f6ceSArnaldo Carvalho de Melo 	if (!no_buildid)
520baa2f6ceSArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
521baa2f6ceSArnaldo Carvalho de Melo 
5224dc0a04bSArnaldo Carvalho de Melo 	if (!file_new) {
523a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
5244dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
52539d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
5264dc0a04bSArnaldo Carvalho de Melo 	}
5274dc0a04bSArnaldo Carvalho de Melo 
528361c99a6SArnaldo Carvalho de Melo 	if (have_tracepoints(&evsel_list->entries))
52994c744b6SArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
53003456a15SFrederic Weisbecker 
531800cd25cSFrederic Weisbecker 	/* 512 kiB: default amount of unprivileged mlocked memory */
532800cd25cSFrederic Weisbecker 	if (mmap_pages == UINT_MAX)
533800cd25cSFrederic Weisbecker 		mmap_pages = (512 * 1024) / page_size;
534800cd25cSFrederic Weisbecker 
535d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
53646be604bSZhang, Yanmin 		child_pid = fork();
5372fb750e8SBorislav Petkov 		if (child_pid < 0) {
538856e9660SPeter Zijlstra 			perror("failed to fork");
539856e9660SPeter Zijlstra 			exit(-1);
540856e9660SPeter Zijlstra 		}
5417c6a1c65SPeter Zijlstra 
54246be604bSZhang, Yanmin 		if (!child_pid) {
543529870e3STom Zanussi 			if (pipe_output)
544529870e3STom Zanussi 				dup2(2, 1);
545856e9660SPeter Zijlstra 			close(child_ready_pipe[0]);
546856e9660SPeter Zijlstra 			close(go_pipe[1]);
547856e9660SPeter Zijlstra 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
548856e9660SPeter Zijlstra 
549856e9660SPeter Zijlstra 			/*
550856e9660SPeter Zijlstra 			 * Do a dummy execvp to get the PLT entry resolved,
551856e9660SPeter Zijlstra 			 * so we avoid the resolver overhead on the real
552856e9660SPeter Zijlstra 			 * execvp call.
553856e9660SPeter Zijlstra 			 */
554856e9660SPeter Zijlstra 			execvp("", (char **)argv);
555856e9660SPeter Zijlstra 
556856e9660SPeter Zijlstra 			/*
557856e9660SPeter Zijlstra 			 * Tell the parent we're ready to go
558856e9660SPeter Zijlstra 			 */
559856e9660SPeter Zijlstra 			close(child_ready_pipe[1]);
560856e9660SPeter Zijlstra 
561856e9660SPeter Zijlstra 			/*
562856e9660SPeter Zijlstra 			 * Wait until the parent tells us to go.
563856e9660SPeter Zijlstra 			 */
564856e9660SPeter Zijlstra 			if (read(go_pipe[0], &buf, 1) == -1)
565856e9660SPeter Zijlstra 				perror("unable to read pipe");
566856e9660SPeter Zijlstra 
567856e9660SPeter Zijlstra 			execvp(argv[0], (char **)argv);
568856e9660SPeter Zijlstra 
569856e9660SPeter Zijlstra 			perror(argv[0]);
57018483b81SArnaldo Carvalho de Melo 			kill(getppid(), SIGUSR1);
571856e9660SPeter Zijlstra 			exit(-1);
572856e9660SPeter Zijlstra 		}
573856e9660SPeter Zijlstra 
574d6d901c2SZhang, Yanmin 		if (!system_wide && target_tid == -1 && target_pid == -1)
5757e2ed097SArnaldo Carvalho de Melo 			evsel_list->threads->map[0] = child_pid;
576d6d901c2SZhang, Yanmin 
577856e9660SPeter Zijlstra 		close(child_ready_pipe[1]);
578856e9660SPeter Zijlstra 		close(go_pipe[0]);
579856e9660SPeter Zijlstra 		/*
580856e9660SPeter Zijlstra 		 * wait for child to settle
581856e9660SPeter Zijlstra 		 */
582856e9660SPeter Zijlstra 		if (read(child_ready_pipe[0], &buf, 1) == -1) {
583856e9660SPeter Zijlstra 			perror("unable to read pipe");
584856e9660SPeter Zijlstra 			exit(-1);
585856e9660SPeter Zijlstra 		}
586856e9660SPeter Zijlstra 		close(child_ready_pipe[0]);
587856e9660SPeter Zijlstra 	}
588856e9660SPeter Zijlstra 
589dd7927f4SArnaldo Carvalho de Melo 	open_counters(evsel_list);
59086470930SIngo Molnar 
591712a4b60SArnaldo Carvalho de Melo 	/*
592712a4b60SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at atexit_header()
593712a4b60SArnaldo Carvalho de Melo 	 */
594712a4b60SArnaldo Carvalho de Melo 	atexit(atexit_header);
595712a4b60SArnaldo Carvalho de Melo 
596529870e3STom Zanussi 	if (pipe_output) {
597529870e3STom Zanussi 		err = perf_header__write_pipe(output);
598529870e3STom Zanussi 		if (err < 0)
599529870e3STom Zanussi 			return err;
600529870e3STom Zanussi 	} else if (file_new) {
601a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
602361c99a6SArnaldo Carvalho de Melo 						 output, false);
603d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
604d5eed904SArnaldo Carvalho de Melo 			return err;
605d5eed904SArnaldo Carvalho de Melo 	}
6067c6a1c65SPeter Zijlstra 
6076122e4e4SArnaldo Carvalho de Melo 	post_processing_offset = lseek(output, 0, SEEK_CUR);
6086122e4e4SArnaldo Carvalho de Melo 
6092c46dbb5STom Zanussi 	if (pipe_output) {
610a91e5431SArnaldo Carvalho de Melo 		err = perf_session__synthesize_attrs(session,
611a91e5431SArnaldo Carvalho de Melo 						     process_synthesized_event);
6122c46dbb5STom Zanussi 		if (err < 0) {
6132c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
6142c46dbb5STom Zanussi 			return err;
6152c46dbb5STom Zanussi 		}
616cd19a035STom Zanussi 
6178115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(process_synthesized_event,
618cd19a035STom Zanussi 							 session);
619cd19a035STom Zanussi 		if (err < 0) {
620cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
621cd19a035STom Zanussi 			return err;
622cd19a035STom Zanussi 		}
6239215545eSTom Zanussi 
624361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
62563e0c771STom Zanussi 			/*
62663e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
62763e0c771STom Zanussi 			 * there were no tracepoints so its not really
62863e0c771STom Zanussi 			 * an error, just that we don't need to
62963e0c771STom Zanussi 			 * synthesize anything.  We really have to
63063e0c771STom Zanussi 			 * return this more properly and also
63163e0c771STom Zanussi 			 * propagate errors that now are calling die()
63263e0c771STom Zanussi 			 */
6338115d60cSArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(output, evsel_list,
6349215545eSTom Zanussi 								  process_synthesized_event,
6359215545eSTom Zanussi 								  session);
63663e0c771STom Zanussi 			if (err <= 0) {
63763e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
63863e0c771STom Zanussi 				return err;
63963e0c771STom Zanussi 			}
6409215545eSTom Zanussi 			advance_output(err);
6412c46dbb5STom Zanussi 		}
64263e0c771STom Zanussi 	}
6432c46dbb5STom Zanussi 
64423346f21SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
64523346f21SArnaldo Carvalho de Melo 	if (!machine) {
646a1645ce1SZhang, Yanmin 		pr_err("Couldn't find native kernel information.\n");
647a1645ce1SZhang, Yanmin 		return -1;
648a1645ce1SZhang, Yanmin 	}
649a1645ce1SZhang, Yanmin 
6508115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
65123346f21SArnaldo Carvalho de Melo 						 session, machine, "_text");
65270162138SArnaldo Carvalho de Melo 	if (err < 0)
6538115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
65423346f21SArnaldo Carvalho de Melo 							 session, machine, "_stext");
655c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
656c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
657c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
658c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
65956b03f3cSArnaldo Carvalho de Melo 
6608115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
66123346f21SArnaldo Carvalho de Melo 					     session, machine);
662c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
663c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
664c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
665c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
666c1a3a4b9SArnaldo Carvalho de Melo 
667a1645ce1SZhang, Yanmin 	if (perf_guest)
6688115d60cSArnaldo Carvalho de Melo 		perf_session__process_machines(session,
6698115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
670b7cece76SArnaldo Carvalho de Melo 
671cf103a14SStephane Eranian 	if (!system_wide)
6727c940c18SArnaldo Carvalho de Melo 		perf_event__synthesize_thread_map(evsel_list->threads,
6738115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
674d8f66248SArnaldo Carvalho de Melo 						  session);
675234fbbf5SArnaldo Carvalho de Melo 	else
6768115d60cSArnaldo Carvalho de Melo 		perf_event__synthesize_threads(process_synthesized_event,
6778115d60cSArnaldo Carvalho de Melo 					       session);
6787c6a1c65SPeter Zijlstra 
67986470930SIngo Molnar 	if (realtime_prio) {
68086470930SIngo Molnar 		struct sched_param param;
68186470930SIngo Molnar 
68286470930SIngo Molnar 		param.sched_priority = realtime_prio;
68386470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6846beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
68586470930SIngo Molnar 			exit(-1);
68686470930SIngo Molnar 		}
68786470930SIngo Molnar 	}
68886470930SIngo Molnar 
689856e9660SPeter Zijlstra 	/*
690856e9660SPeter Zijlstra 	 * Let the child rip
691856e9660SPeter Zijlstra 	 */
692d4db3f16SArnaldo Carvalho de Melo 	if (forks)
693856e9660SPeter Zijlstra 		close(go_pipe[1]);
694856e9660SPeter Zijlstra 
695649c48a9SPeter Zijlstra 	for (;;) {
69686470930SIngo Molnar 		int hits = samples;
69786470930SIngo Molnar 
69898402807SFrederic Weisbecker 		mmap_read_all();
69986470930SIngo Molnar 
700649c48a9SPeter Zijlstra 		if (hits == samples) {
701649c48a9SPeter Zijlstra 			if (done)
702649c48a9SPeter Zijlstra 				break;
7035c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
7048b412664SPeter Zijlstra 			waking++;
7058b412664SPeter Zijlstra 		}
7068b412664SPeter Zijlstra 
7074152ab37SArnaldo Carvalho de Melo 		if (done)
7084152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
7098b412664SPeter Zijlstra 	}
7108b412664SPeter Zijlstra 
71118483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
712b44308f5SArnaldo Carvalho de Melo 		return 0;
713b44308f5SArnaldo Carvalho de Melo 
7148b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
71586470930SIngo Molnar 
71686470930SIngo Molnar 	/*
71786470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
71886470930SIngo Molnar 	 */
71986470930SIngo Molnar 	fprintf(stderr,
7209486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
72186470930SIngo Molnar 		(double)bytes_written / 1024.0 / 1024.0,
72286470930SIngo Molnar 		output_name,
72386470930SIngo Molnar 		bytes_written / 24);
72486470930SIngo Molnar 
72586470930SIngo Molnar 	return 0;
72639d17dacSArnaldo Carvalho de Melo 
72739d17dacSArnaldo Carvalho de Melo out_delete_session:
72839d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
72939d17dacSArnaldo Carvalho de Melo 	return err;
73086470930SIngo Molnar }
73186470930SIngo Molnar 
73286470930SIngo Molnar static const char * const record_usage[] = {
73386470930SIngo Molnar 	"perf record [<options>] [<command>]",
73486470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
73586470930SIngo Molnar 	NULL
73686470930SIngo Molnar };
73786470930SIngo Molnar 
7387865e817SFrederic Weisbecker static bool force, append_file;
7397865e817SFrederic Weisbecker 
740bca647aaSTom Zanussi const struct option record_options[] = {
741361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &evsel_list, "event",
74286470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
743f120f9d5SJiri Olsa 		     parse_events_option),
744361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
745c171b552SLi Zefan 		     "event filter", parse_filter),
74686470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
747d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
748d6d901c2SZhang, Yanmin 	OPT_INTEGER('t', "tid", &target_tid,
749d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
75086470930SIngo Molnar 	OPT_INTEGER('r', "realtime", &realtime_prio,
75186470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
752acac03faSKirill Smelkov 	OPT_BOOLEAN('D', "no-delay", &nodelay,
753acac03faSKirill Smelkov 		    "collect data without buffering"),
754daac07b2SFrederic Weisbecker 	OPT_BOOLEAN('R', "raw-samples", &raw_samples,
755daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
75686470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
75786470930SIngo Molnar 			    "system-wide collection from all CPUs"),
75886470930SIngo Molnar 	OPT_BOOLEAN('A', "append", &append_file,
75986470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
760c45c6ea2SStephane Eranian 	OPT_STRING('C', "cpu", &cpu_list, "cpu",
761c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
76286470930SIngo Molnar 	OPT_BOOLEAN('f', "force", &force,
7637865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
7643de29cabSStephane Eranian 	OPT_U64('c', "count", &user_interval, "event period to sample"),
76586470930SIngo Molnar 	OPT_STRING('o', "output", &output_name, "file",
76686470930SIngo Molnar 		    "output file name"),
7672e6cdf99SStephane Eranian 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
7682e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
7691967936dSArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
7701967936dSArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
77143bece79SLin Ming 	OPT_BOOLEAN(0, "group", &group,
77243bece79SLin Ming 		    "put the counters into a counter group"),
7733efa1cc9SIngo Molnar 	OPT_BOOLEAN('g', "call-graph", &call_graph,
7743efa1cc9SIngo Molnar 		    "do call-graph (stack chain/backtrace) recording"),
775c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
7763da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
777b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
778649c48a9SPeter Zijlstra 	OPT_BOOLEAN('s', "stat", &inherit_stat,
779649c48a9SPeter Zijlstra 		    "per thread counts"),
7804bba828dSAnton Blanchard 	OPT_BOOLEAN('d', "data", &sample_address,
7814bba828dSAnton Blanchard 		    "Sample addresses"),
7829c90a61cSArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
783649c48a9SPeter Zijlstra 	OPT_BOOLEAN('n', "no-samples", &no_samples,
784649c48a9SPeter Zijlstra 		    "don't sample"),
785baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
786a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
787baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
788baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
789023695d9SStephane Eranian 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
790023695d9SStephane Eranian 		     "monitor event in cgroup name only",
791023695d9SStephane Eranian 		     parse_cgroups),
79286470930SIngo Molnar 	OPT_END()
79386470930SIngo Molnar };
79486470930SIngo Molnar 
795f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used)
79686470930SIngo Molnar {
79769aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
79869aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
79986470930SIngo Molnar 
8007e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
801361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
802361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
803361c99a6SArnaldo Carvalho de Melo 
804bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
805a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
806d6d901c2SZhang, Yanmin 	if (!argc && target_pid == -1 && target_tid == -1 &&
807c45c6ea2SStephane Eranian 		!system_wide && !cpu_list)
808bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
80986470930SIngo Molnar 
8107865e817SFrederic Weisbecker 	if (force && append_file) {
8117865e817SFrederic Weisbecker 		fprintf(stderr, "Can't overwrite and append at the same time."
8127865e817SFrederic Weisbecker 				" You need to choose between -f and -A");
813bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
8147865e817SFrederic Weisbecker 	} else if (append_file) {
8157865e817SFrederic Weisbecker 		write_mode = WRITE_APPEND;
8167865e817SFrederic Weisbecker 	} else {
8177865e817SFrederic Weisbecker 		write_mode = WRITE_FORCE;
8187865e817SFrederic Weisbecker 	}
8197865e817SFrederic Weisbecker 
820023695d9SStephane Eranian 	if (nr_cgroups && !system_wide) {
821023695d9SStephane Eranian 		fprintf(stderr, "cgroup monitoring only available in"
822023695d9SStephane Eranian 			" system-wide mode\n");
823023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
824023695d9SStephane Eranian 	}
825023695d9SStephane Eranian 
826655000e7SArnaldo Carvalho de Melo 	symbol__init();
827baa2f6ceSArnaldo Carvalho de Melo 
828ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
829646aaea6SArnaldo Carvalho de Melo 		pr_warning(
830646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
831ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
832646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
833646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
834646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
835646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
836646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
837ec80fde7SArnaldo Carvalho de Melo 
838baa2f6ceSArnaldo Carvalho de Melo 	if (no_buildid_cache || no_buildid)
839a1ac1d3cSStephane Eranian 		disable_buildid_cache();
840655000e7SArnaldo Carvalho de Melo 
841361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
842361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
84369aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
84469aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
845bbd36e5eSPeter Zijlstra 	}
84686470930SIngo Molnar 
8475c98d466SArnaldo Carvalho de Melo 	if (target_pid != -1)
848d6d901c2SZhang, Yanmin 		target_tid = target_pid;
849d6d901c2SZhang, Yanmin 
8507e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(evsel_list, target_pid,
8517e2ed097SArnaldo Carvalho de Melo 				     target_tid, cpu_list) < 0)
852dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
85369aad6f1SArnaldo Carvalho de Melo 
854361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
8557e2ed097SArnaldo Carvalho de Melo 		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
8567e2ed097SArnaldo Carvalho de Melo 					 evsel_list->threads->nr) < 0)
85769aad6f1SArnaldo Carvalho de Melo 			goto out_free_fd;
858ad7f4e3fSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, event_name(pos)))
859ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
860d6d901c2SZhang, Yanmin 	}
8615c581041SArnaldo Carvalho de Melo 
8627e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
86339d17dacSArnaldo Carvalho de Melo 		goto out_free_fd;
864d6d901c2SZhang, Yanmin 
8653de29cabSStephane Eranian 	if (user_interval != ULLONG_MAX)
866f9212819SFrederic Weisbecker 		default_interval = user_interval;
867f9212819SFrederic Weisbecker 	if (user_freq != UINT_MAX)
868f9212819SFrederic Weisbecker 		freq = user_freq;
869f9212819SFrederic Weisbecker 
8707e4ff9e3SMike Galbraith 	/*
8717e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
8727e4ff9e3SMike Galbraith 	 */
8737e4ff9e3SMike Galbraith 	if (default_interval)
8747e4ff9e3SMike Galbraith 		freq = 0;
8757e4ff9e3SMike Galbraith 	else if (freq) {
8767e4ff9e3SMike Galbraith 		default_interval = freq;
8777e4ff9e3SMike Galbraith 	} else {
8787e4ff9e3SMike Galbraith 		fprintf(stderr, "frequency and count are zero, aborting\n");
87939d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
8805c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
8817e4ff9e3SMike Galbraith 	}
8827e4ff9e3SMike Galbraith 
88339d17dacSArnaldo Carvalho de Melo 	err = __cmd_record(argc, argv);
88439d17dacSArnaldo Carvalho de Melo out_free_fd:
8857e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
886d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
887d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
88839d17dacSArnaldo Carvalho de Melo 	return err;
88986470930SIngo Molnar }
890