xref: /openbmc/linux/tools/perf/builtin-record.c (revision 764e16a30a77a9c8346fbae6615e7c818ce9d00f)
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;
76f5970550SPeter Zijlstra 
779215545eSTom Zanussi static void advance_output(size_t size)
789215545eSTom Zanussi {
799215545eSTom Zanussi 	bytes_written += size;
809215545eSTom Zanussi }
819215545eSTom Zanussi 
82f5970550SPeter Zijlstra static void write_output(void *buf, size_t size)
83f5970550SPeter Zijlstra {
84f5970550SPeter Zijlstra 	while (size) {
85f5970550SPeter Zijlstra 		int ret = write(output, buf, size);
86f5970550SPeter Zijlstra 
87f5970550SPeter Zijlstra 		if (ret < 0)
88f5970550SPeter Zijlstra 			die("failed to write");
89f5970550SPeter Zijlstra 
90f5970550SPeter Zijlstra 		size -= ret;
91f5970550SPeter Zijlstra 		buf += ret;
92f5970550SPeter Zijlstra 
93f5970550SPeter Zijlstra 		bytes_written += ret;
94f5970550SPeter Zijlstra 	}
95f5970550SPeter Zijlstra }
96f5970550SPeter Zijlstra 
978115d60cSArnaldo Carvalho de Melo static int process_synthesized_event(union perf_event *event,
988d50e5b4SArnaldo Carvalho de Melo 				     struct perf_sample *sample __used,
99d8f66248SArnaldo Carvalho de Melo 				     struct perf_session *self __used)
100234fbbf5SArnaldo Carvalho de Melo {
1016122e4e4SArnaldo Carvalho de Melo 	write_output(event, event->header.size);
102234fbbf5SArnaldo Carvalho de Melo 	return 0;
103234fbbf5SArnaldo Carvalho de Melo }
104234fbbf5SArnaldo Carvalho de Melo 
105744bd8aaSArnaldo Carvalho de Melo static void mmap_read(struct perf_mmap *md)
10686470930SIngo Molnar {
107744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
10886470930SIngo Molnar 	unsigned int old = md->prev;
10986470930SIngo Molnar 	unsigned char *data = md->base + page_size;
11086470930SIngo Molnar 	unsigned long size;
11186470930SIngo Molnar 	void *buf;
11286470930SIngo Molnar 
113dc82009aSArnaldo Carvalho de Melo 	if (old == head)
114dc82009aSArnaldo Carvalho de Melo 		return;
11586470930SIngo Molnar 
11686470930SIngo Molnar 	samples++;
11786470930SIngo Molnar 
11886470930SIngo Molnar 	size = head - old;
11986470930SIngo Molnar 
12086470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
12186470930SIngo Molnar 		buf = &data[old & md->mask];
12286470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
12386470930SIngo Molnar 		old += size;
12486470930SIngo Molnar 
1256122e4e4SArnaldo Carvalho de Melo 		write_output(buf, size);
12686470930SIngo Molnar 	}
12786470930SIngo Molnar 
12886470930SIngo Molnar 	buf = &data[old & md->mask];
12986470930SIngo Molnar 	size = head - old;
13086470930SIngo Molnar 	old += size;
13186470930SIngo Molnar 
1326122e4e4SArnaldo Carvalho de Melo 	write_output(buf, size);
13386470930SIngo Molnar 
13486470930SIngo Molnar 	md->prev = old;
135115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
13686470930SIngo Molnar }
13786470930SIngo Molnar 
13886470930SIngo Molnar static volatile int done = 0;
139f7b7c26eSPeter Zijlstra static volatile int signr = -1;
14086470930SIngo Molnar 
14186470930SIngo Molnar static void sig_handler(int sig)
14286470930SIngo Molnar {
14386470930SIngo Molnar 	done = 1;
144f7b7c26eSPeter Zijlstra 	signr = sig;
145f7b7c26eSPeter Zijlstra }
146f7b7c26eSPeter Zijlstra 
147f7b7c26eSPeter Zijlstra static void sig_atexit(void)
148f7b7c26eSPeter Zijlstra {
1495ffc8881SIan Munsie 	if (child_pid > 0)
150933da83aSChris Wilson 		kill(child_pid, SIGTERM);
151933da83aSChris Wilson 
15218483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
153f7b7c26eSPeter Zijlstra 		return;
154f7b7c26eSPeter Zijlstra 
155f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
156f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
15786470930SIngo Molnar }
15886470930SIngo Molnar 
159dd7927f4SArnaldo Carvalho de Melo static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
160dd7927f4SArnaldo Carvalho de Melo {
161dd7927f4SArnaldo Carvalho de Melo 	struct perf_event_attr *attr = &evsel->attr;
162dd7927f4SArnaldo Carvalho de Melo 	int track = !evsel->idx; /* only the first counter needs these */
1637c6a1c65SPeter Zijlstra 
164*764e16a3SDavid Ahern 	attr->disabled		= 1;
1655d2cd909SArnaldo Carvalho de Melo 	attr->inherit		= !no_inherit;
1667c6a1c65SPeter Zijlstra 	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
1677c6a1c65SPeter Zijlstra 				  PERF_FORMAT_TOTAL_TIME_RUNNING |
1687c6a1c65SPeter Zijlstra 				  PERF_FORMAT_ID;
16986470930SIngo Molnar 
1703a9f131fSFrederic Weisbecker 	attr->sample_type	|= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1713efa1cc9SIngo Molnar 
172361c99a6SArnaldo Carvalho de Melo 	if (evlist->nr_entries > 1)
1738907fd60SEric B Munson 		attr->sample_type |= PERF_SAMPLE_ID;
1748907fd60SEric B Munson 
175f9212819SFrederic Weisbecker 	/*
176f9212819SFrederic Weisbecker 	 * We default some events to a 1 default interval. But keep
177f9212819SFrederic Weisbecker 	 * it a weak assumption overridable by the user.
178f9212819SFrederic Weisbecker 	 */
179f9212819SFrederic Weisbecker 	if (!attr->sample_period || (user_freq != UINT_MAX &&
1803de29cabSStephane Eranian 				     user_interval != ULLONG_MAX)) {
18186470930SIngo Molnar 		if (freq) {
182ea1900e5SPeter Zijlstra 			attr->sample_type	|= PERF_SAMPLE_PERIOD;
18386470930SIngo Molnar 			attr->freq		= 1;
18486470930SIngo Molnar 			attr->sample_freq	= freq;
185f9212819SFrederic Weisbecker 		} else {
186f9212819SFrederic Weisbecker 			attr->sample_period = default_interval;
187f9212819SFrederic Weisbecker 		}
18886470930SIngo Molnar 	}
1893efa1cc9SIngo Molnar 
190649c48a9SPeter Zijlstra 	if (no_samples)
191649c48a9SPeter Zijlstra 		attr->sample_freq = 0;
192649c48a9SPeter Zijlstra 
193649c48a9SPeter Zijlstra 	if (inherit_stat)
194649c48a9SPeter Zijlstra 		attr->inherit_stat = 1;
195649c48a9SPeter Zijlstra 
1963af9e859SEric B Munson 	if (sample_address) {
1974bba828dSAnton Blanchard 		attr->sample_type	|= PERF_SAMPLE_ADDR;
1983af9e859SEric B Munson 		attr->mmap_data = track;
1993af9e859SEric B Munson 	}
2004bba828dSAnton Blanchard 
2013efa1cc9SIngo Molnar 	if (call_graph)
2023efa1cc9SIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN;
2033efa1cc9SIngo Molnar 
204f60f3593SArun Sharma 	if (system_wide)
205f60f3593SArun Sharma 		attr->sample_type	|= PERF_SAMPLE_CPU;
206f60f3593SArun Sharma 
207a43d3f08SArnaldo Carvalho de Melo 	if (sample_id_all_avail &&
208a43d3f08SArnaldo Carvalho de Melo 	    (sample_time || system_wide || !no_inherit || cpu_list))
2099c90a61cSArnaldo Carvalho de Melo 		attr->sample_type	|= PERF_SAMPLE_TIME;
2109c90a61cSArnaldo Carvalho de Melo 
211cd6feeeaSIngo Molnar 	if (raw_samples) {
2126ddf259dSIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_TIME;
213daac07b2SFrederic Weisbecker 		attr->sample_type	|= PERF_SAMPLE_RAW;
214cd6feeeaSIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_CPU;
215cd6feeeaSIngo Molnar 	}
216f413cdb8SFrederic Weisbecker 
217acac03faSKirill Smelkov 	if (nodelay) {
218acac03faSKirill Smelkov 		attr->watermark = 0;
219acac03faSKirill Smelkov 		attr->wakeup_events = 1;
220acac03faSKirill Smelkov 	}
221acac03faSKirill Smelkov 
22286470930SIngo Molnar 	attr->mmap		= track;
22386470930SIngo Molnar 	attr->comm		= track;
224dd7927f4SArnaldo Carvalho de Melo 
2252e6cdf99SStephane Eranian 	if (target_pid == -1 && target_tid == -1 && !system_wide) {
2264502d77cSPeter Zijlstra 		attr->disabled = 1;
227bedbfdeaSEric B Munson 		attr->enable_on_exec = 1;
22846be604bSZhang, Yanmin 	}
229dd7927f4SArnaldo Carvalho de Melo }
230dd7927f4SArnaldo Carvalho de Melo 
231a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
232a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
233a91e5431SArnaldo Carvalho de Melo {
234a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
235a91e5431SArnaldo Carvalho de Melo 
236a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
237a91e5431SArnaldo Carvalho de Melo 		return false;
238a91e5431SArnaldo Carvalho de Melo 
239a91e5431SArnaldo Carvalho de Melo 	pair = list_entry(other->entries.next, struct perf_evsel, node);
240a91e5431SArnaldo Carvalho de Melo 
241a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
242a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
243a91e5431SArnaldo Carvalho de Melo 			return false;
244a91e5431SArnaldo Carvalho de Melo 		pair = list_entry(pair->node.next, struct perf_evsel, node);
245a91e5431SArnaldo Carvalho de Melo 	}
246a91e5431SArnaldo Carvalho de Melo 
247a91e5431SArnaldo Carvalho de Melo 	return true;
248a91e5431SArnaldo Carvalho de Melo }
249a91e5431SArnaldo Carvalho de Melo 
250dd7927f4SArnaldo Carvalho de Melo static void open_counters(struct perf_evlist *evlist)
251dd7927f4SArnaldo Carvalho de Melo {
252dd7927f4SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
253dd7927f4SArnaldo Carvalho de Melo 
2545d2cd909SArnaldo Carvalho de Melo 	if (evlist->cpus->map[0] < 0)
2555d2cd909SArnaldo Carvalho de Melo 		no_inherit = true;
2565d2cd909SArnaldo Carvalho de Melo 
257dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
258dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
259dd7927f4SArnaldo Carvalho de Melo 		/*
260dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
261dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
262dd7927f4SArnaldo Carvalho de Melo 		 *
263dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
264dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
265dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
266dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
267dd7927f4SArnaldo Carvalho de Melo 		 *
268dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
269dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
270dd7927f4SArnaldo Carvalho de Melo 		 */
271dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
272dd7927f4SArnaldo Carvalho de Melo 
273dd7927f4SArnaldo Carvalho de Melo 		config_attr(pos, evlist);
2749c90a61cSArnaldo Carvalho de Melo retry_sample_id:
2759c90a61cSArnaldo Carvalho de Melo 		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
2763da297a6SIngo Molnar try_again:
2775d2cd909SArnaldo Carvalho de Melo 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
27886470930SIngo Molnar 			int err = errno;
27986470930SIngo Molnar 
280c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
281c286c419SArnaldo Carvalho de Melo 				ui__warning_paranoid();
282c286c419SArnaldo Carvalho de Melo 				exit(EXIT_FAILURE);
283c286c419SArnaldo Carvalho de Melo 			} else if (err ==  ENODEV && cpu_list) {
284d6d901c2SZhang, Yanmin 				die("No such device - did you specify"
285d6d901c2SZhang, Yanmin 					" an out-of-range profile CPU?\n");
2869c90a61cSArnaldo Carvalho de Melo 			} else if (err == EINVAL && sample_id_all_avail) {
2879c90a61cSArnaldo Carvalho de Melo 				/*
2889c90a61cSArnaldo Carvalho de Melo 				 * Old kernel, no attr->sample_id_type_all field
2899c90a61cSArnaldo Carvalho de Melo 				 */
2909c90a61cSArnaldo Carvalho de Melo 				sample_id_all_avail = false;
291a43d3f08SArnaldo Carvalho de Melo 				if (!sample_time && !raw_samples && !time_needed)
292eac23d1cSIan Munsie 					attr->sample_type &= ~PERF_SAMPLE_TIME;
293eac23d1cSIan Munsie 
2949c90a61cSArnaldo Carvalho de Melo 				goto retry_sample_id;
295d6d901c2SZhang, Yanmin 			}
2963da297a6SIngo Molnar 
2973da297a6SIngo Molnar 			/*
2983da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
2993da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
3003da297a6SIngo Molnar 			 * is always available even if no PMU support:
3013da297a6SIngo Molnar 			 */
3023da297a6SIngo Molnar 			if (attr->type == PERF_TYPE_HARDWARE
303f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
3043da297a6SIngo Molnar 
3053da297a6SIngo Molnar 				if (verbose)
306ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
307ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
3083da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
309f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
3103da297a6SIngo Molnar 				goto try_again;
3113da297a6SIngo Molnar 			}
312ca6a4258SDavid Ahern 
313ca6a4258SDavid Ahern 			if (err == ENOENT) {
314ca6a4258SDavid Ahern 				ui__warning("The %s event is not supported.\n",
315ca6a4258SDavid Ahern 					    event_name(pos));
316ca6a4258SDavid Ahern 				exit(EXIT_FAILURE);
317ca6a4258SDavid Ahern 			}
318ca6a4258SDavid Ahern 
31930c806a0SIngo Molnar 			printf("\n");
320d9cf837eSCorey Ashford 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
321dd7927f4SArnaldo Carvalho de Melo 			      err, strerror(err));
322bfd45118SSimon Kaempflein 
323bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
324bfd45118SSimon Kaempflein 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
325d6d901c2SZhang, Yanmin 				die("No hardware sampling interrupt available."
326d6d901c2SZhang, Yanmin 				    " No APIC? If so then you can boot the kernel"
327d6d901c2SZhang, Yanmin 				    " with the \"lapic\" boot parameter to"
328d6d901c2SZhang, Yanmin 				    " force-enable it.\n");
329bfd45118SSimon Kaempflein #endif
330bfd45118SSimon Kaempflein 
331cdd6c482SIngo Molnar 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
3327c6a1c65SPeter Zijlstra 		}
3337c6a1c65SPeter Zijlstra 	}
3347c6a1c65SPeter Zijlstra 
3350a102479SFrederic Weisbecker 	if (perf_evlist__set_filters(evlist)) {
3360a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
3370a102479SFrederic Weisbecker 			strerror(errno));
3380a102479SFrederic Weisbecker 		exit(-1);
3390a102479SFrederic Weisbecker 	}
3400a102479SFrederic Weisbecker 
3417e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
3420a27d7f9SArnaldo Carvalho de Melo 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
3430a27d7f9SArnaldo Carvalho de Melo 
344a91e5431SArnaldo Carvalho de Melo 	if (file_new)
345a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
346a91e5431SArnaldo Carvalho de Melo 	else {
347a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
348a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
349a91e5431SArnaldo Carvalho de Melo 			exit(-1);
350dd7927f4SArnaldo Carvalho de Melo 		}
35186470930SIngo Molnar  	}
35286470930SIngo Molnar 
353a91e5431SArnaldo Carvalho de Melo 	perf_session__update_sample_type(session);
354a91e5431SArnaldo Carvalho de Melo }
355a91e5431SArnaldo Carvalho de Melo 
3566122e4e4SArnaldo Carvalho de Melo static int process_buildids(void)
3576122e4e4SArnaldo Carvalho de Melo {
3586122e4e4SArnaldo Carvalho de Melo 	u64 size = lseek(output, 0, SEEK_CUR);
3596122e4e4SArnaldo Carvalho de Melo 
3609f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3619f591fd7SArnaldo Carvalho de Melo 		return 0;
3629f591fd7SArnaldo Carvalho de Melo 
3636122e4e4SArnaldo Carvalho de Melo 	session->fd = output;
3646122e4e4SArnaldo Carvalho de Melo 	return __perf_session__process_events(session, post_processing_offset,
3656122e4e4SArnaldo Carvalho de Melo 					      size - post_processing_offset,
3666122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3676122e4e4SArnaldo Carvalho de Melo }
3686122e4e4SArnaldo Carvalho de Melo 
369f5970550SPeter Zijlstra static void atexit_header(void)
370f5970550SPeter Zijlstra {
371c7929e47STom Zanussi 	if (!pipe_output) {
37294c744b6SArnaldo Carvalho de Melo 		session->header.data_size += bytes_written;
373f5970550SPeter Zijlstra 
374baa2f6ceSArnaldo Carvalho de Melo 		if (!no_buildid)
3756122e4e4SArnaldo Carvalho de Melo 			process_buildids();
376a91e5431SArnaldo Carvalho de Melo 		perf_session__write_header(session, evsel_list, output, true);
37739d17dacSArnaldo Carvalho de Melo 		perf_session__delete(session);
378361c99a6SArnaldo Carvalho de Melo 		perf_evlist__delete(evsel_list);
379d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
380c7929e47STom Zanussi 	}
381f5970550SPeter Zijlstra }
382f5970550SPeter Zijlstra 
3838115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
384a1645ce1SZhang, Yanmin {
385a1645ce1SZhang, Yanmin 	int err;
38623346f21SArnaldo Carvalho de Melo 	struct perf_session *psession = data;
387a1645ce1SZhang, Yanmin 
38823346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
389a1645ce1SZhang, Yanmin 		return;
390a1645ce1SZhang, Yanmin 
391a1645ce1SZhang, Yanmin 	/*
392a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
393a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
394a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
395a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
396a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
397a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
398a1645ce1SZhang, Yanmin 	 */
3998115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
40023346f21SArnaldo Carvalho de Melo 					     psession, machine);
401a1645ce1SZhang, Yanmin 	if (err < 0)
402a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
40323346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
404a1645ce1SZhang, Yanmin 
405a1645ce1SZhang, Yanmin 	/*
406a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
407a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
408a1645ce1SZhang, Yanmin 	 */
4098115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
41023346f21SArnaldo Carvalho de Melo 						 psession, machine, "_text");
411a1645ce1SZhang, Yanmin 	if (err < 0)
4128115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
4138115d60cSArnaldo Carvalho de Melo 							 psession, machine,
4148115d60cSArnaldo Carvalho de Melo 							 "_stext");
415a1645ce1SZhang, Yanmin 	if (err < 0)
416a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41723346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
418a1645ce1SZhang, Yanmin }
419a1645ce1SZhang, Yanmin 
42098402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
42198402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
42298402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
42398402807SFrederic Weisbecker };
42498402807SFrederic Weisbecker 
42598402807SFrederic Weisbecker static void mmap_read_all(void)
42698402807SFrederic Weisbecker {
4270e2e63ddSPeter Zijlstra 	int i;
42898402807SFrederic Weisbecker 
429aece948fSArnaldo Carvalho de Melo 	for (i = 0; i < evsel_list->nr_mmaps; i++) {
4300a27d7f9SArnaldo Carvalho de Melo 		if (evsel_list->mmap[i].base)
4310a27d7f9SArnaldo Carvalho de Melo 			mmap_read(&evsel_list->mmap[i]);
43298402807SFrederic Weisbecker 	}
43398402807SFrederic Weisbecker 
43498402807SFrederic Weisbecker 	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
43598402807SFrederic Weisbecker 		write_output(&finished_round_event, sizeof(finished_round_event));
43698402807SFrederic Weisbecker }
43798402807SFrederic Weisbecker 
438d4db3f16SArnaldo Carvalho de Melo static int __cmd_record(int argc, const char **argv)
43986470930SIngo Molnar {
44086470930SIngo Molnar 	struct stat st;
44186470930SIngo Molnar 	int flags;
4424dc0a04bSArnaldo Carvalho de Melo 	int err;
4438b412664SPeter Zijlstra 	unsigned long waking = 0;
444856e9660SPeter Zijlstra 	int child_ready_pipe[2], go_pipe[2];
44546be604bSZhang, Yanmin 	const bool forks = argc > 0;
446856e9660SPeter Zijlstra 	char buf;
44723346f21SArnaldo Carvalho de Melo 	struct machine *machine;
44886470930SIngo Molnar 
44986470930SIngo Molnar 	page_size = sysconf(_SC_PAGE_SIZE);
45086470930SIngo Molnar 
451f5970550SPeter Zijlstra 	atexit(sig_atexit);
452f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
453f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
45418483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
455f5970550SPeter Zijlstra 
456d4db3f16SArnaldo Carvalho de Melo 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
457856e9660SPeter Zijlstra 		perror("failed to create pipes");
458856e9660SPeter Zijlstra 		exit(-1);
459856e9660SPeter Zijlstra 	}
460856e9660SPeter Zijlstra 
461d7065adbSFranck Bui-Huu 	if (!output_name) {
462d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
463d7065adbSFranck Bui-Huu 			pipe_output = 1;
464d7065adbSFranck Bui-Huu 		else
465d7065adbSFranck Bui-Huu 			output_name = "perf.data";
466d7065adbSFranck Bui-Huu 	}
467d7065adbSFranck Bui-Huu 	if (output_name) {
468529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
469529870e3STom Zanussi 			pipe_output = 1;
470529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
4717865e817SFrederic Weisbecker 			if (write_mode == WRITE_FORCE) {
472b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
473b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
474b38d3464SArnaldo Carvalho de Melo 					 output_name);
475b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
476b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
477b38d3464SArnaldo Carvalho de Melo 			}
4787865e817SFrederic Weisbecker 		} else if (write_mode == WRITE_APPEND) {
4797865e817SFrederic Weisbecker 			write_mode = WRITE_FORCE;
480266e0e21SPierre Habouzit 		}
481d7065adbSFranck Bui-Huu 	}
48286470930SIngo Molnar 
483f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
4847865e817SFrederic Weisbecker 	if (write_mode == WRITE_APPEND)
485f5970550SPeter Zijlstra 		file_new = 0;
48686470930SIngo Molnar 	else
48786470930SIngo Molnar 		flags |= O_TRUNC;
48886470930SIngo Molnar 
489529870e3STom Zanussi 	if (pipe_output)
490529870e3STom Zanussi 		output = STDOUT_FILENO;
491529870e3STom Zanussi 	else
49286470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
49386470930SIngo Molnar 	if (output < 0) {
49486470930SIngo Molnar 		perror("failed to create output file");
49586470930SIngo Molnar 		exit(-1);
49686470930SIngo Molnar 	}
49786470930SIngo Molnar 
4987865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
49921ef97f0SIan Munsie 				    write_mode == WRITE_FORCE, false, NULL);
50094c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
501a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
502a9a70bbcSArnaldo Carvalho de Melo 		return -1;
503a9a70bbcSArnaldo Carvalho de Melo 	}
504a9a70bbcSArnaldo Carvalho de Melo 
505baa2f6ceSArnaldo Carvalho de Melo 	if (!no_buildid)
506baa2f6ceSArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
507baa2f6ceSArnaldo Carvalho de Melo 
5084dc0a04bSArnaldo Carvalho de Melo 	if (!file_new) {
509a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
5104dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
51139d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
5124dc0a04bSArnaldo Carvalho de Melo 	}
5134dc0a04bSArnaldo Carvalho de Melo 
514361c99a6SArnaldo Carvalho de Melo 	if (have_tracepoints(&evsel_list->entries))
51594c744b6SArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
51603456a15SFrederic Weisbecker 
517800cd25cSFrederic Weisbecker 	/* 512 kiB: default amount of unprivileged mlocked memory */
518800cd25cSFrederic Weisbecker 	if (mmap_pages == UINT_MAX)
519800cd25cSFrederic Weisbecker 		mmap_pages = (512 * 1024) / page_size;
520800cd25cSFrederic Weisbecker 
521d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
52246be604bSZhang, Yanmin 		child_pid = fork();
5232fb750e8SBorislav Petkov 		if (child_pid < 0) {
524856e9660SPeter Zijlstra 			perror("failed to fork");
525856e9660SPeter Zijlstra 			exit(-1);
526856e9660SPeter Zijlstra 		}
5277c6a1c65SPeter Zijlstra 
52846be604bSZhang, Yanmin 		if (!child_pid) {
529529870e3STom Zanussi 			if (pipe_output)
530529870e3STom Zanussi 				dup2(2, 1);
531856e9660SPeter Zijlstra 			close(child_ready_pipe[0]);
532856e9660SPeter Zijlstra 			close(go_pipe[1]);
533856e9660SPeter Zijlstra 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
534856e9660SPeter Zijlstra 
535856e9660SPeter Zijlstra 			/*
536856e9660SPeter Zijlstra 			 * Do a dummy execvp to get the PLT entry resolved,
537856e9660SPeter Zijlstra 			 * so we avoid the resolver overhead on the real
538856e9660SPeter Zijlstra 			 * execvp call.
539856e9660SPeter Zijlstra 			 */
540856e9660SPeter Zijlstra 			execvp("", (char **)argv);
541856e9660SPeter Zijlstra 
542856e9660SPeter Zijlstra 			/*
543856e9660SPeter Zijlstra 			 * Tell the parent we're ready to go
544856e9660SPeter Zijlstra 			 */
545856e9660SPeter Zijlstra 			close(child_ready_pipe[1]);
546856e9660SPeter Zijlstra 
547856e9660SPeter Zijlstra 			/*
548856e9660SPeter Zijlstra 			 * Wait until the parent tells us to go.
549856e9660SPeter Zijlstra 			 */
550856e9660SPeter Zijlstra 			if (read(go_pipe[0], &buf, 1) == -1)
551856e9660SPeter Zijlstra 				perror("unable to read pipe");
552856e9660SPeter Zijlstra 
553856e9660SPeter Zijlstra 			execvp(argv[0], (char **)argv);
554856e9660SPeter Zijlstra 
555856e9660SPeter Zijlstra 			perror(argv[0]);
55618483b81SArnaldo Carvalho de Melo 			kill(getppid(), SIGUSR1);
557856e9660SPeter Zijlstra 			exit(-1);
558856e9660SPeter Zijlstra 		}
559856e9660SPeter Zijlstra 
560d6d901c2SZhang, Yanmin 		if (!system_wide && target_tid == -1 && target_pid == -1)
5617e2ed097SArnaldo Carvalho de Melo 			evsel_list->threads->map[0] = child_pid;
562d6d901c2SZhang, Yanmin 
563856e9660SPeter Zijlstra 		close(child_ready_pipe[1]);
564856e9660SPeter Zijlstra 		close(go_pipe[0]);
565856e9660SPeter Zijlstra 		/*
566856e9660SPeter Zijlstra 		 * wait for child to settle
567856e9660SPeter Zijlstra 		 */
568856e9660SPeter Zijlstra 		if (read(child_ready_pipe[0], &buf, 1) == -1) {
569856e9660SPeter Zijlstra 			perror("unable to read pipe");
570856e9660SPeter Zijlstra 			exit(-1);
571856e9660SPeter Zijlstra 		}
572856e9660SPeter Zijlstra 		close(child_ready_pipe[0]);
573856e9660SPeter Zijlstra 	}
574856e9660SPeter Zijlstra 
575dd7927f4SArnaldo Carvalho de Melo 	open_counters(evsel_list);
57686470930SIngo Molnar 
577712a4b60SArnaldo Carvalho de Melo 	/*
578712a4b60SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at atexit_header()
579712a4b60SArnaldo Carvalho de Melo 	 */
580712a4b60SArnaldo Carvalho de Melo 	atexit(atexit_header);
581712a4b60SArnaldo Carvalho de Melo 
582529870e3STom Zanussi 	if (pipe_output) {
583529870e3STom Zanussi 		err = perf_header__write_pipe(output);
584529870e3STom Zanussi 		if (err < 0)
585529870e3STom Zanussi 			return err;
586529870e3STom Zanussi 	} else if (file_new) {
587a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
588361c99a6SArnaldo Carvalho de Melo 						 output, false);
589d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
590d5eed904SArnaldo Carvalho de Melo 			return err;
591d5eed904SArnaldo Carvalho de Melo 	}
5927c6a1c65SPeter Zijlstra 
5936122e4e4SArnaldo Carvalho de Melo 	post_processing_offset = lseek(output, 0, SEEK_CUR);
5946122e4e4SArnaldo Carvalho de Melo 
5952c46dbb5STom Zanussi 	if (pipe_output) {
596a91e5431SArnaldo Carvalho de Melo 		err = perf_session__synthesize_attrs(session,
597a91e5431SArnaldo Carvalho de Melo 						     process_synthesized_event);
5982c46dbb5STom Zanussi 		if (err < 0) {
5992c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
6002c46dbb5STom Zanussi 			return err;
6012c46dbb5STom Zanussi 		}
602cd19a035STom Zanussi 
6038115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(process_synthesized_event,
604cd19a035STom Zanussi 							 session);
605cd19a035STom Zanussi 		if (err < 0) {
606cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
607cd19a035STom Zanussi 			return err;
608cd19a035STom Zanussi 		}
6099215545eSTom Zanussi 
610361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
61163e0c771STom Zanussi 			/*
61263e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
61363e0c771STom Zanussi 			 * there were no tracepoints so its not really
61463e0c771STom Zanussi 			 * an error, just that we don't need to
61563e0c771STom Zanussi 			 * synthesize anything.  We really have to
61663e0c771STom Zanussi 			 * return this more properly and also
61763e0c771STom Zanussi 			 * propagate errors that now are calling die()
61863e0c771STom Zanussi 			 */
6198115d60cSArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(output, evsel_list,
6209215545eSTom Zanussi 								  process_synthesized_event,
6219215545eSTom Zanussi 								  session);
62263e0c771STom Zanussi 			if (err <= 0) {
62363e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
62463e0c771STom Zanussi 				return err;
62563e0c771STom Zanussi 			}
6269215545eSTom Zanussi 			advance_output(err);
6272c46dbb5STom Zanussi 		}
62863e0c771STom Zanussi 	}
6292c46dbb5STom Zanussi 
63023346f21SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
63123346f21SArnaldo Carvalho de Melo 	if (!machine) {
632a1645ce1SZhang, Yanmin 		pr_err("Couldn't find native kernel information.\n");
633a1645ce1SZhang, Yanmin 		return -1;
634a1645ce1SZhang, Yanmin 	}
635a1645ce1SZhang, Yanmin 
6368115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
63723346f21SArnaldo Carvalho de Melo 						 session, machine, "_text");
63870162138SArnaldo Carvalho de Melo 	if (err < 0)
6398115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
64023346f21SArnaldo Carvalho de Melo 							 session, machine, "_stext");
641c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
642c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
643c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
644c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
64556b03f3cSArnaldo Carvalho de Melo 
6468115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
64723346f21SArnaldo Carvalho de Melo 					     session, machine);
648c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
649c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
650c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
651c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
652c1a3a4b9SArnaldo Carvalho de Melo 
653a1645ce1SZhang, Yanmin 	if (perf_guest)
6548115d60cSArnaldo Carvalho de Melo 		perf_session__process_machines(session,
6558115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
656b7cece76SArnaldo Carvalho de Melo 
657cf103a14SStephane Eranian 	if (!system_wide)
6587c940c18SArnaldo Carvalho de Melo 		perf_event__synthesize_thread_map(evsel_list->threads,
6598115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
660d8f66248SArnaldo Carvalho de Melo 						  session);
661234fbbf5SArnaldo Carvalho de Melo 	else
6628115d60cSArnaldo Carvalho de Melo 		perf_event__synthesize_threads(process_synthesized_event,
6638115d60cSArnaldo Carvalho de Melo 					       session);
6647c6a1c65SPeter Zijlstra 
66586470930SIngo Molnar 	if (realtime_prio) {
66686470930SIngo Molnar 		struct sched_param param;
66786470930SIngo Molnar 
66886470930SIngo Molnar 		param.sched_priority = realtime_prio;
66986470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6706beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
67186470930SIngo Molnar 			exit(-1);
67286470930SIngo Molnar 		}
67386470930SIngo Molnar 	}
67486470930SIngo Molnar 
675*764e16a3SDavid Ahern 	perf_evlist__enable(evsel_list);
676*764e16a3SDavid Ahern 
677856e9660SPeter Zijlstra 	/*
678856e9660SPeter Zijlstra 	 * Let the child rip
679856e9660SPeter Zijlstra 	 */
680d4db3f16SArnaldo Carvalho de Melo 	if (forks)
681856e9660SPeter Zijlstra 		close(go_pipe[1]);
682856e9660SPeter Zijlstra 
683649c48a9SPeter Zijlstra 	for (;;) {
68486470930SIngo Molnar 		int hits = samples;
68586470930SIngo Molnar 
68698402807SFrederic Weisbecker 		mmap_read_all();
68786470930SIngo Molnar 
688649c48a9SPeter Zijlstra 		if (hits == samples) {
689649c48a9SPeter Zijlstra 			if (done)
690649c48a9SPeter Zijlstra 				break;
6915c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6928b412664SPeter Zijlstra 			waking++;
6938b412664SPeter Zijlstra 		}
6948b412664SPeter Zijlstra 
6954152ab37SArnaldo Carvalho de Melo 		if (done)
6964152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
6978b412664SPeter Zijlstra 	}
6988b412664SPeter Zijlstra 
69918483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
700b44308f5SArnaldo Carvalho de Melo 		return 0;
701b44308f5SArnaldo Carvalho de Melo 
7028b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
70386470930SIngo Molnar 
70486470930SIngo Molnar 	/*
70586470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
70686470930SIngo Molnar 	 */
70786470930SIngo Molnar 	fprintf(stderr,
7089486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
70986470930SIngo Molnar 		(double)bytes_written / 1024.0 / 1024.0,
71086470930SIngo Molnar 		output_name,
71186470930SIngo Molnar 		bytes_written / 24);
71286470930SIngo Molnar 
71386470930SIngo Molnar 	return 0;
71439d17dacSArnaldo Carvalho de Melo 
71539d17dacSArnaldo Carvalho de Melo out_delete_session:
71639d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
71739d17dacSArnaldo Carvalho de Melo 	return err;
71886470930SIngo Molnar }
71986470930SIngo Molnar 
72086470930SIngo Molnar static const char * const record_usage[] = {
72186470930SIngo Molnar 	"perf record [<options>] [<command>]",
72286470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
72386470930SIngo Molnar 	NULL
72486470930SIngo Molnar };
72586470930SIngo Molnar 
7267865e817SFrederic Weisbecker static bool force, append_file;
7277865e817SFrederic Weisbecker 
728bca647aaSTom Zanussi const struct option record_options[] = {
729361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &evsel_list, "event",
73086470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
731f120f9d5SJiri Olsa 		     parse_events_option),
732361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
733c171b552SLi Zefan 		     "event filter", parse_filter),
73486470930SIngo Molnar 	OPT_INTEGER('p', "pid", &target_pid,
735d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
736d6d901c2SZhang, Yanmin 	OPT_INTEGER('t', "tid", &target_tid,
737d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
73886470930SIngo Molnar 	OPT_INTEGER('r', "realtime", &realtime_prio,
73986470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
740acac03faSKirill Smelkov 	OPT_BOOLEAN('D', "no-delay", &nodelay,
741acac03faSKirill Smelkov 		    "collect data without buffering"),
742daac07b2SFrederic Weisbecker 	OPT_BOOLEAN('R', "raw-samples", &raw_samples,
743daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
74486470930SIngo Molnar 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
74586470930SIngo Molnar 			    "system-wide collection from all CPUs"),
74686470930SIngo Molnar 	OPT_BOOLEAN('A', "append", &append_file,
74786470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
748c45c6ea2SStephane Eranian 	OPT_STRING('C', "cpu", &cpu_list, "cpu",
749c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
75086470930SIngo Molnar 	OPT_BOOLEAN('f', "force", &force,
7517865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
7523de29cabSStephane Eranian 	OPT_U64('c', "count", &user_interval, "event period to sample"),
75386470930SIngo Molnar 	OPT_STRING('o', "output", &output_name, "file",
75486470930SIngo Molnar 		    "output file name"),
7552e6cdf99SStephane Eranian 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
7562e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
7571967936dSArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
7581967936dSArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
75943bece79SLin Ming 	OPT_BOOLEAN(0, "group", &group,
76043bece79SLin Ming 		    "put the counters into a counter group"),
7613efa1cc9SIngo Molnar 	OPT_BOOLEAN('g', "call-graph", &call_graph,
7623efa1cc9SIngo Molnar 		    "do call-graph (stack chain/backtrace) recording"),
763c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
7643da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
765b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
766649c48a9SPeter Zijlstra 	OPT_BOOLEAN('s', "stat", &inherit_stat,
767649c48a9SPeter Zijlstra 		    "per thread counts"),
7684bba828dSAnton Blanchard 	OPT_BOOLEAN('d', "data", &sample_address,
7694bba828dSAnton Blanchard 		    "Sample addresses"),
7709c90a61cSArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
771649c48a9SPeter Zijlstra 	OPT_BOOLEAN('n', "no-samples", &no_samples,
772649c48a9SPeter Zijlstra 		    "don't sample"),
773baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
774a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
775baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
776baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
777023695d9SStephane Eranian 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
778023695d9SStephane Eranian 		     "monitor event in cgroup name only",
779023695d9SStephane Eranian 		     parse_cgroups),
78086470930SIngo Molnar 	OPT_END()
78186470930SIngo Molnar };
78286470930SIngo Molnar 
783f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used)
78486470930SIngo Molnar {
78569aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
78669aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
78786470930SIngo Molnar 
7887e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
789361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
790361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
791361c99a6SArnaldo Carvalho de Melo 
792bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
793a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
794d6d901c2SZhang, Yanmin 	if (!argc && target_pid == -1 && target_tid == -1 &&
795c45c6ea2SStephane Eranian 		!system_wide && !cpu_list)
796bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
79786470930SIngo Molnar 
7987865e817SFrederic Weisbecker 	if (force && append_file) {
7997865e817SFrederic Weisbecker 		fprintf(stderr, "Can't overwrite and append at the same time."
8007865e817SFrederic Weisbecker 				" You need to choose between -f and -A");
801bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
8027865e817SFrederic Weisbecker 	} else if (append_file) {
8037865e817SFrederic Weisbecker 		write_mode = WRITE_APPEND;
8047865e817SFrederic Weisbecker 	} else {
8057865e817SFrederic Weisbecker 		write_mode = WRITE_FORCE;
8067865e817SFrederic Weisbecker 	}
8077865e817SFrederic Weisbecker 
808023695d9SStephane Eranian 	if (nr_cgroups && !system_wide) {
809023695d9SStephane Eranian 		fprintf(stderr, "cgroup monitoring only available in"
810023695d9SStephane Eranian 			" system-wide mode\n");
811023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
812023695d9SStephane Eranian 	}
813023695d9SStephane Eranian 
814655000e7SArnaldo Carvalho de Melo 	symbol__init();
815baa2f6ceSArnaldo Carvalho de Melo 
816ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
817646aaea6SArnaldo Carvalho de Melo 		pr_warning(
818646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
819ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
820646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
821646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
822646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
823646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
824646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
825ec80fde7SArnaldo Carvalho de Melo 
826baa2f6ceSArnaldo Carvalho de Melo 	if (no_buildid_cache || no_buildid)
827a1ac1d3cSStephane Eranian 		disable_buildid_cache();
828655000e7SArnaldo Carvalho de Melo 
829361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
830361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
83169aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
83269aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
833bbd36e5eSPeter Zijlstra 	}
83486470930SIngo Molnar 
8355c98d466SArnaldo Carvalho de Melo 	if (target_pid != -1)
836d6d901c2SZhang, Yanmin 		target_tid = target_pid;
837d6d901c2SZhang, Yanmin 
8387e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(evsel_list, target_pid,
8397e2ed097SArnaldo Carvalho de Melo 				     target_tid, cpu_list) < 0)
840dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
84169aad6f1SArnaldo Carvalho de Melo 
842361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
8437e2ed097SArnaldo Carvalho de Melo 		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
8447e2ed097SArnaldo Carvalho de Melo 					 evsel_list->threads->nr) < 0)
84569aad6f1SArnaldo Carvalho de Melo 			goto out_free_fd;
846ad7f4e3fSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, event_name(pos)))
847ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
848d6d901c2SZhang, Yanmin 	}
8495c581041SArnaldo Carvalho de Melo 
8507e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
85139d17dacSArnaldo Carvalho de Melo 		goto out_free_fd;
852d6d901c2SZhang, Yanmin 
8533de29cabSStephane Eranian 	if (user_interval != ULLONG_MAX)
854f9212819SFrederic Weisbecker 		default_interval = user_interval;
855f9212819SFrederic Weisbecker 	if (user_freq != UINT_MAX)
856f9212819SFrederic Weisbecker 		freq = user_freq;
857f9212819SFrederic Weisbecker 
8587e4ff9e3SMike Galbraith 	/*
8597e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
8607e4ff9e3SMike Galbraith 	 */
8617e4ff9e3SMike Galbraith 	if (default_interval)
8627e4ff9e3SMike Galbraith 		freq = 0;
8637e4ff9e3SMike Galbraith 	else if (freq) {
8647e4ff9e3SMike Galbraith 		default_interval = freq;
8657e4ff9e3SMike Galbraith 	} else {
8667e4ff9e3SMike Galbraith 		fprintf(stderr, "frequency and count are zero, aborting\n");
86739d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
8685c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
8697e4ff9e3SMike Galbraith 	}
8707e4ff9e3SMike Galbraith 
87139d17dacSArnaldo Carvalho de Melo 	err = __cmd_record(argc, argv);
87239d17dacSArnaldo Carvalho de Melo out_free_fd:
8737e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
874d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
875d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
87639d17dacSArnaldo Carvalho de Melo 	return err;
87786470930SIngo Molnar }
878