xref: /openbmc/linux/tools/perf/builtin-record.c (revision 0f82ebc452f921590e216b28eee0b41f5e434a48)
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 
38*0f82ebc4SArnaldo Carvalho de Melo static struct perf_record_opts record_opts = {
39*0f82ebc4SArnaldo Carvalho de Melo 	.target_pid	     = -1,
40*0f82ebc4SArnaldo Carvalho de Melo 	.target_tid	     = -1,
41*0f82ebc4SArnaldo Carvalho de Melo 	.user_freq	     = UINT_MAX,
42*0f82ebc4SArnaldo Carvalho de Melo 	.user_interval	     = ULLONG_MAX,
43*0f82ebc4SArnaldo Carvalho de Melo 	.freq		     = 1000,
44*0f82ebc4SArnaldo Carvalho de Melo 	.sample_id_all_avail = true,
45*0f82ebc4SArnaldo Carvalho de Melo };
4686470930SIngo Molnar 
4786470930SIngo Molnar static unsigned int		page_size;
48800cd25cSFrederic Weisbecker static unsigned int		mmap_pages			= UINT_MAX;
4986470930SIngo Molnar static int			output;
50529870e3STom Zanussi static int			pipe_output			=      0;
51d7065adbSFranck Bui-Huu static const char		*output_name			= NULL;
5243bece79SLin Ming static bool			group				=  false;
531967936dSArnaldo Carvalho de Melo static int			realtime_prio			=      0;
54933da83aSChris Wilson static pid_t			child_pid			=     -1;
557865e817SFrederic Weisbecker static enum write_mode_t	write_mode			= WRITE_FORCE;
56a1ac1d3cSStephane Eranian static bool			no_buildid			=  false;
57baa2f6ceSArnaldo Carvalho de Melo static bool			no_buildid_cache		=  false;
58361c99a6SArnaldo Carvalho de Melo static struct perf_evlist	*evsel_list;
5986470930SIngo Molnar 
6042e59d7dSIngo Molnar static long			samples				=      0;
6142e59d7dSIngo Molnar static u64			bytes_written			=      0;
6286470930SIngo Molnar 
63f5970550SPeter Zijlstra static int			file_new			=      1;
646122e4e4SArnaldo Carvalho de Melo static off_t			post_processing_offset;
657c6a1c65SPeter Zijlstra 
6694c744b6SArnaldo Carvalho de Melo static struct perf_session	*session;
6733e49ea7SAndi Kleen static const char               *progname;
68f5970550SPeter Zijlstra 
699215545eSTom Zanussi static void advance_output(size_t size)
709215545eSTom Zanussi {
719215545eSTom Zanussi 	bytes_written += size;
729215545eSTom Zanussi }
739215545eSTom Zanussi 
74f5970550SPeter Zijlstra static void write_output(void *buf, size_t size)
75f5970550SPeter Zijlstra {
76f5970550SPeter Zijlstra 	while (size) {
77f5970550SPeter Zijlstra 		int ret = write(output, buf, size);
78f5970550SPeter Zijlstra 
79f5970550SPeter Zijlstra 		if (ret < 0)
80f5970550SPeter Zijlstra 			die("failed to write");
81f5970550SPeter Zijlstra 
82f5970550SPeter Zijlstra 		size -= ret;
83f5970550SPeter Zijlstra 		buf += ret;
84f5970550SPeter Zijlstra 
85f5970550SPeter Zijlstra 		bytes_written += ret;
86f5970550SPeter Zijlstra 	}
87f5970550SPeter Zijlstra }
88f5970550SPeter Zijlstra 
898115d60cSArnaldo Carvalho de Melo static int process_synthesized_event(union perf_event *event,
908d50e5b4SArnaldo Carvalho de Melo 				     struct perf_sample *sample __used,
91d8f66248SArnaldo Carvalho de Melo 				     struct perf_session *self __used)
92234fbbf5SArnaldo Carvalho de Melo {
936122e4e4SArnaldo Carvalho de Melo 	write_output(event, event->header.size);
94234fbbf5SArnaldo Carvalho de Melo 	return 0;
95234fbbf5SArnaldo Carvalho de Melo }
96234fbbf5SArnaldo Carvalho de Melo 
97744bd8aaSArnaldo Carvalho de Melo static void mmap_read(struct perf_mmap *md)
9886470930SIngo Molnar {
99744bd8aaSArnaldo Carvalho de Melo 	unsigned int head = perf_mmap__read_head(md);
10086470930SIngo Molnar 	unsigned int old = md->prev;
10186470930SIngo Molnar 	unsigned char *data = md->base + page_size;
10286470930SIngo Molnar 	unsigned long size;
10386470930SIngo Molnar 	void *buf;
10486470930SIngo Molnar 
105dc82009aSArnaldo Carvalho de Melo 	if (old == head)
106dc82009aSArnaldo Carvalho de Melo 		return;
10786470930SIngo Molnar 
10886470930SIngo Molnar 	samples++;
10986470930SIngo Molnar 
11086470930SIngo Molnar 	size = head - old;
11186470930SIngo Molnar 
11286470930SIngo Molnar 	if ((old & md->mask) + size != (head & md->mask)) {
11386470930SIngo Molnar 		buf = &data[old & md->mask];
11486470930SIngo Molnar 		size = md->mask + 1 - (old & md->mask);
11586470930SIngo Molnar 		old += size;
11686470930SIngo Molnar 
1176122e4e4SArnaldo Carvalho de Melo 		write_output(buf, size);
11886470930SIngo Molnar 	}
11986470930SIngo Molnar 
12086470930SIngo Molnar 	buf = &data[old & md->mask];
12186470930SIngo Molnar 	size = head - old;
12286470930SIngo Molnar 	old += size;
12386470930SIngo Molnar 
1246122e4e4SArnaldo Carvalho de Melo 	write_output(buf, size);
12586470930SIngo Molnar 
12686470930SIngo Molnar 	md->prev = old;
127115d2d89SArnaldo Carvalho de Melo 	perf_mmap__write_tail(md, old);
12886470930SIngo Molnar }
12986470930SIngo Molnar 
13086470930SIngo Molnar static volatile int done = 0;
131f7b7c26eSPeter Zijlstra static volatile int signr = -1;
13233e49ea7SAndi Kleen static volatile int child_finished = 0;
13386470930SIngo Molnar 
13486470930SIngo Molnar static void sig_handler(int sig)
13586470930SIngo Molnar {
13633e49ea7SAndi Kleen 	if (sig == SIGCHLD)
13733e49ea7SAndi Kleen 		child_finished = 1;
13833e49ea7SAndi Kleen 
13986470930SIngo Molnar 	done = 1;
140f7b7c26eSPeter Zijlstra 	signr = sig;
141f7b7c26eSPeter Zijlstra }
142f7b7c26eSPeter Zijlstra 
143f7b7c26eSPeter Zijlstra static void sig_atexit(void)
144f7b7c26eSPeter Zijlstra {
14533e49ea7SAndi Kleen 	int status;
14633e49ea7SAndi Kleen 
14733e49ea7SAndi Kleen 	if (child_pid > 0) {
14833e49ea7SAndi Kleen 		if (!child_finished)
149933da83aSChris Wilson 			kill(child_pid, SIGTERM);
150933da83aSChris Wilson 
15133e49ea7SAndi Kleen 		wait(&status);
15233e49ea7SAndi Kleen 		if (WIFSIGNALED(status))
15333e49ea7SAndi Kleen 			psignal(WTERMSIG(status), progname);
15433e49ea7SAndi Kleen 	}
15533e49ea7SAndi Kleen 
15618483b81SArnaldo Carvalho de Melo 	if (signr == -1 || signr == SIGUSR1)
157f7b7c26eSPeter Zijlstra 		return;
158f7b7c26eSPeter Zijlstra 
159f7b7c26eSPeter Zijlstra 	signal(signr, SIG_DFL);
160f7b7c26eSPeter Zijlstra 	kill(getpid(), signr);
16186470930SIngo Molnar }
16286470930SIngo Molnar 
163a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist,
164a91e5431SArnaldo Carvalho de Melo 			       struct perf_evlist *other)
165a91e5431SArnaldo Carvalho de Melo {
166a91e5431SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *pair;
167a91e5431SArnaldo Carvalho de Melo 
168a91e5431SArnaldo Carvalho de Melo 	if (evlist->nr_entries != other->nr_entries)
169a91e5431SArnaldo Carvalho de Melo 		return false;
170a91e5431SArnaldo Carvalho de Melo 
171a91e5431SArnaldo Carvalho de Melo 	pair = list_entry(other->entries.next, struct perf_evsel, node);
172a91e5431SArnaldo Carvalho de Melo 
173a91e5431SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
174a91e5431SArnaldo Carvalho de Melo 		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
175a91e5431SArnaldo Carvalho de Melo 			return false;
176a91e5431SArnaldo Carvalho de Melo 		pair = list_entry(pair->node.next, struct perf_evsel, node);
177a91e5431SArnaldo Carvalho de Melo 	}
178a91e5431SArnaldo Carvalho de Melo 
179a91e5431SArnaldo Carvalho de Melo 	return true;
180a91e5431SArnaldo Carvalho de Melo }
181a91e5431SArnaldo Carvalho de Melo 
182dd7927f4SArnaldo Carvalho de Melo static void open_counters(struct perf_evlist *evlist)
183dd7927f4SArnaldo Carvalho de Melo {
184727ab04eSArnaldo Carvalho de Melo 	struct perf_evsel *pos, *first;
185dd7927f4SArnaldo Carvalho de Melo 
186727ab04eSArnaldo Carvalho de Melo 	first = list_entry(evlist->entries.next, struct perf_evsel, node);
187727ab04eSArnaldo Carvalho de Melo 
188*0f82ebc4SArnaldo Carvalho de Melo 	perf_evlist__config_attrs(evlist, &record_opts);
189*0f82ebc4SArnaldo Carvalho de Melo 
190dd7927f4SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evlist->entries, node) {
191dd7927f4SArnaldo Carvalho de Melo 		struct perf_event_attr *attr = &pos->attr;
192727ab04eSArnaldo Carvalho de Melo 		struct xyarray *group_fd = NULL;
193dd7927f4SArnaldo Carvalho de Melo 		/*
194dd7927f4SArnaldo Carvalho de Melo 		 * Check if parse_single_tracepoint_event has already asked for
195dd7927f4SArnaldo Carvalho de Melo 		 * PERF_SAMPLE_TIME.
196dd7927f4SArnaldo Carvalho de Melo 		 *
197dd7927f4SArnaldo Carvalho de Melo 		 * XXX this is kludgy but short term fix for problems introduced by
198dd7927f4SArnaldo Carvalho de Melo 		 * eac23d1c that broke 'perf script' by having different sample_types
199dd7927f4SArnaldo Carvalho de Melo 		 * when using multiple tracepoint events when we use a perf binary
200dd7927f4SArnaldo Carvalho de Melo 		 * that tries to use sample_id_all on an older kernel.
201dd7927f4SArnaldo Carvalho de Melo 		 *
202dd7927f4SArnaldo Carvalho de Melo 		 * We need to move counter creation to perf_session, support
203dd7927f4SArnaldo Carvalho de Melo 		 * different sample_types, etc.
204dd7927f4SArnaldo Carvalho de Melo 		 */
205dd7927f4SArnaldo Carvalho de Melo 		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
206dd7927f4SArnaldo Carvalho de Melo 
207727ab04eSArnaldo Carvalho de Melo 		if (group && pos != first)
208727ab04eSArnaldo Carvalho de Melo 			group_fd = first->fd;
2099c90a61cSArnaldo Carvalho de Melo retry_sample_id:
210*0f82ebc4SArnaldo Carvalho de Melo 		attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0;
2113da297a6SIngo Molnar try_again:
212727ab04eSArnaldo Carvalho de Melo 		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
213727ab04eSArnaldo Carvalho de Melo 				     group_fd) < 0) {
21486470930SIngo Molnar 			int err = errno;
21586470930SIngo Molnar 
216c286c419SArnaldo Carvalho de Melo 			if (err == EPERM || err == EACCES) {
217b8631e6eSArnaldo Carvalho de Melo 				ui__error_paranoid();
218c286c419SArnaldo Carvalho de Melo 				exit(EXIT_FAILURE);
219*0f82ebc4SArnaldo Carvalho de Melo 			} else if (err ==  ENODEV && record_opts.cpu_list) {
220d6d901c2SZhang, Yanmin 				die("No such device - did you specify"
221d6d901c2SZhang, Yanmin 					" an out-of-range profile CPU?\n");
222*0f82ebc4SArnaldo Carvalho de Melo 			} else if (err == EINVAL && record_opts.sample_id_all_avail) {
2239c90a61cSArnaldo Carvalho de Melo 				/*
2249c90a61cSArnaldo Carvalho de Melo 				 * Old kernel, no attr->sample_id_type_all field
2259c90a61cSArnaldo Carvalho de Melo 				 */
226*0f82ebc4SArnaldo Carvalho de Melo 				record_opts.sample_id_all_avail = false;
227*0f82ebc4SArnaldo Carvalho de Melo 				if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed)
228eac23d1cSIan Munsie 					attr->sample_type &= ~PERF_SAMPLE_TIME;
229eac23d1cSIan Munsie 
2309c90a61cSArnaldo Carvalho de Melo 				goto retry_sample_id;
231d6d901c2SZhang, Yanmin 			}
2323da297a6SIngo Molnar 
2333da297a6SIngo Molnar 			/*
2343da297a6SIngo Molnar 			 * If it's cycles then fall back to hrtimer
2353da297a6SIngo Molnar 			 * based cpu-clock-tick sw counter, which
2363da297a6SIngo Molnar 			 * is always available even if no PMU support:
2373da297a6SIngo Molnar 			 */
2383da297a6SIngo Molnar 			if (attr->type == PERF_TYPE_HARDWARE
239f4dbfa8fSPeter Zijlstra 					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
2403da297a6SIngo Molnar 
2413da297a6SIngo Molnar 				if (verbose)
242ca6a4258SDavid Ahern 					ui__warning("The cycles event is not supported, "
243ca6a4258SDavid Ahern 						    "trying to fall back to cpu-clock-ticks\n");
2443da297a6SIngo Molnar 				attr->type = PERF_TYPE_SOFTWARE;
245f4dbfa8fSPeter Zijlstra 				attr->config = PERF_COUNT_SW_CPU_CLOCK;
2463da297a6SIngo Molnar 				goto try_again;
2473da297a6SIngo Molnar 			}
248ca6a4258SDavid Ahern 
249ca6a4258SDavid Ahern 			if (err == ENOENT) {
250ca6a4258SDavid Ahern 				ui__warning("The %s event is not supported.\n",
251ca6a4258SDavid Ahern 					    event_name(pos));
252ca6a4258SDavid Ahern 				exit(EXIT_FAILURE);
253ca6a4258SDavid Ahern 			}
254ca6a4258SDavid Ahern 
25530c806a0SIngo Molnar 			printf("\n");
256d9cf837eSCorey Ashford 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
257dd7927f4SArnaldo Carvalho de Melo 			      err, strerror(err));
258bfd45118SSimon Kaempflein 
259bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__)
260bfd45118SSimon Kaempflein 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
261d6d901c2SZhang, Yanmin 				die("No hardware sampling interrupt available."
262d6d901c2SZhang, Yanmin 				    " No APIC? If so then you can boot the kernel"
263d6d901c2SZhang, Yanmin 				    " with the \"lapic\" boot parameter to"
264d6d901c2SZhang, Yanmin 				    " force-enable it.\n");
265bfd45118SSimon Kaempflein #endif
266bfd45118SSimon Kaempflein 
267cdd6c482SIngo Molnar 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
2687c6a1c65SPeter Zijlstra 		}
2697c6a1c65SPeter Zijlstra 	}
2707c6a1c65SPeter Zijlstra 
2710a102479SFrederic Weisbecker 	if (perf_evlist__set_filters(evlist)) {
2720a102479SFrederic Weisbecker 		error("failed to set filter with %d (%s)\n", errno,
2730a102479SFrederic Weisbecker 			strerror(errno));
2740a102479SFrederic Weisbecker 		exit(-1);
2750a102479SFrederic Weisbecker 	}
2760a102479SFrederic Weisbecker 
2777e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
2780a27d7f9SArnaldo Carvalho de Melo 		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
2790a27d7f9SArnaldo Carvalho de Melo 
280a91e5431SArnaldo Carvalho de Melo 	if (file_new)
281a91e5431SArnaldo Carvalho de Melo 		session->evlist = evlist;
282a91e5431SArnaldo Carvalho de Melo 	else {
283a91e5431SArnaldo Carvalho de Melo 		if (!perf_evlist__equal(session->evlist, evlist)) {
284a91e5431SArnaldo Carvalho de Melo 			fprintf(stderr, "incompatible append\n");
285a91e5431SArnaldo Carvalho de Melo 			exit(-1);
286dd7927f4SArnaldo Carvalho de Melo 		}
28786470930SIngo Molnar  	}
28886470930SIngo Molnar 
289a91e5431SArnaldo Carvalho de Melo 	perf_session__update_sample_type(session);
290a91e5431SArnaldo Carvalho de Melo }
291a91e5431SArnaldo Carvalho de Melo 
2926122e4e4SArnaldo Carvalho de Melo static int process_buildids(void)
2936122e4e4SArnaldo Carvalho de Melo {
2946122e4e4SArnaldo Carvalho de Melo 	u64 size = lseek(output, 0, SEEK_CUR);
2956122e4e4SArnaldo Carvalho de Melo 
2969f591fd7SArnaldo Carvalho de Melo 	if (size == 0)
2979f591fd7SArnaldo Carvalho de Melo 		return 0;
2989f591fd7SArnaldo Carvalho de Melo 
2996122e4e4SArnaldo Carvalho de Melo 	session->fd = output;
3006122e4e4SArnaldo Carvalho de Melo 	return __perf_session__process_events(session, post_processing_offset,
3016122e4e4SArnaldo Carvalho de Melo 					      size - post_processing_offset,
3026122e4e4SArnaldo Carvalho de Melo 					      size, &build_id__mark_dso_hit_ops);
3036122e4e4SArnaldo Carvalho de Melo }
3046122e4e4SArnaldo Carvalho de Melo 
305f5970550SPeter Zijlstra static void atexit_header(void)
306f5970550SPeter Zijlstra {
307c7929e47STom Zanussi 	if (!pipe_output) {
30894c744b6SArnaldo Carvalho de Melo 		session->header.data_size += bytes_written;
309f5970550SPeter Zijlstra 
310baa2f6ceSArnaldo Carvalho de Melo 		if (!no_buildid)
3116122e4e4SArnaldo Carvalho de Melo 			process_buildids();
312a91e5431SArnaldo Carvalho de Melo 		perf_session__write_header(session, evsel_list, output, true);
31339d17dacSArnaldo Carvalho de Melo 		perf_session__delete(session);
314361c99a6SArnaldo Carvalho de Melo 		perf_evlist__delete(evsel_list);
315d65a458bSArnaldo Carvalho de Melo 		symbol__exit();
316c7929e47STom Zanussi 	}
317f5970550SPeter Zijlstra }
318f5970550SPeter Zijlstra 
3198115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
320a1645ce1SZhang, Yanmin {
321a1645ce1SZhang, Yanmin 	int err;
32223346f21SArnaldo Carvalho de Melo 	struct perf_session *psession = data;
323a1645ce1SZhang, Yanmin 
32423346f21SArnaldo Carvalho de Melo 	if (machine__is_host(machine))
325a1645ce1SZhang, Yanmin 		return;
326a1645ce1SZhang, Yanmin 
327a1645ce1SZhang, Yanmin 	/*
328a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
329a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
330a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
331a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
332a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
333a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
334a1645ce1SZhang, Yanmin 	 */
3358115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
33623346f21SArnaldo Carvalho de Melo 					     psession, machine);
337a1645ce1SZhang, Yanmin 	if (err < 0)
338a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
33923346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
340a1645ce1SZhang, Yanmin 
341a1645ce1SZhang, Yanmin 	/*
342a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
343a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
344a1645ce1SZhang, Yanmin 	 */
3458115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
34623346f21SArnaldo Carvalho de Melo 						 psession, machine, "_text");
347a1645ce1SZhang, Yanmin 	if (err < 0)
3488115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
3498115d60cSArnaldo Carvalho de Melo 							 psession, machine,
3508115d60cSArnaldo Carvalho de Melo 							 "_stext");
351a1645ce1SZhang, Yanmin 	if (err < 0)
352a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
35323346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
354a1645ce1SZhang, Yanmin }
355a1645ce1SZhang, Yanmin 
35698402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
35798402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
35898402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
35998402807SFrederic Weisbecker };
36098402807SFrederic Weisbecker 
36198402807SFrederic Weisbecker static void mmap_read_all(void)
36298402807SFrederic Weisbecker {
3630e2e63ddSPeter Zijlstra 	int i;
36498402807SFrederic Weisbecker 
365aece948fSArnaldo Carvalho de Melo 	for (i = 0; i < evsel_list->nr_mmaps; i++) {
3660a27d7f9SArnaldo Carvalho de Melo 		if (evsel_list->mmap[i].base)
3670a27d7f9SArnaldo Carvalho de Melo 			mmap_read(&evsel_list->mmap[i]);
36898402807SFrederic Weisbecker 	}
36998402807SFrederic Weisbecker 
37098402807SFrederic Weisbecker 	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
37198402807SFrederic Weisbecker 		write_output(&finished_round_event, sizeof(finished_round_event));
37298402807SFrederic Weisbecker }
37398402807SFrederic Weisbecker 
374d4db3f16SArnaldo Carvalho de Melo static int __cmd_record(int argc, const char **argv)
37586470930SIngo Molnar {
37686470930SIngo Molnar 	struct stat st;
37786470930SIngo Molnar 	int flags;
3784dc0a04bSArnaldo Carvalho de Melo 	int err;
3798b412664SPeter Zijlstra 	unsigned long waking = 0;
380856e9660SPeter Zijlstra 	int child_ready_pipe[2], go_pipe[2];
38146be604bSZhang, Yanmin 	const bool forks = argc > 0;
382856e9660SPeter Zijlstra 	char buf;
38323346f21SArnaldo Carvalho de Melo 	struct machine *machine;
38486470930SIngo Molnar 
38533e49ea7SAndi Kleen 	progname = argv[0];
38633e49ea7SAndi Kleen 
38786470930SIngo Molnar 	page_size = sysconf(_SC_PAGE_SIZE);
38886470930SIngo Molnar 
389f5970550SPeter Zijlstra 	atexit(sig_atexit);
390f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
391f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
39218483b81SArnaldo Carvalho de Melo 	signal(SIGUSR1, sig_handler);
393f5970550SPeter Zijlstra 
394d4db3f16SArnaldo Carvalho de Melo 	if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
395856e9660SPeter Zijlstra 		perror("failed to create pipes");
396856e9660SPeter Zijlstra 		exit(-1);
397856e9660SPeter Zijlstra 	}
398856e9660SPeter Zijlstra 
399d7065adbSFranck Bui-Huu 	if (!output_name) {
400d7065adbSFranck Bui-Huu 		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
401*0f82ebc4SArnaldo Carvalho de Melo 			pipe_output = true;
402d7065adbSFranck Bui-Huu 		else
403d7065adbSFranck Bui-Huu 			output_name = "perf.data";
404d7065adbSFranck Bui-Huu 	}
405d7065adbSFranck Bui-Huu 	if (output_name) {
406529870e3STom Zanussi 		if (!strcmp(output_name, "-"))
407*0f82ebc4SArnaldo Carvalho de Melo 			pipe_output = true;
408529870e3STom Zanussi 		else if (!stat(output_name, &st) && st.st_size) {
4097865e817SFrederic Weisbecker 			if (write_mode == WRITE_FORCE) {
410b38d3464SArnaldo Carvalho de Melo 				char oldname[PATH_MAX];
411b38d3464SArnaldo Carvalho de Melo 				snprintf(oldname, sizeof(oldname), "%s.old",
412b38d3464SArnaldo Carvalho de Melo 					 output_name);
413b38d3464SArnaldo Carvalho de Melo 				unlink(oldname);
414b38d3464SArnaldo Carvalho de Melo 				rename(output_name, oldname);
415b38d3464SArnaldo Carvalho de Melo 			}
4167865e817SFrederic Weisbecker 		} else if (write_mode == WRITE_APPEND) {
4177865e817SFrederic Weisbecker 			write_mode = WRITE_FORCE;
418266e0e21SPierre Habouzit 		}
419d7065adbSFranck Bui-Huu 	}
42086470930SIngo Molnar 
421f887f301SXiao Guangrong 	flags = O_CREAT|O_RDWR;
4227865e817SFrederic Weisbecker 	if (write_mode == WRITE_APPEND)
423f5970550SPeter Zijlstra 		file_new = 0;
42486470930SIngo Molnar 	else
42586470930SIngo Molnar 		flags |= O_TRUNC;
42686470930SIngo Molnar 
427529870e3STom Zanussi 	if (pipe_output)
428529870e3STom Zanussi 		output = STDOUT_FILENO;
429529870e3STom Zanussi 	else
43086470930SIngo Molnar 		output = open(output_name, flags, S_IRUSR | S_IWUSR);
43186470930SIngo Molnar 	if (output < 0) {
43286470930SIngo Molnar 		perror("failed to create output file");
43386470930SIngo Molnar 		exit(-1);
43486470930SIngo Molnar 	}
43586470930SIngo Molnar 
4367865e817SFrederic Weisbecker 	session = perf_session__new(output_name, O_WRONLY,
43721ef97f0SIan Munsie 				    write_mode == WRITE_FORCE, false, NULL);
43894c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
439a9a70bbcSArnaldo Carvalho de Melo 		pr_err("Not enough memory for reading perf file header\n");
440a9a70bbcSArnaldo Carvalho de Melo 		return -1;
441a9a70bbcSArnaldo Carvalho de Melo 	}
442a9a70bbcSArnaldo Carvalho de Melo 
443baa2f6ceSArnaldo Carvalho de Melo 	if (!no_buildid)
444baa2f6ceSArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
445baa2f6ceSArnaldo Carvalho de Melo 
4464dc0a04bSArnaldo Carvalho de Melo 	if (!file_new) {
447a91e5431SArnaldo Carvalho de Melo 		err = perf_session__read_header(session, output);
4484dc0a04bSArnaldo Carvalho de Melo 		if (err < 0)
44939d17dacSArnaldo Carvalho de Melo 			goto out_delete_session;
4504dc0a04bSArnaldo Carvalho de Melo 	}
4514dc0a04bSArnaldo Carvalho de Melo 
452361c99a6SArnaldo Carvalho de Melo 	if (have_tracepoints(&evsel_list->entries))
45394c744b6SArnaldo Carvalho de Melo 		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
45403456a15SFrederic Weisbecker 
455fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_HOSTNAME);
456fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_OSRELEASE);
457fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_ARCH);
458fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_CPUDESC);
459fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_NRCPUS);
460fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
461fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_CMDLINE);
462fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_VERSION);
463fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
464fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
465fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
466fbe96f29SStephane Eranian 	perf_header__set_feat(&session->header, HEADER_CPUID);
467fbe96f29SStephane Eranian 
468800cd25cSFrederic Weisbecker 	/* 512 kiB: default amount of unprivileged mlocked memory */
469800cd25cSFrederic Weisbecker 	if (mmap_pages == UINT_MAX)
470800cd25cSFrederic Weisbecker 		mmap_pages = (512 * 1024) / page_size;
471800cd25cSFrederic Weisbecker 
472d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
47346be604bSZhang, Yanmin 		child_pid = fork();
4742fb750e8SBorislav Petkov 		if (child_pid < 0) {
475856e9660SPeter Zijlstra 			perror("failed to fork");
476856e9660SPeter Zijlstra 			exit(-1);
477856e9660SPeter Zijlstra 		}
4787c6a1c65SPeter Zijlstra 
47946be604bSZhang, Yanmin 		if (!child_pid) {
480529870e3STom Zanussi 			if (pipe_output)
481529870e3STom Zanussi 				dup2(2, 1);
482856e9660SPeter Zijlstra 			close(child_ready_pipe[0]);
483856e9660SPeter Zijlstra 			close(go_pipe[1]);
484856e9660SPeter Zijlstra 			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
485856e9660SPeter Zijlstra 
486856e9660SPeter Zijlstra 			/*
487856e9660SPeter Zijlstra 			 * Do a dummy execvp to get the PLT entry resolved,
488856e9660SPeter Zijlstra 			 * so we avoid the resolver overhead on the real
489856e9660SPeter Zijlstra 			 * execvp call.
490856e9660SPeter Zijlstra 			 */
491856e9660SPeter Zijlstra 			execvp("", (char **)argv);
492856e9660SPeter Zijlstra 
493856e9660SPeter Zijlstra 			/*
494856e9660SPeter Zijlstra 			 * Tell the parent we're ready to go
495856e9660SPeter Zijlstra 			 */
496856e9660SPeter Zijlstra 			close(child_ready_pipe[1]);
497856e9660SPeter Zijlstra 
498856e9660SPeter Zijlstra 			/*
499856e9660SPeter Zijlstra 			 * Wait until the parent tells us to go.
500856e9660SPeter Zijlstra 			 */
501856e9660SPeter Zijlstra 			if (read(go_pipe[0], &buf, 1) == -1)
502856e9660SPeter Zijlstra 				perror("unable to read pipe");
503856e9660SPeter Zijlstra 
504856e9660SPeter Zijlstra 			execvp(argv[0], (char **)argv);
505856e9660SPeter Zijlstra 
506856e9660SPeter Zijlstra 			perror(argv[0]);
50718483b81SArnaldo Carvalho de Melo 			kill(getppid(), SIGUSR1);
508856e9660SPeter Zijlstra 			exit(-1);
509856e9660SPeter Zijlstra 		}
510856e9660SPeter Zijlstra 
511*0f82ebc4SArnaldo Carvalho de Melo 		if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1)
5127e2ed097SArnaldo Carvalho de Melo 			evsel_list->threads->map[0] = child_pid;
513d6d901c2SZhang, Yanmin 
514856e9660SPeter Zijlstra 		close(child_ready_pipe[1]);
515856e9660SPeter Zijlstra 		close(go_pipe[0]);
516856e9660SPeter Zijlstra 		/*
517856e9660SPeter Zijlstra 		 * wait for child to settle
518856e9660SPeter Zijlstra 		 */
519856e9660SPeter Zijlstra 		if (read(child_ready_pipe[0], &buf, 1) == -1) {
520856e9660SPeter Zijlstra 			perror("unable to read pipe");
521856e9660SPeter Zijlstra 			exit(-1);
522856e9660SPeter Zijlstra 		}
523856e9660SPeter Zijlstra 		close(child_ready_pipe[0]);
524856e9660SPeter Zijlstra 	}
525856e9660SPeter Zijlstra 
526dd7927f4SArnaldo Carvalho de Melo 	open_counters(evsel_list);
52786470930SIngo Molnar 
528712a4b60SArnaldo Carvalho de Melo 	/*
529712a4b60SArnaldo Carvalho de Melo 	 * perf_session__delete(session) will be called at atexit_header()
530712a4b60SArnaldo Carvalho de Melo 	 */
531712a4b60SArnaldo Carvalho de Melo 	atexit(atexit_header);
532712a4b60SArnaldo Carvalho de Melo 
533529870e3STom Zanussi 	if (pipe_output) {
534529870e3STom Zanussi 		err = perf_header__write_pipe(output);
535529870e3STom Zanussi 		if (err < 0)
536529870e3STom Zanussi 			return err;
537529870e3STom Zanussi 	} else if (file_new) {
538a91e5431SArnaldo Carvalho de Melo 		err = perf_session__write_header(session, evsel_list,
539361c99a6SArnaldo Carvalho de Melo 						 output, false);
540d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
541d5eed904SArnaldo Carvalho de Melo 			return err;
542d5eed904SArnaldo Carvalho de Melo 	}
5437c6a1c65SPeter Zijlstra 
5446122e4e4SArnaldo Carvalho de Melo 	post_processing_offset = lseek(output, 0, SEEK_CUR);
5456122e4e4SArnaldo Carvalho de Melo 
5462c46dbb5STom Zanussi 	if (pipe_output) {
547a91e5431SArnaldo Carvalho de Melo 		err = perf_session__synthesize_attrs(session,
548a91e5431SArnaldo Carvalho de Melo 						     process_synthesized_event);
5492c46dbb5STom Zanussi 		if (err < 0) {
5502c46dbb5STom Zanussi 			pr_err("Couldn't synthesize attrs.\n");
5512c46dbb5STom Zanussi 			return err;
5522c46dbb5STom Zanussi 		}
553cd19a035STom Zanussi 
5548115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_event_types(process_synthesized_event,
555cd19a035STom Zanussi 							 session);
556cd19a035STom Zanussi 		if (err < 0) {
557cd19a035STom Zanussi 			pr_err("Couldn't synthesize event_types.\n");
558cd19a035STom Zanussi 			return err;
559cd19a035STom Zanussi 		}
5609215545eSTom Zanussi 
561361c99a6SArnaldo Carvalho de Melo 		if (have_tracepoints(&evsel_list->entries)) {
56263e0c771STom Zanussi 			/*
56363e0c771STom Zanussi 			 * FIXME err <= 0 here actually means that
56463e0c771STom Zanussi 			 * there were no tracepoints so its not really
56563e0c771STom Zanussi 			 * an error, just that we don't need to
56663e0c771STom Zanussi 			 * synthesize anything.  We really have to
56763e0c771STom Zanussi 			 * return this more properly and also
56863e0c771STom Zanussi 			 * propagate errors that now are calling die()
56963e0c771STom Zanussi 			 */
5708115d60cSArnaldo Carvalho de Melo 			err = perf_event__synthesize_tracing_data(output, evsel_list,
5719215545eSTom Zanussi 								  process_synthesized_event,
5729215545eSTom Zanussi 								  session);
57363e0c771STom Zanussi 			if (err <= 0) {
57463e0c771STom Zanussi 				pr_err("Couldn't record tracing data.\n");
57563e0c771STom Zanussi 				return err;
57663e0c771STom Zanussi 			}
5779215545eSTom Zanussi 			advance_output(err);
5782c46dbb5STom Zanussi 		}
57963e0c771STom Zanussi 	}
5802c46dbb5STom Zanussi 
58123346f21SArnaldo Carvalho de Melo 	machine = perf_session__find_host_machine(session);
58223346f21SArnaldo Carvalho de Melo 	if (!machine) {
583a1645ce1SZhang, Yanmin 		pr_err("Couldn't find native kernel information.\n");
584a1645ce1SZhang, Yanmin 		return -1;
585a1645ce1SZhang, Yanmin 	}
586a1645ce1SZhang, Yanmin 
5878115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
58823346f21SArnaldo Carvalho de Melo 						 session, machine, "_text");
58970162138SArnaldo Carvalho de Melo 	if (err < 0)
5908115d60cSArnaldo Carvalho de Melo 		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
59123346f21SArnaldo Carvalho de Melo 							 session, machine, "_stext");
592c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
593c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel reference relocation symbol\n"
594c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
595c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/kallsyms permission or run as root.\n");
59656b03f3cSArnaldo Carvalho de Melo 
5978115d60cSArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(process_synthesized_event,
59823346f21SArnaldo Carvalho de Melo 					     session, machine);
599c1a3a4b9SArnaldo Carvalho de Melo 	if (err < 0)
600c1a3a4b9SArnaldo Carvalho de Melo 		pr_err("Couldn't record kernel module information.\n"
601c1a3a4b9SArnaldo Carvalho de Melo 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
602c1a3a4b9SArnaldo Carvalho de Melo 		       "Check /proc/modules permission or run as root.\n");
603c1a3a4b9SArnaldo Carvalho de Melo 
604a1645ce1SZhang, Yanmin 	if (perf_guest)
6058115d60cSArnaldo Carvalho de Melo 		perf_session__process_machines(session,
6068115d60cSArnaldo Carvalho de Melo 					       perf_event__synthesize_guest_os);
607b7cece76SArnaldo Carvalho de Melo 
608*0f82ebc4SArnaldo Carvalho de Melo 	if (!record_opts.system_wide)
6097c940c18SArnaldo Carvalho de Melo 		perf_event__synthesize_thread_map(evsel_list->threads,
6108115d60cSArnaldo Carvalho de Melo 						  process_synthesized_event,
611d8f66248SArnaldo Carvalho de Melo 						  session);
612234fbbf5SArnaldo Carvalho de Melo 	else
6138115d60cSArnaldo Carvalho de Melo 		perf_event__synthesize_threads(process_synthesized_event,
6148115d60cSArnaldo Carvalho de Melo 					       session);
6157c6a1c65SPeter Zijlstra 
61686470930SIngo Molnar 	if (realtime_prio) {
61786470930SIngo Molnar 		struct sched_param param;
61886470930SIngo Molnar 
61986470930SIngo Molnar 		param.sched_priority = realtime_prio;
62086470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
6216beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
62286470930SIngo Molnar 			exit(-1);
62386470930SIngo Molnar 		}
62486470930SIngo Molnar 	}
62586470930SIngo Molnar 
626764e16a3SDavid Ahern 	perf_evlist__enable(evsel_list);
627764e16a3SDavid Ahern 
628856e9660SPeter Zijlstra 	/*
629856e9660SPeter Zijlstra 	 * Let the child rip
630856e9660SPeter Zijlstra 	 */
631d4db3f16SArnaldo Carvalho de Melo 	if (forks)
632856e9660SPeter Zijlstra 		close(go_pipe[1]);
633856e9660SPeter Zijlstra 
634649c48a9SPeter Zijlstra 	for (;;) {
63586470930SIngo Molnar 		int hits = samples;
63686470930SIngo Molnar 
63798402807SFrederic Weisbecker 		mmap_read_all();
63886470930SIngo Molnar 
639649c48a9SPeter Zijlstra 		if (hits == samples) {
640649c48a9SPeter Zijlstra 			if (done)
641649c48a9SPeter Zijlstra 				break;
6425c581041SArnaldo Carvalho de Melo 			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
6438b412664SPeter Zijlstra 			waking++;
6448b412664SPeter Zijlstra 		}
6458b412664SPeter Zijlstra 
6464152ab37SArnaldo Carvalho de Melo 		if (done)
6474152ab37SArnaldo Carvalho de Melo 			perf_evlist__disable(evsel_list);
6488b412664SPeter Zijlstra 	}
6498b412664SPeter Zijlstra 
65018483b81SArnaldo Carvalho de Melo 	if (quiet || signr == SIGUSR1)
651b44308f5SArnaldo Carvalho de Melo 		return 0;
652b44308f5SArnaldo Carvalho de Melo 
6538b412664SPeter Zijlstra 	fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
65486470930SIngo Molnar 
65586470930SIngo Molnar 	/*
65686470930SIngo Molnar 	 * Approximate RIP event size: 24 bytes.
65786470930SIngo Molnar 	 */
65886470930SIngo Molnar 	fprintf(stderr,
6599486aa38SArnaldo Carvalho de Melo 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
66086470930SIngo Molnar 		(double)bytes_written / 1024.0 / 1024.0,
66186470930SIngo Molnar 		output_name,
66286470930SIngo Molnar 		bytes_written / 24);
66386470930SIngo Molnar 
66486470930SIngo Molnar 	return 0;
66539d17dacSArnaldo Carvalho de Melo 
66639d17dacSArnaldo Carvalho de Melo out_delete_session:
66739d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
66839d17dacSArnaldo Carvalho de Melo 	return err;
66986470930SIngo Molnar }
67086470930SIngo Molnar 
67186470930SIngo Molnar static const char * const record_usage[] = {
67286470930SIngo Molnar 	"perf record [<options>] [<command>]",
67386470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
67486470930SIngo Molnar 	NULL
67586470930SIngo Molnar };
67686470930SIngo Molnar 
6777865e817SFrederic Weisbecker static bool force, append_file;
6787865e817SFrederic Weisbecker 
679bca647aaSTom Zanussi const struct option record_options[] = {
680361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &evsel_list, "event",
68186470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
682f120f9d5SJiri Olsa 		     parse_events_option),
683361c99a6SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
684c171b552SLi Zefan 		     "event filter", parse_filter),
685*0f82ebc4SArnaldo Carvalho de Melo 	OPT_INTEGER('p', "pid", &record_opts.target_pid,
686d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
687*0f82ebc4SArnaldo Carvalho de Melo 	OPT_INTEGER('t', "tid", &record_opts.target_tid,
688d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
68986470930SIngo Molnar 	OPT_INTEGER('r', "realtime", &realtime_prio,
69086470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
691*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('D', "no-delay", &record_opts.no_delay,
692acac03faSKirill Smelkov 		    "collect data without buffering"),
693*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record_opts.raw_samples,
694daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
695*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('a', "all-cpus", &record_opts.system_wide,
69686470930SIngo Molnar 			    "system-wide collection from all CPUs"),
69786470930SIngo Molnar 	OPT_BOOLEAN('A', "append", &append_file,
69886470930SIngo Molnar 			    "append to the output file to do incremental profiling"),
699*0f82ebc4SArnaldo Carvalho de Melo 	OPT_STRING('C', "cpu", &record_opts.cpu_list, "cpu",
700c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
70186470930SIngo Molnar 	OPT_BOOLEAN('f', "force", &force,
7027865e817SFrederic Weisbecker 			"overwrite existing data file (deprecated)"),
703*0f82ebc4SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record_opts.user_interval, "event period to sample"),
70486470930SIngo Molnar 	OPT_STRING('o', "output", &output_name, "file",
70586470930SIngo Molnar 		    "output file name"),
706*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit,
7072e6cdf99SStephane Eranian 		    "child tasks do not inherit counters"),
708*0f82ebc4SArnaldo Carvalho de Melo 	OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"),
7091967936dSArnaldo Carvalho de Melo 	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
71043bece79SLin Ming 	OPT_BOOLEAN(0, "group", &group,
71143bece79SLin Ming 		    "put the counters into a counter group"),
712*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph,
7133efa1cc9SIngo Molnar 		    "do call-graph (stack chain/backtrace) recording"),
714c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
7153da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
716b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
717*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record_opts.inherit_stat,
718649c48a9SPeter Zijlstra 		    "per thread counts"),
719*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('d', "data", &record_opts.sample_address,
7204bba828dSAnton Blanchard 		    "Sample addresses"),
721*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('T', "timestamp", &record_opts.sample_time, "Sample timestamps"),
722*0f82ebc4SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record_opts.no_samples,
723649c48a9SPeter Zijlstra 		    "don't sample"),
724baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
725a1ac1d3cSStephane Eranian 		    "do not update the buildid cache"),
726baa2f6ceSArnaldo Carvalho de Melo 	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
727baa2f6ceSArnaldo Carvalho de Melo 		    "do not collect buildids in perf.data"),
728023695d9SStephane Eranian 	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
729023695d9SStephane Eranian 		     "monitor event in cgroup name only",
730023695d9SStephane Eranian 		     parse_cgroups),
73186470930SIngo Molnar 	OPT_END()
73286470930SIngo Molnar };
73386470930SIngo Molnar 
734f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used)
73586470930SIngo Molnar {
73669aad6f1SArnaldo Carvalho de Melo 	int err = -ENOMEM;
73769aad6f1SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
73886470930SIngo Molnar 
739fbe96f29SStephane Eranian 	perf_header__set_cmdline(argc, argv);
740fbe96f29SStephane Eranian 
7417e2ed097SArnaldo Carvalho de Melo 	evsel_list = perf_evlist__new(NULL, NULL);
742361c99a6SArnaldo Carvalho de Melo 	if (evsel_list == NULL)
743361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
744361c99a6SArnaldo Carvalho de Melo 
745bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
746a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
747*0f82ebc4SArnaldo Carvalho de Melo 	if (!argc && record_opts.target_pid == -1 && record_opts.target_tid == -1 &&
748*0f82ebc4SArnaldo Carvalho de Melo 		!record_opts.system_wide && !record_opts.cpu_list)
749bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
75086470930SIngo Molnar 
7517865e817SFrederic Weisbecker 	if (force && append_file) {
7527865e817SFrederic Weisbecker 		fprintf(stderr, "Can't overwrite and append at the same time."
7537865e817SFrederic Weisbecker 				" You need to choose between -f and -A");
754bca647aaSTom Zanussi 		usage_with_options(record_usage, record_options);
7557865e817SFrederic Weisbecker 	} else if (append_file) {
7567865e817SFrederic Weisbecker 		write_mode = WRITE_APPEND;
7577865e817SFrederic Weisbecker 	} else {
7587865e817SFrederic Weisbecker 		write_mode = WRITE_FORCE;
7597865e817SFrederic Weisbecker 	}
7607865e817SFrederic Weisbecker 
761*0f82ebc4SArnaldo Carvalho de Melo 	if (nr_cgroups && !record_opts.system_wide) {
762023695d9SStephane Eranian 		fprintf(stderr, "cgroup monitoring only available in"
763023695d9SStephane Eranian 			" system-wide mode\n");
764023695d9SStephane Eranian 		usage_with_options(record_usage, record_options);
765023695d9SStephane Eranian 	}
766023695d9SStephane Eranian 
767655000e7SArnaldo Carvalho de Melo 	symbol__init();
768baa2f6ceSArnaldo Carvalho de Melo 
769ec80fde7SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict)
770646aaea6SArnaldo Carvalho de Melo 		pr_warning(
771646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
772ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
773646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
774646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
775646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
776646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
777646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
778ec80fde7SArnaldo Carvalho de Melo 
779baa2f6ceSArnaldo Carvalho de Melo 	if (no_buildid_cache || no_buildid)
780a1ac1d3cSStephane Eranian 		disable_buildid_cache();
781655000e7SArnaldo Carvalho de Melo 
782361c99a6SArnaldo Carvalho de Melo 	if (evsel_list->nr_entries == 0 &&
783361c99a6SArnaldo Carvalho de Melo 	    perf_evlist__add_default(evsel_list) < 0) {
78469aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
78569aad6f1SArnaldo Carvalho de Melo 		goto out_symbol_exit;
786bbd36e5eSPeter Zijlstra 	}
78786470930SIngo Molnar 
788*0f82ebc4SArnaldo Carvalho de Melo 	if (record_opts.target_pid != -1)
789*0f82ebc4SArnaldo Carvalho de Melo 		record_opts.target_tid = record_opts.target_pid;
790d6d901c2SZhang, Yanmin 
791*0f82ebc4SArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(evsel_list, record_opts.target_pid,
792*0f82ebc4SArnaldo Carvalho de Melo 				     record_opts.target_tid, record_opts.cpu_list) < 0)
793dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
79469aad6f1SArnaldo Carvalho de Melo 
795361c99a6SArnaldo Carvalho de Melo 	list_for_each_entry(pos, &evsel_list->entries, node) {
7967e2ed097SArnaldo Carvalho de Melo 		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
7977e2ed097SArnaldo Carvalho de Melo 					 evsel_list->threads->nr) < 0)
79869aad6f1SArnaldo Carvalho de Melo 			goto out_free_fd;
799ad7f4e3fSArnaldo Carvalho de Melo 		if (perf_header__push_event(pos->attr.config, event_name(pos)))
800ad7f4e3fSArnaldo Carvalho de Melo 			goto out_free_fd;
801d6d901c2SZhang, Yanmin 	}
8025c581041SArnaldo Carvalho de Melo 
8037e2ed097SArnaldo Carvalho de Melo 	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
80439d17dacSArnaldo Carvalho de Melo 		goto out_free_fd;
805d6d901c2SZhang, Yanmin 
806*0f82ebc4SArnaldo Carvalho de Melo 	if (record_opts.user_interval != ULLONG_MAX)
807*0f82ebc4SArnaldo Carvalho de Melo 		record_opts.default_interval = record_opts.user_interval;
808*0f82ebc4SArnaldo Carvalho de Melo 	if (record_opts.user_freq != UINT_MAX)
809*0f82ebc4SArnaldo Carvalho de Melo 		record_opts.freq = record_opts.user_freq;
810f9212819SFrederic Weisbecker 
8117e4ff9e3SMike Galbraith 	/*
8127e4ff9e3SMike Galbraith 	 * User specified count overrides default frequency.
8137e4ff9e3SMike Galbraith 	 */
814*0f82ebc4SArnaldo Carvalho de Melo 	if (record_opts.default_interval)
815*0f82ebc4SArnaldo Carvalho de Melo 		record_opts.freq = 0;
816*0f82ebc4SArnaldo Carvalho de Melo 	else if (record_opts.freq) {
817*0f82ebc4SArnaldo Carvalho de Melo 		record_opts.default_interval = record_opts.freq;
8187e4ff9e3SMike Galbraith 	} else {
8197e4ff9e3SMike Galbraith 		fprintf(stderr, "frequency and count are zero, aborting\n");
82039d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
8215c581041SArnaldo Carvalho de Melo 		goto out_free_fd;
8227e4ff9e3SMike Galbraith 	}
8237e4ff9e3SMike Galbraith 
82439d17dacSArnaldo Carvalho de Melo 	err = __cmd_record(argc, argv);
82539d17dacSArnaldo Carvalho de Melo out_free_fd:
8267e2ed097SArnaldo Carvalho de Melo 	perf_evlist__delete_maps(evsel_list);
827d65a458bSArnaldo Carvalho de Melo out_symbol_exit:
828d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
82939d17dacSArnaldo Carvalho de Melo 	return err;
83086470930SIngo Molnar }
831