xref: /openbmc/linux/tools/perf/builtin-record.c (revision f120f9d51be3a7db8991e7b78dc08bab5f8ab8f3)
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 
3369aad6f1SArnaldo Carvalho de Melo #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
3469aad6f1SArnaldo Carvalho de Melo 
357865e817SFrederic Weisbecker enum write_mode_t {
367865e817SFrederic Weisbecker 	WRITE_FORCE,
377865e817SFrederic Weisbecker 	WRITE_APPEND
387865e817SFrederic Weisbecker };
397865e817SFrederic Weisbecker 
403de29cabSStephane Eranian static u64			user_interval			= ULLONG_MAX;
413de29cabSStephane Eranian static u64			default_interval		=      0;
4286470930SIngo Molnar 
4386470930SIngo Molnar static unsigned int		page_size;
44800cd25cSFrederic Weisbecker static unsigned int		mmap_pages			= UINT_MAX;
45f9212819SFrederic Weisbecker static unsigned int		user_freq 			= UINT_MAX;
4642e59d7dSIngo Molnar static int			freq				=   1000;
4786470930SIngo Molnar static int			output;
48529870e3STom Zanussi static int			pipe_output			=      0;
49d7065adbSFranck Bui-Huu static const char		*output_name			= NULL;
5086470930SIngo Molnar static int			group				=      0;
511967936dSArnaldo Carvalho de Melo static int			realtime_prio			=      0;
52acac03faSKirill Smelkov static bool			nodelay				=  false;
53c0555642SIan Munsie static bool			raw_samples			=  false;
549c90a61cSArnaldo Carvalho de Melo static bool			sample_id_all_avail		=   true;
55c0555642SIan Munsie static bool			system_wide			=  false;
5686470930SIngo Molnar static pid_t			target_pid			=     -1;
57d6d901c2SZhang, Yanmin static pid_t			target_tid			=     -1;
58933da83aSChris Wilson static pid_t			child_pid			=     -1;
592e6cdf99SStephane Eranian static bool			no_inherit			=  false;
607865e817SFrederic Weisbecker static enum write_mode_t	write_mode			= WRITE_FORCE;
61c0555642SIan Munsie static bool			call_graph			=  false;
62c0555642SIan Munsie static bool			inherit_stat			=  false;
63c0555642SIan Munsie static bool			no_samples			=  false;
64c0555642SIan Munsie static bool			sample_address			=  false;
659c90a61cSArnaldo Carvalho de Melo static bool			sample_time			=  false;
66a1ac1d3cSStephane Eranian static bool			no_buildid			=  false;
67baa2f6ceSArnaldo Carvalho de Melo static bool			no_buildid_cache		=  false;
68361c99a6SArnaldo Carvalho de Melo static struct perf_evlist	*evsel_list;
6986470930SIngo Molnar 
7042e59d7dSIngo Molnar static long			samples				=      0;
7142e59d7dSIngo Molnar static u64			bytes_written			=      0;
7286470930SIngo Molnar 
73f5970550SPeter Zijlstra static int			file_new			=      1;
746122e4e4SArnaldo Carvalho de Melo static off_t			post_processing_offset;
757c6a1c65SPeter Zijlstra 
7694c744b6SArnaldo Carvalho de Melo static struct perf_session	*session;
77c45c6ea2SStephane Eranian static const char		*cpu_list;
78f5970550SPeter Zijlstra 
799215545eSTom Zanussi static void advance_output(size_t size)
809215545eSTom Zanussi {
819215545eSTom Zanussi 	bytes_written += size;
829215545eSTom Zanussi }
839215545eSTom Zanussi 
84f5970550SPeter Zijlstra static void write_output(void *buf, size_t size)
85f5970550SPeter Zijlstra {
86f5970550SPeter Zijlstra 	while (size) {
87f5970550SPeter Zijlstra 		int ret = write(output, buf, size);
88f5970550SPeter Zijlstra 
89f5970550SPeter Zijlstra 		if (ret < 0)
90f5970550SPeter Zijlstra 			die("failed to write");
91f5970550SPeter Zijlstra 
92f5970550SPeter Zijlstra 		size -= ret;
93f5970550SPeter Zijlstra 		buf += ret;
94f5970550SPeter Zijlstra 
95f5970550SPeter Zijlstra 		bytes_written += ret;
96f5970550SPeter Zijlstra 	}
97f5970550SPeter Zijlstra }
98f5970550SPeter Zijlstra 
998115d60cSArnaldo Carvalho de Melo static int process_synthesized_event(union perf_event *event,
1008d50e5b4SArnaldo Carvalho de Melo 				     struct perf_sample *sample __used,
101d8f66248SArnaldo Carvalho de Melo 				     struct perf_session *self __used)
102234fbbf5SArnaldo Carvalho de Melo {
1036122e4e4SArnaldo Carvalho de Melo 	write_output(event, event->header.size);
104234fbbf5SArnaldo Carvalho de Melo 	return 0;
105234fbbf5SArnaldo Carvalho de Melo }
106234fbbf5SArnaldo Carvalho de Melo 
107744bd8aaSArnaldo Carvalho de Melo static void mmap_read(struct perf_mmap *md)
10886470930SIngo Molnar {
109744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
11086470930SIngo Molnar 	unsigned int old = md->prev;
11186470930SIngo Molnar 	unsigned char *data = md->base + page_size;
11286470930SIngo Molnar 	unsigned long size;
11386470930SIngo Molnar 	void *buf;
11486470930SIngo Molnar 
115dc82009aSArnaldo Carvalho de Melo 	if (old == head)
116dc82009aSArnaldo Carvalho de Melo 		return;
11786470930SIngo Molnar 
11886470930SIngo Molnar 	samples++;
11986470930SIngo Molnar 
12086470930SIngo Molnar 	size = head - old;
12186470930SIngo Molnar 
12286470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
12386470930SIngo Molnar 		buf = &data[old & md->mask];
12486470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
12586470930SIngo Molnar 		old += size;
12686470930SIngo Molnar 
1276122e4e4SArnaldo Carvalho de Melo 		write_output(buf, size);
12886470930SIngo Molnar 	}
12986470930SIngo Molnar 
13086470930SIngo Molnar 	buf = &data[old & md->mask];
13186470930SIngo Molnar 	size = head - old;
13286470930SIngo Molnar 	old += size;
13386470930SIngo Molnar 
1346122e4e4SArnaldo Carvalho de Melo 	write_output(buf, size);
13586470930SIngo Molnar 
13686470930SIngo Molnar 	md->prev = old;
137115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
13886470930SIngo Molnar }
13986470930SIngo Molnar 
14086470930SIngo Molnar static volatile int done = 0;
141f7b7c26eSPeter Zijlstra static volatile int signr = -1;
14286470930SIngo Molnar 
14386470930SIngo Molnar static void sig_handler(int sig)
14486470930SIngo Molnar {
14586470930SIngo Molnar 	done = 1;
146f7b7c26eSPeter Zijlstra 	signr = sig;
147f7b7c26eSPeter Zijlstra }
148f7b7c26eSPeter Zijlstra 
149f7b7c26eSPeter Zijlstra static void sig_atexit(void)
150f7b7c26eSPeter Zijlstra {
1515ffc8881SIan Munsie 	if (child_pid > 0)
152933da83aSChris Wilson 		kill(child_pid, SIGTERM);
153933da83aSChris Wilson 
15418483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
155f7b7c26eSPeter Zijlstra 		return;
156f7b7c26eSPeter Zijlstra 
157f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
158f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
15986470930SIngo Molnar }
16086470930SIngo Molnar 
161dd7927f4SArnaldo Carvalho de Melo static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
162dd7927f4SArnaldo Carvalho de Melo {
163dd7927f4SArnaldo Carvalho de Melo 	struct perf_event_attr *attr = &evsel->attr;
164dd7927f4SArnaldo Carvalho de Melo 	int track = !evsel->idx; /* only the first counter needs these */
1657c6a1c65SPeter Zijlstra 
1665d2cd909SArnaldo Carvalho de Melo 	attr->inherit		= !no_inherit;
1677c6a1c65SPeter Zijlstra 	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
1687c6a1c65SPeter Zijlstra 				  PERF_FORMAT_TOTAL_TIME_RUNNING |
1697c6a1c65SPeter Zijlstra 				  PERF_FORMAT_ID;
17086470930SIngo Molnar 
1713a9f131fSFrederic Weisbecker 	attr->sample_type	|= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1723efa1cc9SIngo Molnar 
173361c99a6SArnaldo Carvalho de Melo 	if (evlist->nr_entries > 1)
1748907fd60SEric B Munson 		attr->sample_type |= PERF_SAMPLE_ID;
1758907fd60SEric B Munson 
176f9212819SFrederic Weisbecker 	/*
177f9212819SFrederic Weisbecker 	 * We default some events to a 1 default interval. But keep
178f9212819SFrederic Weisbecker 	 * it a weak assumption overridable by the user.
179f9212819SFrederic Weisbecker 	 */
180f9212819SFrederic Weisbecker 	if (!attr->sample_period || (user_freq != UINT_MAX &&
1813de29cabSStephane Eranian 				     user_interval != ULLONG_MAX)) {
18286470930SIngo Molnar 		if (freq) {
183ea1900e5SPeter Zijlstra 			attr->sample_type	|= PERF_SAMPLE_PERIOD;
18486470930SIngo Molnar 			attr->freq		= 1;
18586470930SIngo Molnar 			attr->sample_freq	= freq;
186f9212819SFrederic Weisbecker 		} else {
187f9212819SFrederic Weisbecker 			attr->sample_period = default_interval;
188f9212819SFrederic Weisbecker 		}
18986470930SIngo Molnar 	}
1903efa1cc9SIngo Molnar 
191649c48a9SPeter Zijlstra 	if (no_samples)
192649c48a9SPeter Zijlstra 		attr->sample_freq = 0;
193649c48a9SPeter Zijlstra 
194649c48a9SPeter Zijlstra 	if (inherit_stat)
195649c48a9SPeter Zijlstra 		attr->inherit_stat = 1;
196649c48a9SPeter Zijlstra 
1973af9e859SEric B Munson 	if (sample_address) {
1984bba828dSAnton Blanchard 		attr->sample_type	|= PERF_SAMPLE_ADDR;
1993af9e859SEric B Munson 		attr->mmap_data = track;
2003af9e859SEric B Munson 	}
2014bba828dSAnton Blanchard 
2023efa1cc9SIngo Molnar 	if (call_graph)
2033efa1cc9SIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN;
2043efa1cc9SIngo Molnar 
205f60f3593SArun Sharma 	if (system_wide)
206f60f3593SArun Sharma 		attr->sample_type	|= PERF_SAMPLE_CPU;
207f60f3593SArun Sharma 
208a43d3f08SArnaldo Carvalho de Melo 	if (sample_id_all_avail &&
209a43d3f08SArnaldo Carvalho de Melo 	    (sample_time || system_wide || !no_inherit || cpu_list))
2109c90a61cSArnaldo Carvalho de Melo 		attr->sample_type	|= PERF_SAMPLE_TIME;
2119c90a61cSArnaldo Carvalho de Melo 
212cd6feeeaSIngo Molnar 	if (raw_samples) {
2136ddf259dSIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_TIME;
214daac07b2SFrederic Weisbecker 		attr->sample_type	|= PERF_SAMPLE_RAW;
215cd6feeeaSIngo Molnar 		attr->sample_type	|= PERF_SAMPLE_CPU;
216cd6feeeaSIngo Molnar 	}
217f413cdb8SFrederic Weisbecker 
218acac03faSKirill Smelkov 	if (nodelay) {
219acac03faSKirill Smelkov 		attr->watermark = 0;
220acac03faSKirill Smelkov 		attr->wakeup_events = 1;
221acac03faSKirill Smelkov 	}
222acac03faSKirill Smelkov 
22386470930SIngo Molnar 	attr->mmap		= track;
22486470930SIngo Molnar 	attr->comm		= track;
225dd7927f4SArnaldo Carvalho de Melo 
2262e6cdf99SStephane Eranian 	if (target_pid == -1 && target_tid == -1 && !system_wide) {
2274502d77cSPeter Zijlstra 		attr->disabled = 1;
228bedbfdeaSEric B Munson 		attr->enable_on_exec = 1;
22946be604bSZhang, Yanmin 	}
230dd7927f4SArnaldo Carvalho de Melo }
231dd7927f4SArnaldo Carvalho de Melo 
232a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
233a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
234a91e5431SArnaldo Carvalho de Melo {
235a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
236a91e5431SArnaldo Carvalho de Melo 
237a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
238a91e5431SArnaldo Carvalho de Melo 		return false;
239a91e5431SArnaldo Carvalho de Melo 
240a91e5431SArnaldo Carvalho de Melo 	pair = list_entry(other->entries.next, struct perf_evsel, node);
241a91e5431SArnaldo Carvalho de Melo 
242a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
243a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
244a91e5431SArnaldo Carvalho de Melo 			return false;
245a91e5431SArnaldo Carvalho de Melo 		pair = list_entry(pair->node.next, struct perf_evsel, node);
246a91e5431SArnaldo Carvalho de Melo 	}
247a91e5431SArnaldo Carvalho de Melo 
248a91e5431SArnaldo Carvalho de Melo 	return true;
249a91e5431SArnaldo Carvalho de Melo }
250a91e5431SArnaldo Carvalho de Melo 
251dd7927f4SArnaldo Carvalho de Melo static void open_counters(struct perf_evlist *evlist)
252dd7927f4SArnaldo Carvalho de Melo {
253dd7927f4SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
254dd7927f4SArnaldo Carvalho de Melo 
2555d2cd909SArnaldo Carvalho de Melo 	if (evlist->cpus->map[0] < 0)
2565d2cd909SArnaldo Carvalho de Melo 		no_inherit = true;
2575d2cd909SArnaldo Carvalho de Melo 
258dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
259dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
260dd7927f4SArnaldo Carvalho de Melo 		/*
261dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
262dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
263dd7927f4SArnaldo Carvalho de Melo 		 *
264dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
265dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
266dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
267dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
268dd7927f4SArnaldo Carvalho de Melo 		 *
269dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
270dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
271dd7927f4SArnaldo Carvalho de Melo 		 */
272dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
273dd7927f4SArnaldo Carvalho de Melo 
274dd7927f4SArnaldo Carvalho de Melo 		config_attr(pos, evlist);
2759c90a61cSArnaldo Carvalho de Melo retry_sample_id:
2769c90a61cSArnaldo Carvalho de Melo 		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
2773da297a6SIngo Molnar try_again:
2785d2cd909SArnaldo Carvalho de Melo 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
27986470930SIngo Molnar 			int err = errno;
28086470930SIngo Molnar 
281c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
282c286c419SArnaldo Carvalho de Melo 				ui__warning_paranoid();
283c286c419SArnaldo Carvalho de Melo 				exit(EXIT_FAILURE);
284c286c419SArnaldo Carvalho de Melo 			} else if (err ==  ENODEV && cpu_list) {
285d6d901c2SZhang, Yanmin 				die("No such device - did you specify"
286d6d901c2SZhang, Yanmin 					" an out-of-range profile CPU?\n");
2879c90a61cSArnaldo Carvalho de Melo 			} else if (err == EINVAL && sample_id_all_avail) {
2889c90a61cSArnaldo Carvalho de Melo 				/*
2899c90a61cSArnaldo Carvalho de Melo 				 * Old kernel, no attr->sample_id_type_all field
2909c90a61cSArnaldo Carvalho de Melo 				 */
2919c90a61cSArnaldo Carvalho de Melo 				sample_id_all_avail = false;
292a43d3f08SArnaldo Carvalho de Melo 				if (!sample_time && !raw_samples && !time_needed)
293eac23d1cSIan Munsie 					attr->sample_type &= ~PERF_SAMPLE_TIME;
294eac23d1cSIan Munsie 
2959c90a61cSArnaldo Carvalho de Melo 				goto retry_sample_id;
296d6d901c2SZhang, Yanmin 			}
2973da297a6SIngo Molnar 
2983da297a6SIngo Molnar 			/*
2993da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
3003da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
3013da297a6SIngo Molnar 			 * is always available even if no PMU support:
3023da297a6SIngo Molnar 			 */
3033da297a6SIngo Molnar 			if (attr->type == PERF_TYPE_HARDWARE
304f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
3053da297a6SIngo Molnar 
3063da297a6SIngo Molnar 				if (verbose)
307ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
308ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
3093da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
310f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
3113da297a6SIngo Molnar 				goto try_again;
3123da297a6SIngo Molnar 			}
313ca6a4258SDavid Ahern 
314ca6a4258SDavid Ahern 			if (err == ENOENT) {
315ca6a4258SDavid Ahern 				ui__warning("The %s event is not supported.\n",
316ca6a4258SDavid Ahern 					    event_name(pos));
317ca6a4258SDavid Ahern 				exit(EXIT_FAILURE);
318ca6a4258SDavid Ahern 			}
319ca6a4258SDavid Ahern 
32030c806a0SIngo Molnar 			printf("\n");
321d9cf837eSCorey Ashford 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
322dd7927f4SArnaldo Carvalho de Melo 			      err, strerror(err));
323bfd45118SSimon Kaempflein 
324bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
325bfd45118SSimon Kaempflein 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
326d6d901c2SZhang, Yanmin 				die("No hardware sampling interrupt available."
327d6d901c2SZhang, Yanmin 				    " No APIC? If so then you can boot the kernel"
328d6d901c2SZhang, Yanmin 				    " with the \"lapic\" boot parameter to"
329d6d901c2SZhang, Yanmin 				    " force-enable it.\n");
330bfd45118SSimon Kaempflein #endif
331bfd45118SSimon Kaempflein 
332cdd6c482SIngo Molnar 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
3337c6a1c65SPeter Zijlstra 		}
3347c6a1c65SPeter Zijlstra 	}
3357c6a1c65SPeter Zijlstra 
3360a102479SFrederic Weisbecker 	if (perf_evlist__set_filters(evlist)) {
3370a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
3380a102479SFrederic Weisbecker 			strerror(errno));
3390a102479SFrederic Weisbecker 		exit(-1);
3400a102479SFrederic Weisbecker 	}
3410a102479SFrederic Weisbecker 
3427e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
3430a27d7f9SArnaldo Carvalho de Melo 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
3440a27d7f9SArnaldo Carvalho de Melo 
345a91e5431SArnaldo Carvalho de Melo 	if (file_new)
346a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
347a91e5431SArnaldo Carvalho de Melo 	else {
348a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
349a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
350a91e5431SArnaldo Carvalho de Melo 			exit(-1);
351dd7927f4SArnaldo Carvalho de Melo 		}
35286470930SIngo Molnar  	}
35386470930SIngo Molnar 
354a91e5431SArnaldo Carvalho de Melo 	perf_session__update_sample_type(session);
355a91e5431SArnaldo Carvalho de Melo }
356a91e5431SArnaldo Carvalho de Melo 
3576122e4e4SArnaldo Carvalho de Melo static int process_buildids(void)
3586122e4e4SArnaldo Carvalho de Melo {
3596122e4e4SArnaldo Carvalho de Melo 	u64 size = lseek(output, 0, SEEK_CUR);
3606122e4e4SArnaldo Carvalho de Melo 
3619f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
3629f591fd7SArnaldo Carvalho de Melo 		return 0;
3639f591fd7SArnaldo Carvalho de Melo 
3646122e4e4SArnaldo Carvalho de Melo 	session->fd = output;
3656122e4e4SArnaldo Carvalho de Melo 	return __perf_session__process_events(session, post_processing_offset,
3666122e4e4SArnaldo Carvalho de Melo 					      size - post_processing_offset,
3676122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3686122e4e4SArnaldo Carvalho de Melo }
3696122e4e4SArnaldo Carvalho de Melo 
370f5970550SPeter Zijlstra static void atexit_header(void)
371f5970550SPeter Zijlstra {
372c7929e47STom Zanussi 	if (!pipe_output) {
37394c744b6SArnaldo Carvalho de Melo 		session->header.data_size += bytes_written;
374f5970550SPeter Zijlstra 
375baa2f6ceSArnaldo Carvalho de Melo 		if (!no_buildid)
3766122e4e4SArnaldo Carvalho de Melo 			process_buildids();
377a91e5431SArnaldo Carvalho de Melo 		perf_session__write_header(session, evsel_list, output, true);
37839d17dacSArnaldo Carvalho de Melo 		perf_session__delete(session);
379361c99a6SArnaldo Carvalho de Melo 		perf_evlist__delete(evsel_list);
380d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
381c7929e47STom Zanussi 	}
382f5970550SPeter Zijlstra }
383f5970550SPeter Zijlstra 
3848115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
385a1645ce1SZhang, Yanmin {
386a1645ce1SZhang, Yanmin 	int err;
38723346f21SArnaldo Carvalho de Melo 	struct perf_session *psession = data;
388a1645ce1SZhang, Yanmin 
38923346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
390a1645ce1SZhang, Yanmin 		return;
391a1645ce1SZhang, Yanmin 
392a1645ce1SZhang, Yanmin 	/*
393a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
394a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
395a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
396a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
397a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
398a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
399a1645ce1SZhang, Yanmin 	 */
4008115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
40123346f21SArnaldo Carvalho de Melo 					     psession, machine);
402a1645ce1SZhang, Yanmin 	if (err < 0)
403a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
40423346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
405a1645ce1SZhang, Yanmin 
406a1645ce1SZhang, Yanmin 	/*
407a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
408a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
409a1645ce1SZhang, Yanmin 	 */
4108115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
41123346f21SArnaldo Carvalho de Melo 						 psession, machine, "_text");
412a1645ce1SZhang, Yanmin 	if (err < 0)
4138115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
4148115d60cSArnaldo Carvalho de Melo 							 psession, machine,
4158115d60cSArnaldo Carvalho de Melo 							 "_stext");
416a1645ce1SZhang, Yanmin 	if (err < 0)
417a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
41823346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
419a1645ce1SZhang, Yanmin }
420a1645ce1SZhang, Yanmin 
42198402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
42298402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
42398402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
42498402807SFrederic Weisbecker };
42598402807SFrederic Weisbecker 
42698402807SFrederic Weisbecker static void mmap_read_all(void)
42798402807SFrederic Weisbecker {
4280e2e63ddSPeter Zijlstra 	int i;
42998402807SFrederic Weisbecker 
430aece948fSArnaldo Carvalho de Melo 	for (i = 0; i < evsel_list->nr_mmaps; i++) {
4310a27d7f9SArnaldo Carvalho de Melo 		if (evsel_list->mmap[i].base)
4320a27d7f9SArnaldo Carvalho de Melo 			mmap_read(&evsel_list->mmap[i]);
43398402807SFrederic Weisbecker 	}
43498402807SFrederic Weisbecker 
43598402807SFrederic Weisbecker 	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
43698402807SFrederic Weisbecker 		write_output(&finished_round_event, sizeof(finished_round_event));
43798402807SFrederic Weisbecker }
43898402807SFrederic Weisbecker 
439d4db3f16SArnaldo Carvalho de Melo static int __cmd_record(int argc, const char **argv)
44086470930SIngo Molnar {
44169aad6f1SArnaldo Carvalho de Melo 	int i;
44286470930SIngo Molnar 	struct stat st;
44386470930SIngo Molnar 	int flags;
4444dc0a04bSArnaldo Carvalho de Melo 	int err;
4458b412664SPeter Zijlstra 	unsigned long waking = 0;
446856e9660SPeter Zijlstra 	int child_ready_pipe[2], go_pipe[2];
44746be604bSZhang, Yanmin 	const bool forks = argc > 0;
448856e9660SPeter Zijlstra 	char buf;
44923346f21SArnaldo Carvalho de Melo 	struct machine *machine;
45086470930SIngo Molnar 
45186470930SIngo Molnar 	page_size = sysconf(_SC_PAGE_SIZE);
45286470930SIngo Molnar 
453f5970550SPeter Zijlstra 	atexit(sig_atexit);
454f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
455f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
45618483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
457f5970550SPeter Zijlstra 
458d4db3f16SArnaldo Carvalho de Melo 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
459856e9660SPeter Zijlstra 		perror("failed to create pipes");
460856e9660SPeter Zijlstra 		exit(-1);
461856e9660SPeter Zijlstra 	}
462856e9660SPeter Zijlstra 
463d7065adbSFranck Bui-Huu 	if (!output_name) {
464d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
465d7065adbSFranck Bui-Huu 			pipe_output = 1;
466d7065adbSFranck Bui-Huu 		else
467d7065adbSFranck Bui-Huu 			output_name = "perf.data";
468d7065adbSFranck Bui-Huu 	}
469d7065adbSFranck Bui-Huu 	if (output_name) {
470529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
471529870e3STom Zanussi 			pipe_output = 1;
472529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
4737865e817SFrederic Weisbecker 			if (write_mode == WRITE_FORCE) {
474b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
475b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
476b38d3464SArnaldo Carvalho de Melo 					 output_name);
477b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
478b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
479b38d3464SArnaldo Carvalho de Melo 			}
4807865e817SFrederic Weisbecker 		} else if (write_mode == WRITE_APPEND) {
4817865e817SFrederic Weisbecker 			write_mode = WRITE_FORCE;
482266e0e21SPierre Habouzit 		}
483d7065adbSFranck Bui-Huu 	}
48486470930SIngo Molnar 
485f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
4867865e817SFrederic Weisbecker 	if (write_mode == WRITE_APPEND)
487f5970550SPeter Zijlstra 		file_new = 0;
48886470930SIngo Molnar 	else
48986470930SIngo Molnar 		flags |= O_TRUNC;
49086470930SIngo Molnar 
491529870e3STom Zanussi 	if (pipe_output)
492529870e3STom Zanussi 		output = STDOUT_FILENO;
493529870e3STom Zanussi 	else
49486470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
49586470930SIngo Molnar 	if (output < 0) {
49686470930SIngo Molnar 		perror("failed to create output file");
49786470930SIngo Molnar 		exit(-1);
49886470930SIngo Molnar 	}
49986470930SIngo Molnar 
5007865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
50121ef97f0SIan Munsie 				    write_mode == WRITE_FORCE, false, NULL);
50294c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
503a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
504a9a70bbcSArnaldo Carvalho de Melo 		return -1;
505a9a70bbcSArnaldo Carvalho de Melo 	}
506a9a70bbcSArnaldo Carvalho de Melo 
507baa2f6ceSArnaldo Carvalho de Melo 	if (!no_buildid)
508baa2f6ceSArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
509baa2f6ceSArnaldo Carvalho de Melo 
5104dc0a04bSArnaldo Carvalho de Melo 	if (!file_new) {
511a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
5124dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
51339d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
5144dc0a04bSArnaldo Carvalho de Melo 	}
5154dc0a04bSArnaldo Carvalho de Melo 
516361c99a6SArnaldo Carvalho de Melo 	if (have_tracepoints(&evsel_list->entries))
51794c744b6SArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
51803456a15SFrederic Weisbecker 
519800cd25cSFrederic Weisbecker 	/* 512 kiB: default amount of unprivileged mlocked memory */
520800cd25cSFrederic Weisbecker 	if (mmap_pages == UINT_MAX)
521800cd25cSFrederic Weisbecker 		mmap_pages = (512 * 1024) / page_size;
522800cd25cSFrederic Weisbecker 
523d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
52446be604bSZhang, Yanmin 		child_pid = fork();
5252fb750e8SBorislav Petkov 		if (child_pid < 0) {
526856e9660SPeter Zijlstra 			perror("failed to fork");
527856e9660SPeter Zijlstra 			exit(-1);
528856e9660SPeter Zijlstra 		}
5297c6a1c65SPeter Zijlstra 
53046be604bSZhang, Yanmin 		if (!child_pid) {
531529870e3STom Zanussi 			if (pipe_output)
532529870e3STom Zanussi 				dup2(2, 1);
533856e9660SPeter Zijlstra 			close(child_ready_pipe[0]);
534856e9660SPeter Zijlstra 			close(go_pipe[1]);
535856e9660SPeter Zijlstra 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
536856e9660SPeter Zijlstra 
537856e9660SPeter Zijlstra 			/*
538856e9660SPeter Zijlstra 			 * Do a dummy execvp to get the PLT entry resolved,
539856e9660SPeter Zijlstra 			 * so we avoid the resolver overhead on the real
540856e9660SPeter Zijlstra 			 * execvp call.
541856e9660SPeter Zijlstra 			 */
542856e9660SPeter Zijlstra 			execvp("", (char **)argv);
543856e9660SPeter Zijlstra 
544856e9660SPeter Zijlstra 			/*
545856e9660SPeter Zijlstra 			 * Tell the parent we're ready to go
546856e9660SPeter Zijlstra 			 */
547856e9660SPeter Zijlstra 			close(child_ready_pipe[1]);
548856e9660SPeter Zijlstra 
549856e9660SPeter Zijlstra 			/*
550856e9660SPeter Zijlstra 			 * Wait until the parent tells us to go.
551856e9660SPeter Zijlstra 			 */
552856e9660SPeter Zijlstra 			if (read(go_pipe[0], &buf, 1) == -1)
553856e9660SPeter Zijlstra 				perror("unable to read pipe");
554856e9660SPeter Zijlstra 
555856e9660SPeter Zijlstra 			execvp(argv[0], (char **)argv);
556856e9660SPeter Zijlstra 
557856e9660SPeter Zijlstra 			perror(argv[0]);
55818483b81SArnaldo Carvalho de Melo 			kill(getppid(), SIGUSR1);
559856e9660SPeter Zijlstra 			exit(-1);
560856e9660SPeter Zijlstra 		}
561856e9660SPeter Zijlstra 
562d6d901c2SZhang, Yanmin 		if (!system_wide && target_tid == -1 && target_pid == -1)
5637e2ed097SArnaldo Carvalho de Melo 			evsel_list->threads->map[0] = child_pid;
564d6d901c2SZhang, Yanmin 
565856e9660SPeter Zijlstra 		close(child_ready_pipe[1]);
566856e9660SPeter Zijlstra 		close(go_pipe[0]);
567856e9660SPeter Zijlstra 		/*
568856e9660SPeter Zijlstra 		 * wait for child to settle
569856e9660SPeter Zijlstra 		 */
570856e9660SPeter Zijlstra 		if (read(child_ready_pipe[0], &buf, 1) == -1) {
571856e9660SPeter Zijlstra 			perror("unable to read pipe");
572856e9660SPeter Zijlstra 			exit(-1);
573856e9660SPeter Zijlstra 		}
574856e9660SPeter Zijlstra 		close(child_ready_pipe[0]);
575856e9660SPeter Zijlstra 	}
576856e9660SPeter Zijlstra 
577dd7927f4SArnaldo Carvalho de Melo 	open_counters(evsel_list);
57886470930SIngo Molnar 
579712a4b60SArnaldo Carvalho de Melo 	/*
580712a4b60SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at atexit_header()
581712a4b60SArnaldo Carvalho de Melo 	 */
582712a4b60SArnaldo Carvalho de Melo 	atexit(atexit_header);
583712a4b60SArnaldo Carvalho de Melo 
584529870e3STom Zanussi 	if (pipe_output) {
585529870e3STom Zanussi 		err = perf_header__write_pipe(output);
586529870e3STom Zanussi 		if (err < 0)
587529870e3STom Zanussi 			return err;
588529870e3STom Zanussi 	} else if (file_new) {
589a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
590361c99a6SArnaldo Carvalho de Melo 						 output, false);
591d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
592d5eed904SArnaldo Carvalho de Melo 			return err;
593d5eed904SArnaldo Carvalho de Melo 	}
5947c6a1c65SPeter Zijlstra 
5956122e4e4SArnaldo Carvalho de Melo 	post_processing_offset = lseek(output, 0, SEEK_CUR);
5966122e4e4SArnaldo Carvalho de Melo 
5972c46dbb5STom Zanussi 	if (pipe_output) {
598a91e5431SArnaldo Carvalho de Melo 		err = perf_session__synthesize_attrs(session,
599a91e5431SArnaldo Carvalho de Melo 						     process_synthesized_event);
6002c46dbb5STom Zanussi 		if (err < 0) {
6012c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
6022c46dbb5STom Zanussi 			return err;
6032c46dbb5STom Zanussi 		}
604cd19a035STom Zanussi 
6058115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(process_synthesized_event,
606cd19a035STom Zanussi 							 session);
607cd19a035STom Zanussi 		if (err < 0) {
608cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
609cd19a035STom Zanussi 			return err;
610cd19a035STom Zanussi 		}
6119215545eSTom Zanussi 
612361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
61363e0c771STom Zanussi 			/*
61463e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
61563e0c771STom Zanussi 			 * there were no tracepoints so its not really
61663e0c771STom Zanussi 			 * an error, just that we don't need to
61763e0c771STom Zanussi 			 * synthesize anything.  We really have to
61863e0c771STom Zanussi 			 * return this more properly and also
61963e0c771STom Zanussi 			 * propagate errors that now are calling die()
62063e0c771STom Zanussi 			 */
6218115d60cSArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(output, evsel_list,
6229215545eSTom Zanussi 								  process_synthesized_event,
6239215545eSTom Zanussi 								  session);
62463e0c771STom Zanussi 			if (err <= 0) {
62563e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
62663e0c771STom Zanussi 				return err;
62763e0c771STom Zanussi 			}
6289215545eSTom Zanussi 			advance_output(err);
6292c46dbb5STom Zanussi 		}
63063e0c771STom Zanussi 	}
6312c46dbb5STom Zanussi 
63223346f21SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
63323346f21SArnaldo Carvalho de Melo 	if (!machine) {
634a1645ce1SZhang, Yanmin 		pr_err("Couldn't find native kernel information.\n");
635a1645ce1SZhang, Yanmin 		return -1;
636a1645ce1SZhang, Yanmin 	}
637a1645ce1SZhang, Yanmin 
6388115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
63923346f21SArnaldo Carvalho de Melo 						 session, machine, "_text");
64070162138SArnaldo Carvalho de Melo 	if (err < 0)
6418115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
64223346f21SArnaldo Carvalho de Melo 							 session, machine, "_stext");
643c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
644c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
645c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
646c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
64756b03f3cSArnaldo Carvalho de Melo 
6488115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
64923346f21SArnaldo Carvalho de Melo 					     session, machine);
650c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
651c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
652c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
653c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
654c1a3a4b9SArnaldo Carvalho de Melo 
655a1645ce1SZhang, Yanmin 	if (perf_guest)
6568115d60cSArnaldo Carvalho de Melo 		perf_session__process_machines(session,
6578115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
658b7cece76SArnaldo Carvalho de Melo 
659cf103a14SStephane Eranian 	if (!system_wide)
6607c940c18SArnaldo Carvalho de Melo 		perf_event__synthesize_thread_map(evsel_list->threads,
6618115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
662d8f66248SArnaldo Carvalho de Melo 						  session);
663234fbbf5SArnaldo Carvalho de Melo 	else
6648115d60cSArnaldo Carvalho de Melo 		perf_event__synthesize_threads(process_synthesized_event,
6658115d60cSArnaldo Carvalho de Melo 					       session);
6667c6a1c65SPeter Zijlstra 
66786470930SIngo Molnar 	if (realtime_prio) {
66886470930SIngo Molnar 		struct sched_param param;
66986470930SIngo Molnar 
67086470930SIngo Molnar 		param.sched_priority = realtime_prio;
67186470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6726beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
67386470930SIngo Molnar 			exit(-1);
67486470930SIngo Molnar 		}
67586470930SIngo Molnar 	}
67686470930SIngo Molnar 
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;
685d6d901c2SZhang, Yanmin 		int thread;
68686470930SIngo Molnar 
68798402807SFrederic Weisbecker 		mmap_read_all();
68886470930SIngo Molnar 
689649c48a9SPeter Zijlstra 		if (hits == samples) {
690649c48a9SPeter Zijlstra 			if (done)
691649c48a9SPeter Zijlstra 				break;
6925c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6938b412664SPeter Zijlstra 			waking++;
6948b412664SPeter Zijlstra 		}
6958b412664SPeter Zijlstra 
6968b412664SPeter Zijlstra 		if (done) {
6977e2ed097SArnaldo Carvalho de Melo 			for (i = 0; i < evsel_list->cpus->nr; i++) {
69869aad6f1SArnaldo Carvalho de Melo 				struct perf_evsel *pos;
69969aad6f1SArnaldo Carvalho de Melo 
700361c99a6SArnaldo Carvalho de Melo 				list_for_each_entry(pos, &evsel_list->entries, node) {
701d6d901c2SZhang, Yanmin 					for (thread = 0;
7027e2ed097SArnaldo Carvalho de Melo 						thread < evsel_list->threads->nr;
703d6d901c2SZhang, Yanmin 						thread++)
70469aad6f1SArnaldo Carvalho de Melo 						ioctl(FD(pos, i, thread),
705d6d901c2SZhang, Yanmin 							PERF_EVENT_IOC_DISABLE);
706d6d901c2SZhang, Yanmin 				}
70786470930SIngo Molnar 			}
708649c48a9SPeter Zijlstra 		}
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",
743*f120f9d5SJiri 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"),
7713efa1cc9SIngo Molnar 	OPT_BOOLEAN('g', "call-graph", &call_graph,
7723efa1cc9SIngo Molnar 		    "do call-graph (stack chain/backtrace) recording"),
773c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
7743da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
775b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
776649c48a9SPeter Zijlstra 	OPT_BOOLEAN('s', "stat", &inherit_stat,
777649c48a9SPeter Zijlstra 		    "per thread counts"),
7784bba828dSAnton Blanchard 	OPT_BOOLEAN('d', "data", &sample_address,
7794bba828dSAnton Blanchard 		    "Sample addresses"),
7809c90a61cSArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
781649c48a9SPeter Zijlstra 	OPT_BOOLEAN('n', "no-samples", &no_samples,
782649c48a9SPeter Zijlstra 		    "don't sample"),
783baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
784a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
785baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
786baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
787023695d9SStephane Eranian 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
788023695d9SStephane Eranian 		     "monitor event in cgroup name only",
789023695d9SStephane Eranian 		     parse_cgroups),
79086470930SIngo Molnar 	OPT_END()
79186470930SIngo Molnar };
79286470930SIngo Molnar 
793f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used)
79486470930SIngo Molnar {
79569aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
79669aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
79786470930SIngo Molnar 
7987e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
799361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
800361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
801361c99a6SArnaldo Carvalho de Melo 
802bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
803a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
804d6d901c2SZhang, Yanmin 	if (!argc && target_pid == -1 && target_tid == -1 &&
805c45c6ea2SStephane Eranian 		!system_wide && !cpu_list)
806bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
80786470930SIngo Molnar 
8087865e817SFrederic Weisbecker 	if (force && append_file) {
8097865e817SFrederic Weisbecker 		fprintf(stderr, "Can't overwrite and append at the same time."
8107865e817SFrederic Weisbecker 				" You need to choose between -f and -A");
811bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
8127865e817SFrederic Weisbecker 	} else if (append_file) {
8137865e817SFrederic Weisbecker 		write_mode = WRITE_APPEND;
8147865e817SFrederic Weisbecker 	} else {
8157865e817SFrederic Weisbecker 		write_mode = WRITE_FORCE;
8167865e817SFrederic Weisbecker 	}
8177865e817SFrederic Weisbecker 
818023695d9SStephane Eranian 	if (nr_cgroups && !system_wide) {
819023695d9SStephane Eranian 		fprintf(stderr, "cgroup monitoring only available in"
820023695d9SStephane Eranian 			" system-wide mode\n");
821023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
822023695d9SStephane Eranian 	}
823023695d9SStephane Eranian 
824655000e7SArnaldo Carvalho de Melo 	symbol__init();
825baa2f6ceSArnaldo Carvalho de Melo 
826ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
827646aaea6SArnaldo Carvalho de Melo 		pr_warning(
828646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
829ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
830646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
831646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
832646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
833646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
834646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
835ec80fde7SArnaldo Carvalho de Melo 
836baa2f6ceSArnaldo Carvalho de Melo 	if (no_buildid_cache || no_buildid)
837a1ac1d3cSStephane Eranian 		disable_buildid_cache();
838655000e7SArnaldo Carvalho de Melo 
839361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
840361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
84169aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
84269aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
843bbd36e5eSPeter Zijlstra 	}
84486470930SIngo Molnar 
8455c98d466SArnaldo Carvalho de Melo 	if (target_pid != -1)
846d6d901c2SZhang, Yanmin 		target_tid = target_pid;
847d6d901c2SZhang, Yanmin 
8487e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(evsel_list, target_pid,
8497e2ed097SArnaldo Carvalho de Melo 				     target_tid, cpu_list) < 0)
850dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
85169aad6f1SArnaldo Carvalho de Melo 
852361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
8537e2ed097SArnaldo Carvalho de Melo 		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
8547e2ed097SArnaldo Carvalho de Melo 					 evsel_list->threads->nr) < 0)
85569aad6f1SArnaldo Carvalho de Melo 			goto out_free_fd;
856ad7f4e3fSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, event_name(pos)))
857ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
858d6d901c2SZhang, Yanmin 	}
8595c581041SArnaldo Carvalho de Melo 
8607e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
86139d17dacSArnaldo Carvalho de Melo 		goto out_free_fd;
862d6d901c2SZhang, Yanmin 
8633de29cabSStephane Eranian 	if (user_interval != ULLONG_MAX)
864f9212819SFrederic Weisbecker 		default_interval = user_interval;
865f9212819SFrederic Weisbecker 	if (user_freq != UINT_MAX)
866f9212819SFrederic Weisbecker 		freq = user_freq;
867f9212819SFrederic Weisbecker 
8687e4ff9e3SMike Galbraith 	/*
8697e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
8707e4ff9e3SMike Galbraith 	 */
8717e4ff9e3SMike Galbraith 	if (default_interval)
8727e4ff9e3SMike Galbraith 		freq = 0;
8737e4ff9e3SMike Galbraith 	else if (freq) {
8747e4ff9e3SMike Galbraith 		default_interval = freq;
8757e4ff9e3SMike Galbraith 	} else {
8767e4ff9e3SMike Galbraith 		fprintf(stderr, "frequency and count are zero, aborting\n");
87739d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
8785c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
8797e4ff9e3SMike Galbraith 	}
8807e4ff9e3SMike Galbraith 
88139d17dacSArnaldo Carvalho de Melo 	err = __cmd_record(argc, argv);
88239d17dacSArnaldo Carvalho de Melo out_free_fd:
8837e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
884d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
885d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
88639d17dacSArnaldo Carvalho de Melo 	return err;
88786470930SIngo Molnar }
888