xref: /openbmc/linux/tools/perf/builtin-record.c (revision 5d7f41164930ecc1797702b7f9728ac702609ef3)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
286470930SIngo Molnar /*
386470930SIngo Molnar  * builtin-record.c
486470930SIngo Molnar  *
586470930SIngo Molnar  * Builtin record command: Record the profile of a workload
686470930SIngo Molnar  * (or a CPU, or a PID) into the perf.data output file - for
786470930SIngo Molnar  * later analysis via perf report.
886470930SIngo Molnar  */
986470930SIngo Molnar #include "builtin.h"
1086470930SIngo Molnar 
1186470930SIngo Molnar #include "perf.h"
1286470930SIngo Molnar 
136122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h"
1486470930SIngo Molnar #include "util/util.h"
154b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
1686470930SIngo Molnar #include "util/parse-events.h"
1741840d21STaeung Song #include "util/config.h"
1886470930SIngo Molnar 
198f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h"
20f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h"
217c6a1c65SPeter Zijlstra #include "util/header.h"
2266e274f3SFrederic Weisbecker #include "util/event.h"
23361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h"
2469aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h"
258f28827aSFrederic Weisbecker #include "util/debug.h"
2694c744b6SArnaldo Carvalho de Melo #include "util/session.h"
2745694aa7SArnaldo Carvalho de Melo #include "util/tool.h"
288d06367fSArnaldo Carvalho de Melo #include "util/symbol.h"
29a12b51c4SPaul Mackerras #include "util/cpumap.h"
30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h"
31f5fc1412SJiri Olsa #include "util/data.h"
32bcc84ec6SStephane Eranian #include "util/perf_regs.h"
33ef149c25SAdrian Hunter #include "util/auxtrace.h"
3446bc29b9SAdrian Hunter #include "util/tsc.h"
35f00898f4SAndi Kleen #include "util/parse-branch-options.h"
36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
3771dc2326SWang Nan #include "util/llvm-utils.h"
388690a2a7SWang Nan #include "util/bpf-loader.h"
395f9cf599SWang Nan #include "util/trigger.h"
40a074865eSWang Nan #include "util/perf-hooks.h"
41f13de660SAlexey Budankov #include "util/cpu-set-sched.h"
42c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h"
4358db1d6eSArnaldo Carvalho de Melo #include "util/units.h"
447b612e29SSong Liu #include "util/bpf-event.h"
45d8871ea7SWang Nan #include "asm/bug.h"
467c6a1c65SPeter Zijlstra 
47a43783aeSArnaldo Carvalho de Melo #include <errno.h>
48fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
4967230479SArnaldo Carvalho de Melo #include <locale.h>
504208735dSArnaldo Carvalho de Melo #include <poll.h>
5186470930SIngo Molnar #include <unistd.h>
5286470930SIngo Molnar #include <sched.h>
539607ad3aSArnaldo Carvalho de Melo #include <signal.h>
54a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h>
554208735dSArnaldo Carvalho de Melo #include <sys/wait.h>
560693e680SArnaldo Carvalho de Melo #include <linux/time64.h>
5778da39faSBernhard Rosenkraenzer 
581b43b704SJiri Olsa struct switch_output {
59dc0c6127SJiri Olsa 	bool		 enabled;
601b43b704SJiri Olsa 	bool		 signal;
61dc0c6127SJiri Olsa 	unsigned long	 size;
62bfacbe3bSJiri Olsa 	unsigned long	 time;
63cb4e1ebbSJiri Olsa 	const char	*str;
64cb4e1ebbSJiri Olsa 	bool		 set;
6503724b2eSAndi Kleen 	char		 **filenames;
6603724b2eSAndi Kleen 	int		 num_files;
6703724b2eSAndi Kleen 	int		 cur_file;
681b43b704SJiri Olsa };
691b43b704SJiri Olsa 
708c6f45a7SArnaldo Carvalho de Melo struct record {
7145694aa7SArnaldo Carvalho de Melo 	struct perf_tool	tool;
72b4006796SArnaldo Carvalho de Melo 	struct record_opts	opts;
73d20deb64SArnaldo Carvalho de Melo 	u64			bytes_written;
748ceb41d7SJiri Olsa 	struct perf_data	data;
75ef149c25SAdrian Hunter 	struct auxtrace_record	*itr;
76d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist	*evlist;
77d20deb64SArnaldo Carvalho de Melo 	struct perf_session	*session;
78d20deb64SArnaldo Carvalho de Melo 	int			realtime_prio;
79d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid;
80d2db9a98SWang Nan 	bool			no_buildid_set;
81d20deb64SArnaldo Carvalho de Melo 	bool			no_buildid_cache;
82d2db9a98SWang Nan 	bool			no_buildid_cache_set;
836156681bSNamhyung Kim 	bool			buildid_all;
84ecfd7a9cSWang Nan 	bool			timestamp_filename;
8568588bafSJin Yao 	bool			timestamp_boundary;
861b43b704SJiri Olsa 	struct switch_output	switch_output;
879f065194SYang Shi 	unsigned long long	samples;
889d2ed645SAlexey Budankov 	cpu_set_t		affinity_mask;
890f82ebc4SArnaldo Carvalho de Melo };
9086470930SIngo Molnar 
91dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started;
92dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
93dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger);
94dc0c6127SJiri Olsa 
959d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = {
969d2ed645SAlexey Budankov 	"SYS", "NODE", "CPU"
979d2ed645SAlexey Budankov };
989d2ed645SAlexey Budankov 
99dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec)
100dc0c6127SJiri Olsa {
101dc0c6127SJiri Olsa 	return rec->switch_output.signal &&
102dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
103dc0c6127SJiri Olsa }
104dc0c6127SJiri Olsa 
105dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec)
106dc0c6127SJiri Olsa {
107dc0c6127SJiri Olsa 	return rec->switch_output.size &&
108dc0c6127SJiri Olsa 	       trigger_is_ready(&switch_output_trigger) &&
109dc0c6127SJiri Olsa 	       (rec->bytes_written >= rec->switch_output.size);
110dc0c6127SJiri Olsa }
111dc0c6127SJiri Olsa 
112bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec)
113bfacbe3bSJiri Olsa {
114bfacbe3bSJiri Olsa 	return rec->switch_output.time &&
115bfacbe3bSJiri Olsa 	       trigger_is_ready(&switch_output_trigger);
116bfacbe3bSJiri Olsa }
117bfacbe3bSJiri Olsa 
118ded2b8feSJiri Olsa static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
119ded2b8feSJiri Olsa 			 void *bf, size_t size)
120f5970550SPeter Zijlstra {
121ded2b8feSJiri Olsa 	struct perf_data_file *file = &rec->session->data->file;
122ded2b8feSJiri Olsa 
123ded2b8feSJiri Olsa 	if (perf_data_file__write(file, bf, size) < 0) {
1244f624685SAdrian Hunter 		pr_err("failed to write perf data, error: %m\n");
1258d3eca20SDavid Ahern 		return -1;
1268d3eca20SDavid Ahern 	}
127f5970550SPeter Zijlstra 
128cf8b2e69SArnaldo Carvalho de Melo 	rec->bytes_written += size;
129dc0c6127SJiri Olsa 
130dc0c6127SJiri Olsa 	if (switch_output_size(rec))
131dc0c6127SJiri Olsa 		trigger_hit(&switch_output_trigger);
132dc0c6127SJiri Olsa 
1338d3eca20SDavid Ahern 	return 0;
134f5970550SPeter Zijlstra }
135f5970550SPeter Zijlstra 
136*5d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
137*5d7f4116SAlexey Budankov 			    void *src, size_t src_size);
138*5d7f4116SAlexey Budankov 
139d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
140d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd,
141d3d1af6fSAlexey Budankov 		void *buf, size_t size, off_t off)
142d3d1af6fSAlexey Budankov {
143d3d1af6fSAlexey Budankov 	int rc;
144d3d1af6fSAlexey Budankov 
145d3d1af6fSAlexey Budankov 	cblock->aio_fildes = trace_fd;
146d3d1af6fSAlexey Budankov 	cblock->aio_buf    = buf;
147d3d1af6fSAlexey Budankov 	cblock->aio_nbytes = size;
148d3d1af6fSAlexey Budankov 	cblock->aio_offset = off;
149d3d1af6fSAlexey Budankov 	cblock->aio_sigevent.sigev_notify = SIGEV_NONE;
150d3d1af6fSAlexey Budankov 
151d3d1af6fSAlexey Budankov 	do {
152d3d1af6fSAlexey Budankov 		rc = aio_write(cblock);
153d3d1af6fSAlexey Budankov 		if (rc == 0) {
154d3d1af6fSAlexey Budankov 			break;
155d3d1af6fSAlexey Budankov 		} else if (errno != EAGAIN) {
156d3d1af6fSAlexey Budankov 			cblock->aio_fildes = -1;
157d3d1af6fSAlexey Budankov 			pr_err("failed to queue perf data, error: %m\n");
158d3d1af6fSAlexey Budankov 			break;
159d3d1af6fSAlexey Budankov 		}
160d3d1af6fSAlexey Budankov 	} while (1);
161d3d1af6fSAlexey Budankov 
162d3d1af6fSAlexey Budankov 	return rc;
163d3d1af6fSAlexey Budankov }
164d3d1af6fSAlexey Budankov 
165d3d1af6fSAlexey Budankov static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock)
166d3d1af6fSAlexey Budankov {
167d3d1af6fSAlexey Budankov 	void *rem_buf;
168d3d1af6fSAlexey Budankov 	off_t rem_off;
169d3d1af6fSAlexey Budankov 	size_t rem_size;
170d3d1af6fSAlexey Budankov 	int rc, aio_errno;
171d3d1af6fSAlexey Budankov 	ssize_t aio_ret, written;
172d3d1af6fSAlexey Budankov 
173d3d1af6fSAlexey Budankov 	aio_errno = aio_error(cblock);
174d3d1af6fSAlexey Budankov 	if (aio_errno == EINPROGRESS)
175d3d1af6fSAlexey Budankov 		return 0;
176d3d1af6fSAlexey Budankov 
177d3d1af6fSAlexey Budankov 	written = aio_ret = aio_return(cblock);
178d3d1af6fSAlexey Budankov 	if (aio_ret < 0) {
179d3d1af6fSAlexey Budankov 		if (aio_errno != EINTR)
180d3d1af6fSAlexey Budankov 			pr_err("failed to write perf data, error: %m\n");
181d3d1af6fSAlexey Budankov 		written = 0;
182d3d1af6fSAlexey Budankov 	}
183d3d1af6fSAlexey Budankov 
184d3d1af6fSAlexey Budankov 	rem_size = cblock->aio_nbytes - written;
185d3d1af6fSAlexey Budankov 
186d3d1af6fSAlexey Budankov 	if (rem_size == 0) {
187d3d1af6fSAlexey Budankov 		cblock->aio_fildes = -1;
188d3d1af6fSAlexey Budankov 		/*
189d3d1af6fSAlexey Budankov 		 * md->refcount is incremented in perf_mmap__push() for
190d3d1af6fSAlexey Budankov 		 * every enqueued aio write request so decrement it because
191d3d1af6fSAlexey Budankov 		 * the request is now complete.
192d3d1af6fSAlexey Budankov 		 */
193d3d1af6fSAlexey Budankov 		perf_mmap__put(md);
194d3d1af6fSAlexey Budankov 		rc = 1;
195d3d1af6fSAlexey Budankov 	} else {
196d3d1af6fSAlexey Budankov 		/*
197d3d1af6fSAlexey Budankov 		 * aio write request may require restart with the
198d3d1af6fSAlexey Budankov 		 * reminder if the kernel didn't write whole
199d3d1af6fSAlexey Budankov 		 * chunk at once.
200d3d1af6fSAlexey Budankov 		 */
201d3d1af6fSAlexey Budankov 		rem_off = cblock->aio_offset + written;
202d3d1af6fSAlexey Budankov 		rem_buf = (void *)(cblock->aio_buf + written);
203d3d1af6fSAlexey Budankov 		record__aio_write(cblock, cblock->aio_fildes,
204d3d1af6fSAlexey Budankov 				rem_buf, rem_size, rem_off);
205d3d1af6fSAlexey Budankov 		rc = 0;
206d3d1af6fSAlexey Budankov 	}
207d3d1af6fSAlexey Budankov 
208d3d1af6fSAlexey Budankov 	return rc;
209d3d1af6fSAlexey Budankov }
210d3d1af6fSAlexey Budankov 
21193f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md, bool sync_all)
212d3d1af6fSAlexey Budankov {
21393f20c0fSAlexey Budankov 	struct aiocb **aiocb = md->aio.aiocb;
21493f20c0fSAlexey Budankov 	struct aiocb *cblocks = md->aio.cblocks;
215d3d1af6fSAlexey Budankov 	struct timespec timeout = { 0, 1000 * 1000  * 1 }; /* 1ms */
21693f20c0fSAlexey Budankov 	int i, do_suspend;
217d3d1af6fSAlexey Budankov 
218d3d1af6fSAlexey Budankov 	do {
21993f20c0fSAlexey Budankov 		do_suspend = 0;
22093f20c0fSAlexey Budankov 		for (i = 0; i < md->aio.nr_cblocks; ++i) {
22193f20c0fSAlexey Budankov 			if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) {
22293f20c0fSAlexey Budankov 				if (sync_all)
22393f20c0fSAlexey Budankov 					aiocb[i] = NULL;
22493f20c0fSAlexey Budankov 				else
22593f20c0fSAlexey Budankov 					return i;
22693f20c0fSAlexey Budankov 			} else {
22793f20c0fSAlexey Budankov 				/*
22893f20c0fSAlexey Budankov 				 * Started aio write is not complete yet
22993f20c0fSAlexey Budankov 				 * so it has to be waited before the
23093f20c0fSAlexey Budankov 				 * next allocation.
23193f20c0fSAlexey Budankov 				 */
23293f20c0fSAlexey Budankov 				aiocb[i] = &cblocks[i];
23393f20c0fSAlexey Budankov 				do_suspend = 1;
23493f20c0fSAlexey Budankov 			}
23593f20c0fSAlexey Budankov 		}
23693f20c0fSAlexey Budankov 		if (!do_suspend)
23793f20c0fSAlexey Budankov 			return -1;
238d3d1af6fSAlexey Budankov 
23993f20c0fSAlexey Budankov 		while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) {
240d3d1af6fSAlexey Budankov 			if (!(errno == EAGAIN || errno == EINTR))
241d3d1af6fSAlexey Budankov 				pr_err("failed to sync perf data, error: %m\n");
242d3d1af6fSAlexey Budankov 		}
243d3d1af6fSAlexey Budankov 	} while (1);
244d3d1af6fSAlexey Budankov }
245d3d1af6fSAlexey Budankov 
246d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t size, off_t off)
247d3d1af6fSAlexey Budankov {
248d3d1af6fSAlexey Budankov 	struct record *rec = to;
249d3d1af6fSAlexey Budankov 	int ret, trace_fd = rec->session->data->file.fd;
250d3d1af6fSAlexey Budankov 
251d3d1af6fSAlexey Budankov 	rec->samples++;
252d3d1af6fSAlexey Budankov 
253d3d1af6fSAlexey Budankov 	ret = record__aio_write(cblock, trace_fd, bf, size, off);
254d3d1af6fSAlexey Budankov 	if (!ret) {
255d3d1af6fSAlexey Budankov 		rec->bytes_written += size;
256d3d1af6fSAlexey Budankov 		if (switch_output_size(rec))
257d3d1af6fSAlexey Budankov 			trigger_hit(&switch_output_trigger);
258d3d1af6fSAlexey Budankov 	}
259d3d1af6fSAlexey Budankov 
260d3d1af6fSAlexey Budankov 	return ret;
261d3d1af6fSAlexey Budankov }
262d3d1af6fSAlexey Budankov 
263d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd)
264d3d1af6fSAlexey Budankov {
265d3d1af6fSAlexey Budankov 	return lseek(trace_fd, 0, SEEK_CUR);
266d3d1af6fSAlexey Budankov }
267d3d1af6fSAlexey Budankov 
268d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos)
269d3d1af6fSAlexey Budankov {
270d3d1af6fSAlexey Budankov 	lseek(trace_fd, pos, SEEK_SET);
271d3d1af6fSAlexey Budankov }
272d3d1af6fSAlexey Budankov 
273d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec)
274d3d1af6fSAlexey Budankov {
275d3d1af6fSAlexey Budankov 	int i;
276d3d1af6fSAlexey Budankov 	struct perf_evlist *evlist = rec->evlist;
277d3d1af6fSAlexey Budankov 	struct perf_mmap *maps = evlist->mmap;
278d3d1af6fSAlexey Budankov 
279d3d1af6fSAlexey Budankov 	if (!rec->opts.nr_cblocks)
280d3d1af6fSAlexey Budankov 		return;
281d3d1af6fSAlexey Budankov 
282d3d1af6fSAlexey Budankov 	for (i = 0; i < evlist->nr_mmaps; i++) {
283d3d1af6fSAlexey Budankov 		struct perf_mmap *map = &maps[i];
284d3d1af6fSAlexey Budankov 
285d3d1af6fSAlexey Budankov 		if (map->base)
28693f20c0fSAlexey Budankov 			record__aio_sync(map, true);
287d3d1af6fSAlexey Budankov 	}
288d3d1af6fSAlexey Budankov }
289d3d1af6fSAlexey Budankov 
290d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1;
29193f20c0fSAlexey Budankov static int nr_cblocks_max = 4;
292d3d1af6fSAlexey Budankov 
293d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt,
29493f20c0fSAlexey Budankov 			     const char *str,
295d3d1af6fSAlexey Budankov 			     int unset)
296d3d1af6fSAlexey Budankov {
297d3d1af6fSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
298d3d1af6fSAlexey Budankov 
29993f20c0fSAlexey Budankov 	if (unset) {
300d3d1af6fSAlexey Budankov 		opts->nr_cblocks = 0;
30193f20c0fSAlexey Budankov 	} else {
30293f20c0fSAlexey Budankov 		if (str)
30393f20c0fSAlexey Budankov 			opts->nr_cblocks = strtol(str, NULL, 0);
30493f20c0fSAlexey Budankov 		if (!opts->nr_cblocks)
305d3d1af6fSAlexey Budankov 			opts->nr_cblocks = nr_cblocks_default;
30693f20c0fSAlexey Budankov 	}
307d3d1af6fSAlexey Budankov 
308d3d1af6fSAlexey Budankov 	return 0;
309d3d1af6fSAlexey Budankov }
310d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */
31193f20c0fSAlexey Budankov static int nr_cblocks_max = 0;
31293f20c0fSAlexey Budankov 
31393f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md __maybe_unused, bool sync_all __maybe_unused)
314d3d1af6fSAlexey Budankov {
31593f20c0fSAlexey Budankov 	return -1;
316d3d1af6fSAlexey Budankov }
317d3d1af6fSAlexey Budankov 
318d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to __maybe_unused, struct aiocb *cblock __maybe_unused,
319d3d1af6fSAlexey Budankov 		void *bf __maybe_unused, size_t size __maybe_unused, off_t off __maybe_unused)
320d3d1af6fSAlexey Budankov {
321d3d1af6fSAlexey Budankov 	return -1;
322d3d1af6fSAlexey Budankov }
323d3d1af6fSAlexey Budankov 
324d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused)
325d3d1af6fSAlexey Budankov {
326d3d1af6fSAlexey Budankov 	return -1;
327d3d1af6fSAlexey Budankov }
328d3d1af6fSAlexey Budankov 
329d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused)
330d3d1af6fSAlexey Budankov {
331d3d1af6fSAlexey Budankov }
332d3d1af6fSAlexey Budankov 
333d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused)
334d3d1af6fSAlexey Budankov {
335d3d1af6fSAlexey Budankov }
336d3d1af6fSAlexey Budankov #endif
337d3d1af6fSAlexey Budankov 
338d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec)
339d3d1af6fSAlexey Budankov {
340d3d1af6fSAlexey Budankov 	return rec->opts.nr_cblocks > 0;
341d3d1af6fSAlexey Budankov }
342d3d1af6fSAlexey Budankov 
343470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1
344470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt,
345470530bbSAlexey Budankov 				    const char *str,
346470530bbSAlexey Budankov 				    int unset)
347470530bbSAlexey Budankov {
348470530bbSAlexey Budankov 	int flush_max;
349470530bbSAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
350470530bbSAlexey Budankov 	static struct parse_tag tags[] = {
351470530bbSAlexey Budankov 			{ .tag  = 'B', .mult = 1       },
352470530bbSAlexey Budankov 			{ .tag  = 'K', .mult = 1 << 10 },
353470530bbSAlexey Budankov 			{ .tag  = 'M', .mult = 1 << 20 },
354470530bbSAlexey Budankov 			{ .tag  = 'G', .mult = 1 << 30 },
355470530bbSAlexey Budankov 			{ .tag  = 0 },
356470530bbSAlexey Budankov 	};
357470530bbSAlexey Budankov 
358470530bbSAlexey Budankov 	if (unset)
359470530bbSAlexey Budankov 		return 0;
360470530bbSAlexey Budankov 
361470530bbSAlexey Budankov 	if (str) {
362470530bbSAlexey Budankov 		opts->mmap_flush = parse_tag_value(str, tags);
363470530bbSAlexey Budankov 		if (opts->mmap_flush == (int)-1)
364470530bbSAlexey Budankov 			opts->mmap_flush = strtol(str, NULL, 0);
365470530bbSAlexey Budankov 	}
366470530bbSAlexey Budankov 
367470530bbSAlexey Budankov 	if (!opts->mmap_flush)
368470530bbSAlexey Budankov 		opts->mmap_flush = MMAP_FLUSH_DEFAULT;
369470530bbSAlexey Budankov 
370470530bbSAlexey Budankov 	flush_max = perf_evlist__mmap_size(opts->mmap_pages);
371470530bbSAlexey Budankov 	flush_max /= 4;
372470530bbSAlexey Budankov 	if (opts->mmap_flush > flush_max)
373470530bbSAlexey Budankov 		opts->mmap_flush = flush_max;
374470530bbSAlexey Budankov 
375470530bbSAlexey Budankov 	return 0;
376470530bbSAlexey Budankov }
377470530bbSAlexey Budankov 
37851255a8aSAlexey Budankov static unsigned int comp_level_max = 22;
37951255a8aSAlexey Budankov 
38042e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec)
38142e1fd80SAlexey Budankov {
38242e1fd80SAlexey Budankov 	return rec->opts.comp_level > 0;
38342e1fd80SAlexey Budankov }
38442e1fd80SAlexey Budankov 
38545694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool,
386d20deb64SArnaldo Carvalho de Melo 				     union perf_event *event,
3871d037ca1SIrina Tirdea 				     struct perf_sample *sample __maybe_unused,
3881d037ca1SIrina Tirdea 				     struct machine *machine __maybe_unused)
389234fbbf5SArnaldo Carvalho de Melo {
3908c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = container_of(tool, struct record, tool);
391ded2b8feSJiri Olsa 	return record__write(rec, NULL, event, event->header.size);
392234fbbf5SArnaldo Carvalho de Melo }
393234fbbf5SArnaldo Carvalho de Melo 
394ded2b8feSJiri Olsa static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
395d37f1586SArnaldo Carvalho de Melo {
396d37f1586SArnaldo Carvalho de Melo 	struct record *rec = to;
397d37f1586SArnaldo Carvalho de Melo 
398*5d7f4116SAlexey Budankov 	if (record__comp_enabled(rec)) {
399*5d7f4116SAlexey Budankov 		size = zstd_compress(rec->session, map->data, perf_mmap__mmap_len(map), bf, size);
400*5d7f4116SAlexey Budankov 		bf   = map->data;
401*5d7f4116SAlexey Budankov 	}
402*5d7f4116SAlexey Budankov 
403d37f1586SArnaldo Carvalho de Melo 	rec->samples++;
404ded2b8feSJiri Olsa 	return record__write(rec, map, bf, size);
405d37f1586SArnaldo Carvalho de Melo }
406d37f1586SArnaldo Carvalho de Melo 
4072dd6d8a1SAdrian Hunter static volatile int done;
4082dd6d8a1SAdrian Hunter static volatile int signr = -1;
4092dd6d8a1SAdrian Hunter static volatile int child_finished;
410c0bdc1c4SWang Nan 
4112dd6d8a1SAdrian Hunter static void sig_handler(int sig)
4122dd6d8a1SAdrian Hunter {
4132dd6d8a1SAdrian Hunter 	if (sig == SIGCHLD)
4142dd6d8a1SAdrian Hunter 		child_finished = 1;
4152dd6d8a1SAdrian Hunter 	else
4162dd6d8a1SAdrian Hunter 		signr = sig;
4172dd6d8a1SAdrian Hunter 
4182dd6d8a1SAdrian Hunter 	done = 1;
4192dd6d8a1SAdrian Hunter }
4202dd6d8a1SAdrian Hunter 
421a074865eSWang Nan static void sigsegv_handler(int sig)
422a074865eSWang Nan {
423a074865eSWang Nan 	perf_hooks__recover();
424a074865eSWang Nan 	sighandler_dump_stack(sig);
425a074865eSWang Nan }
426a074865eSWang Nan 
4272dd6d8a1SAdrian Hunter static void record__sig_exit(void)
4282dd6d8a1SAdrian Hunter {
4292dd6d8a1SAdrian Hunter 	if (signr == -1)
4302dd6d8a1SAdrian Hunter 		return;
4312dd6d8a1SAdrian Hunter 
4322dd6d8a1SAdrian Hunter 	signal(signr, SIG_DFL);
4332dd6d8a1SAdrian Hunter 	raise(signr);
4342dd6d8a1SAdrian Hunter }
4352dd6d8a1SAdrian Hunter 
436e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT
437e31f0d01SAdrian Hunter 
438ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool,
439ded2b8feSJiri Olsa 				    struct perf_mmap *map,
440ef149c25SAdrian Hunter 				    union perf_event *event, void *data1,
441ef149c25SAdrian Hunter 				    size_t len1, void *data2, size_t len2)
442ef149c25SAdrian Hunter {
443ef149c25SAdrian Hunter 	struct record *rec = container_of(tool, struct record, tool);
4448ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
445ef149c25SAdrian Hunter 	size_t padding;
446ef149c25SAdrian Hunter 	u8 pad[8] = {0};
447ef149c25SAdrian Hunter 
448cd3dd8ddSJiri Olsa 	if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) {
44999fa2984SAdrian Hunter 		off_t file_offset;
4508ceb41d7SJiri Olsa 		int fd = perf_data__fd(data);
45199fa2984SAdrian Hunter 		int err;
45299fa2984SAdrian Hunter 
45399fa2984SAdrian Hunter 		file_offset = lseek(fd, 0, SEEK_CUR);
45499fa2984SAdrian Hunter 		if (file_offset == -1)
45599fa2984SAdrian Hunter 			return -1;
45699fa2984SAdrian Hunter 		err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index,
45799fa2984SAdrian Hunter 						     event, file_offset);
45899fa2984SAdrian Hunter 		if (err)
45999fa2984SAdrian Hunter 			return err;
46099fa2984SAdrian Hunter 	}
46199fa2984SAdrian Hunter 
462ef149c25SAdrian Hunter 	/* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */
463ef149c25SAdrian Hunter 	padding = (len1 + len2) & 7;
464ef149c25SAdrian Hunter 	if (padding)
465ef149c25SAdrian Hunter 		padding = 8 - padding;
466ef149c25SAdrian Hunter 
467ded2b8feSJiri Olsa 	record__write(rec, map, event, event->header.size);
468ded2b8feSJiri Olsa 	record__write(rec, map, data1, len1);
469ef149c25SAdrian Hunter 	if (len2)
470ded2b8feSJiri Olsa 		record__write(rec, map, data2, len2);
471ded2b8feSJiri Olsa 	record__write(rec, map, &pad, padding);
472ef149c25SAdrian Hunter 
473ef149c25SAdrian Hunter 	return 0;
474ef149c25SAdrian Hunter }
475ef149c25SAdrian Hunter 
476ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec,
477e035f4caSJiri Olsa 				      struct perf_mmap *map)
478ef149c25SAdrian Hunter {
479ef149c25SAdrian Hunter 	int ret;
480ef149c25SAdrian Hunter 
481e035f4caSJiri Olsa 	ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
482ef149c25SAdrian Hunter 				  record__process_auxtrace);
483ef149c25SAdrian Hunter 	if (ret < 0)
484ef149c25SAdrian Hunter 		return ret;
485ef149c25SAdrian Hunter 
486ef149c25SAdrian Hunter 	if (ret)
487ef149c25SAdrian Hunter 		rec->samples++;
488ef149c25SAdrian Hunter 
489ef149c25SAdrian Hunter 	return 0;
490ef149c25SAdrian Hunter }
491ef149c25SAdrian Hunter 
4922dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec,
493e035f4caSJiri Olsa 					       struct perf_mmap *map)
4942dd6d8a1SAdrian Hunter {
4952dd6d8a1SAdrian Hunter 	int ret;
4962dd6d8a1SAdrian Hunter 
497e035f4caSJiri Olsa 	ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
4982dd6d8a1SAdrian Hunter 					   record__process_auxtrace,
4992dd6d8a1SAdrian Hunter 					   rec->opts.auxtrace_snapshot_size);
5002dd6d8a1SAdrian Hunter 	if (ret < 0)
5012dd6d8a1SAdrian Hunter 		return ret;
5022dd6d8a1SAdrian Hunter 
5032dd6d8a1SAdrian Hunter 	if (ret)
5042dd6d8a1SAdrian Hunter 		rec->samples++;
5052dd6d8a1SAdrian Hunter 
5062dd6d8a1SAdrian Hunter 	return 0;
5072dd6d8a1SAdrian Hunter }
5082dd6d8a1SAdrian Hunter 
5092dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec)
5102dd6d8a1SAdrian Hunter {
5112dd6d8a1SAdrian Hunter 	int i;
5122dd6d8a1SAdrian Hunter 	int rc = 0;
5132dd6d8a1SAdrian Hunter 
5142dd6d8a1SAdrian Hunter 	for (i = 0; i < rec->evlist->nr_mmaps; i++) {
515e035f4caSJiri Olsa 		struct perf_mmap *map = &rec->evlist->mmap[i];
5162dd6d8a1SAdrian Hunter 
517e035f4caSJiri Olsa 		if (!map->auxtrace_mmap.base)
5182dd6d8a1SAdrian Hunter 			continue;
5192dd6d8a1SAdrian Hunter 
520e035f4caSJiri Olsa 		if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
5212dd6d8a1SAdrian Hunter 			rc = -1;
5222dd6d8a1SAdrian Hunter 			goto out;
5232dd6d8a1SAdrian Hunter 		}
5242dd6d8a1SAdrian Hunter 	}
5252dd6d8a1SAdrian Hunter out:
5262dd6d8a1SAdrian Hunter 	return rc;
5272dd6d8a1SAdrian Hunter }
5282dd6d8a1SAdrian Hunter 
5292dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec)
5302dd6d8a1SAdrian Hunter {
5312dd6d8a1SAdrian Hunter 	pr_debug("Recording AUX area tracing snapshot\n");
5322dd6d8a1SAdrian Hunter 	if (record__auxtrace_read_snapshot_all(rec) < 0) {
5335f9cf599SWang Nan 		trigger_error(&auxtrace_snapshot_trigger);
5342dd6d8a1SAdrian Hunter 	} else {
5355f9cf599SWang Nan 		if (auxtrace_record__snapshot_finish(rec->itr))
5365f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
5375f9cf599SWang Nan 		else
5385f9cf599SWang Nan 			trigger_ready(&auxtrace_snapshot_trigger);
5392dd6d8a1SAdrian Hunter 	}
5402dd6d8a1SAdrian Hunter }
5412dd6d8a1SAdrian Hunter 
5424b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec)
5434b5ea3bdSAdrian Hunter {
5444b5ea3bdSAdrian Hunter 	int err;
5454b5ea3bdSAdrian Hunter 
5464b5ea3bdSAdrian Hunter 	if (!rec->itr) {
5474b5ea3bdSAdrian Hunter 		rec->itr = auxtrace_record__init(rec->evlist, &err);
5484b5ea3bdSAdrian Hunter 		if (err)
5494b5ea3bdSAdrian Hunter 			return err;
5504b5ea3bdSAdrian Hunter 	}
5514b5ea3bdSAdrian Hunter 
5524b5ea3bdSAdrian Hunter 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
5534b5ea3bdSAdrian Hunter 					      rec->opts.auxtrace_snapshot_opts);
5544b5ea3bdSAdrian Hunter 	if (err)
5554b5ea3bdSAdrian Hunter 		return err;
5564b5ea3bdSAdrian Hunter 
5574b5ea3bdSAdrian Hunter 	return auxtrace_parse_filters(rec->evlist);
5584b5ea3bdSAdrian Hunter }
5594b5ea3bdSAdrian Hunter 
560e31f0d01SAdrian Hunter #else
561e31f0d01SAdrian Hunter 
562e31f0d01SAdrian Hunter static inline
563e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
564e035f4caSJiri Olsa 			       struct perf_mmap *map __maybe_unused)
565e31f0d01SAdrian Hunter {
566e31f0d01SAdrian Hunter 	return 0;
567e31f0d01SAdrian Hunter }
568e31f0d01SAdrian Hunter 
5692dd6d8a1SAdrian Hunter static inline
5702dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused)
5712dd6d8a1SAdrian Hunter {
5722dd6d8a1SAdrian Hunter }
5732dd6d8a1SAdrian Hunter 
5742dd6d8a1SAdrian Hunter static inline
5752dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
5762dd6d8a1SAdrian Hunter {
5772dd6d8a1SAdrian Hunter 	return 0;
5782dd6d8a1SAdrian Hunter }
5792dd6d8a1SAdrian Hunter 
5804b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused)
5814b5ea3bdSAdrian Hunter {
5824b5ea3bdSAdrian Hunter 	return 0;
5834b5ea3bdSAdrian Hunter }
5844b5ea3bdSAdrian Hunter 
585e31f0d01SAdrian Hunter #endif
586e31f0d01SAdrian Hunter 
587cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec,
588cda57a8cSWang Nan 			       struct perf_evlist *evlist)
589cda57a8cSWang Nan {
590cda57a8cSWang Nan 	struct record_opts *opts = &rec->opts;
591cda57a8cSWang Nan 	char msg[512];
592cda57a8cSWang Nan 
593f13de660SAlexey Budankov 	if (opts->affinity != PERF_AFFINITY_SYS)
594f13de660SAlexey Budankov 		cpu__setup_cpunode_map();
595f13de660SAlexey Budankov 
5967a276ff6SWang Nan 	if (perf_evlist__mmap_ex(evlist, opts->mmap_pages,
597cda57a8cSWang Nan 				 opts->auxtrace_mmap_pages,
5989d2ed645SAlexey Budankov 				 opts->auxtrace_snapshot_mode,
599470530bbSAlexey Budankov 				 opts->nr_cblocks, opts->affinity,
60051255a8aSAlexey Budankov 				 opts->mmap_flush, opts->comp_level) < 0) {
601cda57a8cSWang Nan 		if (errno == EPERM) {
602cda57a8cSWang Nan 			pr_err("Permission error mapping pages.\n"
603cda57a8cSWang Nan 			       "Consider increasing "
604cda57a8cSWang Nan 			       "/proc/sys/kernel/perf_event_mlock_kb,\n"
605cda57a8cSWang Nan 			       "or try again with a smaller value of -m/--mmap_pages.\n"
606cda57a8cSWang Nan 			       "(current value: %u,%u)\n",
607cda57a8cSWang Nan 			       opts->mmap_pages, opts->auxtrace_mmap_pages);
608cda57a8cSWang Nan 			return -errno;
609cda57a8cSWang Nan 		} else {
610cda57a8cSWang Nan 			pr_err("failed to mmap with %d (%s)\n", errno,
611c8b5f2c9SArnaldo Carvalho de Melo 				str_error_r(errno, msg, sizeof(msg)));
612cda57a8cSWang Nan 			if (errno)
613cda57a8cSWang Nan 				return -errno;
614cda57a8cSWang Nan 			else
615cda57a8cSWang Nan 				return -EINVAL;
616cda57a8cSWang Nan 		}
617cda57a8cSWang Nan 	}
618cda57a8cSWang Nan 	return 0;
619cda57a8cSWang Nan }
620cda57a8cSWang Nan 
621cda57a8cSWang Nan static int record__mmap(struct record *rec)
622cda57a8cSWang Nan {
623cda57a8cSWang Nan 	return record__mmap_evlist(rec, rec->evlist);
624cda57a8cSWang Nan }
625cda57a8cSWang Nan 
6268c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec)
627dd7927f4SArnaldo Carvalho de Melo {
628d6195a6aSArnaldo Carvalho de Melo 	char msg[BUFSIZ];
6296a4bb04cSJiri Olsa 	struct perf_evsel *pos;
630d20deb64SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = rec->evlist;
631d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session = rec->session;
632b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
6338d3eca20SDavid Ahern 	int rc = 0;
634dd7927f4SArnaldo Carvalho de Melo 
635d3dbf43cSArnaldo Carvalho de Melo 	/*
636d3dbf43cSArnaldo Carvalho de Melo 	 * For initial_delay we need to add a dummy event so that we can track
637d3dbf43cSArnaldo Carvalho de Melo 	 * PERF_RECORD_MMAP while we wait for the initial delay to enable the
638d3dbf43cSArnaldo Carvalho de Melo 	 * real events, the ones asked by the user.
639d3dbf43cSArnaldo Carvalho de Melo 	 */
640d3dbf43cSArnaldo Carvalho de Melo 	if (opts->initial_delay) {
641d3dbf43cSArnaldo Carvalho de Melo 		if (perf_evlist__add_dummy(evlist))
642d3dbf43cSArnaldo Carvalho de Melo 			return -ENOMEM;
643d3dbf43cSArnaldo Carvalho de Melo 
644d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__first(evlist);
645d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 0;
646d3dbf43cSArnaldo Carvalho de Melo 		pos = perf_evlist__last(evlist);
647d3dbf43cSArnaldo Carvalho de Melo 		pos->tracking = 1;
648d3dbf43cSArnaldo Carvalho de Melo 		pos->attr.enable_on_exec = 1;
649d3dbf43cSArnaldo Carvalho de Melo 	}
650d3dbf43cSArnaldo Carvalho de Melo 
651e68ae9cfSArnaldo Carvalho de Melo 	perf_evlist__config(evlist, opts, &callchain_param);
652cac21425SJiri Olsa 
653e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
6543da297a6SIngo Molnar try_again:
655d988d5eeSKan Liang 		if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
65656e52e85SArnaldo Carvalho de Melo 			if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
657bb963e16SNamhyung Kim 				if (verbose > 0)
658c0a54341SArnaldo Carvalho de Melo 					ui__warning("%s\n", msg);
6593da297a6SIngo Molnar 				goto try_again;
6603da297a6SIngo Molnar 			}
661cf99ad14SAndi Kleen 			if ((errno == EINVAL || errno == EBADF) &&
662cf99ad14SAndi Kleen 			    pos->leader != pos &&
663cf99ad14SAndi Kleen 			    pos->weak_group) {
664cf99ad14SAndi Kleen 			        pos = perf_evlist__reset_weak_group(evlist, pos);
665cf99ad14SAndi Kleen 				goto try_again;
666cf99ad14SAndi Kleen 			}
66756e52e85SArnaldo Carvalho de Melo 			rc = -errno;
66856e52e85SArnaldo Carvalho de Melo 			perf_evsel__open_strerror(pos, &opts->target,
66956e52e85SArnaldo Carvalho de Melo 						  errno, msg, sizeof(msg));
67056e52e85SArnaldo Carvalho de Melo 			ui__error("%s\n", msg);
6718d3eca20SDavid Ahern 			goto out;
6727c6a1c65SPeter Zijlstra 		}
673bfd8f72cSAndi Kleen 
674bfd8f72cSAndi Kleen 		pos->supported = true;
6757c6a1c65SPeter Zijlstra 	}
6767c6a1c65SPeter Zijlstra 
67723d4aad4SArnaldo Carvalho de Melo 	if (perf_evlist__apply_filters(evlist, &pos)) {
67862d94b00SArnaldo Carvalho de Melo 		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
67923d4aad4SArnaldo Carvalho de Melo 			pos->filter, perf_evsel__name(pos), errno,
680c8b5f2c9SArnaldo Carvalho de Melo 			str_error_r(errno, msg, sizeof(msg)));
6818d3eca20SDavid Ahern 		rc = -1;
6828d3eca20SDavid Ahern 		goto out;
6830a102479SFrederic Weisbecker 	}
6840a102479SFrederic Weisbecker 
685cda57a8cSWang Nan 	rc = record__mmap(rec);
686cda57a8cSWang Nan 	if (rc)
6878d3eca20SDavid Ahern 		goto out;
6880a27d7f9SArnaldo Carvalho de Melo 
689a91e5431SArnaldo Carvalho de Melo 	session->evlist = evlist;
6907b56cce2SArnaldo Carvalho de Melo 	perf_session__set_id_hdr_size(session);
6918d3eca20SDavid Ahern out:
6928d3eca20SDavid Ahern 	return rc;
693a91e5431SArnaldo Carvalho de Melo }
694a91e5431SArnaldo Carvalho de Melo 
695e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool,
696e3d59112SNamhyung Kim 				union perf_event *event,
697e3d59112SNamhyung Kim 				struct perf_sample *sample,
698e3d59112SNamhyung Kim 				struct perf_evsel *evsel,
699e3d59112SNamhyung Kim 				struct machine *machine)
700e3d59112SNamhyung Kim {
701e3d59112SNamhyung Kim 	struct record *rec = container_of(tool, struct record, tool);
702e3d59112SNamhyung Kim 
70368588bafSJin Yao 	if (rec->evlist->first_sample_time == 0)
70468588bafSJin Yao 		rec->evlist->first_sample_time = sample->time;
705e3d59112SNamhyung Kim 
70668588bafSJin Yao 	rec->evlist->last_sample_time = sample->time;
70768588bafSJin Yao 
70868588bafSJin Yao 	if (rec->buildid_all)
70968588bafSJin Yao 		return 0;
71068588bafSJin Yao 
71168588bafSJin Yao 	rec->samples++;
712e3d59112SNamhyung Kim 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
713e3d59112SNamhyung Kim }
714e3d59112SNamhyung Kim 
7158c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec)
7166122e4e4SArnaldo Carvalho de Melo {
717f5fc1412SJiri Olsa 	struct perf_session *session = rec->session;
7186122e4e4SArnaldo Carvalho de Melo 
71945112e89SJiri Olsa 	if (perf_data__size(&rec->data) == 0)
7209f591fd7SArnaldo Carvalho de Melo 		return 0;
7219f591fd7SArnaldo Carvalho de Melo 
72200dc8657SNamhyung Kim 	/*
72300dc8657SNamhyung Kim 	 * During this process, it'll load kernel map and replace the
72400dc8657SNamhyung Kim 	 * dso->long_name to a real pathname it found.  In this case
72500dc8657SNamhyung Kim 	 * we prefer the vmlinux path like
72600dc8657SNamhyung Kim 	 *   /lib/modules/3.16.4/build/vmlinux
72700dc8657SNamhyung Kim 	 *
72800dc8657SNamhyung Kim 	 * rather than build-id path (in debug directory).
72900dc8657SNamhyung Kim 	 *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
73000dc8657SNamhyung Kim 	 */
73100dc8657SNamhyung Kim 	symbol_conf.ignore_vmlinux_buildid = true;
73200dc8657SNamhyung Kim 
7336156681bSNamhyung Kim 	/*
7346156681bSNamhyung Kim 	 * If --buildid-all is given, it marks all DSO regardless of hits,
73568588bafSJin Yao 	 * so no need to process samples. But if timestamp_boundary is enabled,
73668588bafSJin Yao 	 * it still needs to walk on all samples to get the timestamps of
73768588bafSJin Yao 	 * first/last samples.
7386156681bSNamhyung Kim 	 */
73968588bafSJin Yao 	if (rec->buildid_all && !rec->timestamp_boundary)
7406156681bSNamhyung Kim 		rec->tool.sample = NULL;
7416156681bSNamhyung Kim 
742b7b61cbeSArnaldo Carvalho de Melo 	return perf_session__process_events(session);
7436122e4e4SArnaldo Carvalho de Melo }
7446122e4e4SArnaldo Carvalho de Melo 
7458115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
746a1645ce1SZhang, Yanmin {
747a1645ce1SZhang, Yanmin 	int err;
74845694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = data;
749a1645ce1SZhang, Yanmin 	/*
750a1645ce1SZhang, Yanmin 	 *As for guest kernel when processing subcommand record&report,
751a1645ce1SZhang, Yanmin 	 *we arrange module mmap prior to guest kernel mmap and trigger
752a1645ce1SZhang, Yanmin 	 *a preload dso because default guest module symbols are loaded
753a1645ce1SZhang, Yanmin 	 *from guest kallsyms instead of /lib/modules/XXX/XXX. This
754a1645ce1SZhang, Yanmin 	 *method is used to avoid symbol missing when the first addr is
755a1645ce1SZhang, Yanmin 	 *in module instead of in guest kernel.
756a1645ce1SZhang, Yanmin 	 */
75745694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_modules(tool, process_synthesized_event,
758743eb868SArnaldo Carvalho de Melo 					     machine);
759a1645ce1SZhang, Yanmin 	if (err < 0)
760a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
76123346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
762a1645ce1SZhang, Yanmin 
763a1645ce1SZhang, Yanmin 	/*
764a1645ce1SZhang, Yanmin 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
765a1645ce1SZhang, Yanmin 	 * have no _text sometimes.
766a1645ce1SZhang, Yanmin 	 */
76745694aa7SArnaldo Carvalho de Melo 	err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
7680ae617beSAdrian Hunter 						 machine);
769a1645ce1SZhang, Yanmin 	if (err < 0)
770a1645ce1SZhang, Yanmin 		pr_err("Couldn't record guest kernel [%d]'s reference"
77123346f21SArnaldo Carvalho de Melo 		       " relocation symbol.\n", machine->pid);
772a1645ce1SZhang, Yanmin }
773a1645ce1SZhang, Yanmin 
77498402807SFrederic Weisbecker static struct perf_event_header finished_round_event = {
77598402807SFrederic Weisbecker 	.size = sizeof(struct perf_event_header),
77698402807SFrederic Weisbecker 	.type = PERF_RECORD_FINISHED_ROUND,
77798402807SFrederic Weisbecker };
77898402807SFrederic Weisbecker 
779f13de660SAlexey Budankov static void record__adjust_affinity(struct record *rec, struct perf_mmap *map)
780f13de660SAlexey Budankov {
781f13de660SAlexey Budankov 	if (rec->opts.affinity != PERF_AFFINITY_SYS &&
782f13de660SAlexey Budankov 	    !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) {
783f13de660SAlexey Budankov 		CPU_ZERO(&rec->affinity_mask);
784f13de660SAlexey Budankov 		CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask);
785f13de660SAlexey Budankov 		sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask);
786f13de660SAlexey Budankov 	}
787f13de660SAlexey Budankov }
788f13de660SAlexey Budankov 
789*5d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment)
790*5d7f4116SAlexey Budankov {
791*5d7f4116SAlexey Budankov 	struct compressed_event *event = record;
792*5d7f4116SAlexey Budankov 	size_t size = sizeof(*event);
793*5d7f4116SAlexey Budankov 
794*5d7f4116SAlexey Budankov 	if (increment) {
795*5d7f4116SAlexey Budankov 		event->header.size += increment;
796*5d7f4116SAlexey Budankov 		return increment;
797*5d7f4116SAlexey Budankov 	}
798*5d7f4116SAlexey Budankov 
799*5d7f4116SAlexey Budankov 	event->header.type = PERF_RECORD_COMPRESSED;
800*5d7f4116SAlexey Budankov 	event->header.size = size;
801*5d7f4116SAlexey Budankov 
802*5d7f4116SAlexey Budankov 	return size;
803*5d7f4116SAlexey Budankov }
804*5d7f4116SAlexey Budankov 
805*5d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size,
806*5d7f4116SAlexey Budankov 			    void *src, size_t src_size)
807*5d7f4116SAlexey Budankov {
808*5d7f4116SAlexey Budankov 	size_t compressed;
809*5d7f4116SAlexey Budankov 	size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct compressed_event) - 1;
810*5d7f4116SAlexey Budankov 
811*5d7f4116SAlexey Budankov 	compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size,
812*5d7f4116SAlexey Budankov 						     max_record_size, process_comp_header);
813*5d7f4116SAlexey Budankov 
814*5d7f4116SAlexey Budankov 	session->bytes_transferred += src_size;
815*5d7f4116SAlexey Budankov 	session->bytes_compressed  += compressed;
816*5d7f4116SAlexey Budankov 
817*5d7f4116SAlexey Budankov 	return compressed;
818*5d7f4116SAlexey Budankov }
819*5d7f4116SAlexey Budankov 
820a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
821470530bbSAlexey Budankov 				    bool overwrite, bool synch)
82298402807SFrederic Weisbecker {
823dcabb507SJiri Olsa 	u64 bytes_written = rec->bytes_written;
8240e2e63ddSPeter Zijlstra 	int i;
8258d3eca20SDavid Ahern 	int rc = 0;
826a4ea0ec4SWang Nan 	struct perf_mmap *maps;
827d3d1af6fSAlexey Budankov 	int trace_fd = rec->data.file.fd;
828d3d1af6fSAlexey Budankov 	off_t off;
82998402807SFrederic Weisbecker 
830cb21686bSWang Nan 	if (!evlist)
831cb21686bSWang Nan 		return 0;
832ef149c25SAdrian Hunter 
8330b72d69aSWang Nan 	maps = overwrite ? evlist->overwrite_mmap : evlist->mmap;
834a4ea0ec4SWang Nan 	if (!maps)
835a4ea0ec4SWang Nan 		return 0;
836cb21686bSWang Nan 
8370b72d69aSWang Nan 	if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
83854cc54deSWang Nan 		return 0;
83954cc54deSWang Nan 
840d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
841d3d1af6fSAlexey Budankov 		off = record__aio_get_pos(trace_fd);
842d3d1af6fSAlexey Budankov 
843a4ea0ec4SWang Nan 	for (i = 0; i < evlist->nr_mmaps; i++) {
844470530bbSAlexey Budankov 		u64 flush = 0;
845e035f4caSJiri Olsa 		struct perf_mmap *map = &maps[i];
846a4ea0ec4SWang Nan 
847e035f4caSJiri Olsa 		if (map->base) {
848f13de660SAlexey Budankov 			record__adjust_affinity(rec, map);
849470530bbSAlexey Budankov 			if (synch) {
850470530bbSAlexey Budankov 				flush = map->flush;
851470530bbSAlexey Budankov 				map->flush = 1;
852470530bbSAlexey Budankov 			}
853d3d1af6fSAlexey Budankov 			if (!record__aio_enabled(rec)) {
854e035f4caSJiri Olsa 				if (perf_mmap__push(map, rec, record__pushfn) != 0) {
855470530bbSAlexey Budankov 					if (synch)
856470530bbSAlexey Budankov 						map->flush = flush;
8578d3eca20SDavid Ahern 					rc = -1;
8588d3eca20SDavid Ahern 					goto out;
8598d3eca20SDavid Ahern 				}
860d3d1af6fSAlexey Budankov 			} else {
86193f20c0fSAlexey Budankov 				int idx;
862d3d1af6fSAlexey Budankov 				/*
863d3d1af6fSAlexey Budankov 				 * Call record__aio_sync() to wait till map->data buffer
864d3d1af6fSAlexey Budankov 				 * becomes available after previous aio write request.
865d3d1af6fSAlexey Budankov 				 */
86693f20c0fSAlexey Budankov 				idx = record__aio_sync(map, false);
86793f20c0fSAlexey Budankov 				if (perf_mmap__aio_push(map, rec, idx, record__aio_pushfn, &off) != 0) {
868d3d1af6fSAlexey Budankov 					record__aio_set_pos(trace_fd, off);
869470530bbSAlexey Budankov 					if (synch)
870470530bbSAlexey Budankov 						map->flush = flush;
871d3d1af6fSAlexey Budankov 					rc = -1;
872d3d1af6fSAlexey Budankov 					goto out;
873d3d1af6fSAlexey Budankov 				}
874d3d1af6fSAlexey Budankov 			}
875470530bbSAlexey Budankov 			if (synch)
876470530bbSAlexey Budankov 				map->flush = flush;
8778d3eca20SDavid Ahern 		}
878ef149c25SAdrian Hunter 
879e035f4caSJiri Olsa 		if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
880e035f4caSJiri Olsa 		    record__auxtrace_mmap_read(rec, map) != 0) {
881ef149c25SAdrian Hunter 			rc = -1;
882ef149c25SAdrian Hunter 			goto out;
883ef149c25SAdrian Hunter 		}
88498402807SFrederic Weisbecker 	}
88598402807SFrederic Weisbecker 
886d3d1af6fSAlexey Budankov 	if (record__aio_enabled(rec))
887d3d1af6fSAlexey Budankov 		record__aio_set_pos(trace_fd, off);
888d3d1af6fSAlexey Budankov 
889dcabb507SJiri Olsa 	/*
890dcabb507SJiri Olsa 	 * Mark the round finished in case we wrote
891dcabb507SJiri Olsa 	 * at least one event.
892dcabb507SJiri Olsa 	 */
893dcabb507SJiri Olsa 	if (bytes_written != rec->bytes_written)
894ded2b8feSJiri Olsa 		rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
8958d3eca20SDavid Ahern 
8960b72d69aSWang Nan 	if (overwrite)
89754cc54deSWang Nan 		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
8988d3eca20SDavid Ahern out:
8998d3eca20SDavid Ahern 	return rc;
90098402807SFrederic Weisbecker }
90198402807SFrederic Weisbecker 
902470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch)
903cb21686bSWang Nan {
904cb21686bSWang Nan 	int err;
905cb21686bSWang Nan 
906470530bbSAlexey Budankov 	err = record__mmap_read_evlist(rec, rec->evlist, false, synch);
907cb21686bSWang Nan 	if (err)
908cb21686bSWang Nan 		return err;
909cb21686bSWang Nan 
910470530bbSAlexey Budankov 	return record__mmap_read_evlist(rec, rec->evlist, true, synch);
911cb21686bSWang Nan }
912cb21686bSWang Nan 
9138c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec)
91457706abcSDavid Ahern {
91557706abcSDavid Ahern 	struct perf_session *session = rec->session;
91657706abcSDavid Ahern 	int feat;
91757706abcSDavid Ahern 
91857706abcSDavid Ahern 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
91957706abcSDavid Ahern 		perf_header__set_feat(&session->header, feat);
92057706abcSDavid Ahern 
92157706abcSDavid Ahern 	if (rec->no_buildid)
92257706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
92357706abcSDavid Ahern 
9243e2be2daSArnaldo Carvalho de Melo 	if (!have_tracepoints(&rec->evlist->entries))
92557706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
92657706abcSDavid Ahern 
92757706abcSDavid Ahern 	if (!rec->opts.branch_stack)
92857706abcSDavid Ahern 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
929ef149c25SAdrian Hunter 
930ef149c25SAdrian Hunter 	if (!rec->opts.full_auxtrace)
931ef149c25SAdrian Hunter 		perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
932ffa517adSJiri Olsa 
933cf790516SAlexey Budankov 	if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
934cf790516SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_CLOCKID);
935cf790516SAlexey Budankov 
936258031c0SJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT);
93742e1fd80SAlexey Budankov 	if (!record__comp_enabled(rec))
93842e1fd80SAlexey Budankov 		perf_header__clear_feat(&session->header, HEADER_COMPRESSED);
939258031c0SJiri Olsa 
940ffa517adSJiri Olsa 	perf_header__clear_feat(&session->header, HEADER_STAT);
94157706abcSDavid Ahern }
94257706abcSDavid Ahern 
943e1ab48baSWang Nan static void
944e1ab48baSWang Nan record__finish_output(struct record *rec)
945e1ab48baSWang Nan {
9468ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
9478ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
948e1ab48baSWang Nan 
9498ceb41d7SJiri Olsa 	if (data->is_pipe)
950e1ab48baSWang Nan 		return;
951e1ab48baSWang Nan 
952e1ab48baSWang Nan 	rec->session->header.data_size += rec->bytes_written;
95345112e89SJiri Olsa 	data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR);
954e1ab48baSWang Nan 
955e1ab48baSWang Nan 	if (!rec->no_buildid) {
956e1ab48baSWang Nan 		process_buildids(rec);
957e1ab48baSWang Nan 
958e1ab48baSWang Nan 		if (rec->buildid_all)
959e1ab48baSWang Nan 			dsos__hit_all(rec->session);
960e1ab48baSWang Nan 	}
961e1ab48baSWang Nan 	perf_session__write_header(rec->session, rec->evlist, fd, true);
962e1ab48baSWang Nan 
963e1ab48baSWang Nan 	return;
964e1ab48baSWang Nan }
965e1ab48baSWang Nan 
9664ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail)
967be7b0c9eSWang Nan {
9689d6aae72SArnaldo Carvalho de Melo 	int err;
9699d6aae72SArnaldo Carvalho de Melo 	struct thread_map *thread_map;
970be7b0c9eSWang Nan 
9714ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
9724ea648aeSWang Nan 		return 0;
9734ea648aeSWang Nan 
9749d6aae72SArnaldo Carvalho de Melo 	thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
9759d6aae72SArnaldo Carvalho de Melo 	if (thread_map == NULL)
9769d6aae72SArnaldo Carvalho de Melo 		return -1;
9779d6aae72SArnaldo Carvalho de Melo 
9789d6aae72SArnaldo Carvalho de Melo 	err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
979be7b0c9eSWang Nan 						 process_synthesized_event,
980be7b0c9eSWang Nan 						 &rec->session->machines.host,
9813fcb10e4SMark Drayton 						 rec->opts.sample_address);
9829d6aae72SArnaldo Carvalho de Melo 	thread_map__put(thread_map);
9839d6aae72SArnaldo Carvalho de Melo 	return err;
984be7b0c9eSWang Nan }
985be7b0c9eSWang Nan 
9864ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail);
9873c1cb7e3SWang Nan 
988ecfd7a9cSWang Nan static int
989ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit)
990ecfd7a9cSWang Nan {
9918ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
992ecfd7a9cSWang Nan 	int fd, err;
99303724b2eSAndi Kleen 	char *new_filename;
994ecfd7a9cSWang Nan 
995ecfd7a9cSWang Nan 	/* Same Size:      "2015122520103046"*/
996ecfd7a9cSWang Nan 	char timestamp[] = "InvalidTimestamp";
997ecfd7a9cSWang Nan 
998d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
999d3d1af6fSAlexey Budankov 
10004ea648aeSWang Nan 	record__synthesize(rec, true);
10014ea648aeSWang Nan 	if (target__none(&rec->opts.target))
10024ea648aeSWang Nan 		record__synthesize_workload(rec, true);
10034ea648aeSWang Nan 
1004ecfd7a9cSWang Nan 	rec->samples = 0;
1005ecfd7a9cSWang Nan 	record__finish_output(rec);
1006ecfd7a9cSWang Nan 	err = fetch_current_timestamp(timestamp, sizeof(timestamp));
1007ecfd7a9cSWang Nan 	if (err) {
1008ecfd7a9cSWang Nan 		pr_err("Failed to get current timestamp\n");
1009ecfd7a9cSWang Nan 		return -EINVAL;
1010ecfd7a9cSWang Nan 	}
1011ecfd7a9cSWang Nan 
10128ceb41d7SJiri Olsa 	fd = perf_data__switch(data, timestamp,
1013ecfd7a9cSWang Nan 				    rec->session->header.data_offset,
101403724b2eSAndi Kleen 				    at_exit, &new_filename);
1015ecfd7a9cSWang Nan 	if (fd >= 0 && !at_exit) {
1016ecfd7a9cSWang Nan 		rec->bytes_written = 0;
1017ecfd7a9cSWang Nan 		rec->session->header.data_size = 0;
1018ecfd7a9cSWang Nan 	}
1019ecfd7a9cSWang Nan 
1020ecfd7a9cSWang Nan 	if (!quiet)
1021ecfd7a9cSWang Nan 		fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
10222d4f2799SJiri Olsa 			data->path, timestamp);
10233c1cb7e3SWang Nan 
102403724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
102503724b2eSAndi Kleen 		int n = rec->switch_output.cur_file + 1;
102603724b2eSAndi Kleen 
102703724b2eSAndi Kleen 		if (n >= rec->switch_output.num_files)
102803724b2eSAndi Kleen 			n = 0;
102903724b2eSAndi Kleen 		rec->switch_output.cur_file = n;
103003724b2eSAndi Kleen 		if (rec->switch_output.filenames[n]) {
103103724b2eSAndi Kleen 			remove(rec->switch_output.filenames[n]);
103203724b2eSAndi Kleen 			free(rec->switch_output.filenames[n]);
103303724b2eSAndi Kleen 		}
103403724b2eSAndi Kleen 		rec->switch_output.filenames[n] = new_filename;
103503724b2eSAndi Kleen 	} else {
103603724b2eSAndi Kleen 		free(new_filename);
103703724b2eSAndi Kleen 	}
103803724b2eSAndi Kleen 
10393c1cb7e3SWang Nan 	/* Output tracking events */
1040be7b0c9eSWang Nan 	if (!at_exit) {
10414ea648aeSWang Nan 		record__synthesize(rec, false);
10423c1cb7e3SWang Nan 
1043be7b0c9eSWang Nan 		/*
1044be7b0c9eSWang Nan 		 * In 'perf record --switch-output' without -a,
1045be7b0c9eSWang Nan 		 * record__synthesize() in record__switch_output() won't
1046be7b0c9eSWang Nan 		 * generate tracking events because there's no thread_map
1047be7b0c9eSWang Nan 		 * in evlist. Which causes newly created perf.data doesn't
1048be7b0c9eSWang Nan 		 * contain map and comm information.
1049be7b0c9eSWang Nan 		 * Create a fake thread_map and directly call
1050be7b0c9eSWang Nan 		 * perf_event__synthesize_thread_map() for those events.
1051be7b0c9eSWang Nan 		 */
1052be7b0c9eSWang Nan 		if (target__none(&rec->opts.target))
10534ea648aeSWang Nan 			record__synthesize_workload(rec, false);
1054be7b0c9eSWang Nan 	}
1055ecfd7a9cSWang Nan 	return fd;
1056ecfd7a9cSWang Nan }
1057ecfd7a9cSWang Nan 
1058f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno;
1059f33cbe72SArnaldo Carvalho de Melo 
1060f33cbe72SArnaldo Carvalho de Melo /*
1061f33cbe72SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload will send a SIGUSR1
1062f33cbe72SArnaldo Carvalho de Melo  * if the fork fails, since we asked by setting its
1063f33cbe72SArnaldo Carvalho de Melo  * want_signal to true.
1064f33cbe72SArnaldo Carvalho de Melo  */
106545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused,
106645604710SNamhyung Kim 					siginfo_t *info,
1067f33cbe72SArnaldo Carvalho de Melo 					void *ucontext __maybe_unused)
1068f33cbe72SArnaldo Carvalho de Melo {
1069f33cbe72SArnaldo Carvalho de Melo 	workload_exec_errno = info->si_value.sival_int;
1070f33cbe72SArnaldo Carvalho de Melo 	done = 1;
1071f33cbe72SArnaldo Carvalho de Melo 	child_finished = 1;
1072f33cbe72SArnaldo Carvalho de Melo }
1073f33cbe72SArnaldo Carvalho de Melo 
10742dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig);
1075bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig);
10762dd6d8a1SAdrian Hunter 
107746bc29b9SAdrian Hunter int __weak
107846bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
107946bc29b9SAdrian Hunter 			    struct perf_tool *tool __maybe_unused,
108046bc29b9SAdrian Hunter 			    perf_event__handler_t process __maybe_unused,
108146bc29b9SAdrian Hunter 			    struct machine *machine __maybe_unused)
108246bc29b9SAdrian Hunter {
108346bc29b9SAdrian Hunter 	return 0;
108446bc29b9SAdrian Hunter }
108546bc29b9SAdrian Hunter 
1086ee667f94SWang Nan static const struct perf_event_mmap_page *
1087ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist)
1088ee667f94SWang Nan {
1089b2cb615dSWang Nan 	if (evlist) {
1090b2cb615dSWang Nan 		if (evlist->mmap && evlist->mmap[0].base)
1091ee667f94SWang Nan 			return evlist->mmap[0].base;
10920b72d69aSWang Nan 		if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base)
10930b72d69aSWang Nan 			return evlist->overwrite_mmap[0].base;
1094b2cb615dSWang Nan 	}
1095ee667f94SWang Nan 	return NULL;
1096ee667f94SWang Nan }
1097ee667f94SWang Nan 
1098c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
1099c45628b0SWang Nan {
1100ee667f94SWang Nan 	const struct perf_event_mmap_page *pc;
1101ee667f94SWang Nan 
1102ee667f94SWang Nan 	pc = perf_evlist__pick_pc(rec->evlist);
1103ee667f94SWang Nan 	if (pc)
1104ee667f94SWang Nan 		return pc;
1105c45628b0SWang Nan 	return NULL;
1106c45628b0SWang Nan }
1107c45628b0SWang Nan 
11084ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail)
1109c45c86ebSWang Nan {
1110c45c86ebSWang Nan 	struct perf_session *session = rec->session;
1111c45c86ebSWang Nan 	struct machine *machine = &session->machines.host;
11128ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1113c45c86ebSWang Nan 	struct record_opts *opts = &rec->opts;
1114c45c86ebSWang Nan 	struct perf_tool *tool = &rec->tool;
11158ceb41d7SJiri Olsa 	int fd = perf_data__fd(data);
1116c45c86ebSWang Nan 	int err = 0;
1117c45c86ebSWang Nan 
11184ea648aeSWang Nan 	if (rec->opts.tail_synthesize != tail)
11194ea648aeSWang Nan 		return 0;
11204ea648aeSWang Nan 
11218ceb41d7SJiri Olsa 	if (data->is_pipe) {
1122a2015516SJiri Olsa 		/*
1123a2015516SJiri Olsa 		 * We need to synthesize events first, because some
1124a2015516SJiri Olsa 		 * features works on top of them (on report side).
1125a2015516SJiri Olsa 		 */
1126318ec184SJiri Olsa 		err = perf_event__synthesize_attrs(tool, rec->evlist,
1127c45c86ebSWang Nan 						   process_synthesized_event);
1128c45c86ebSWang Nan 		if (err < 0) {
1129c45c86ebSWang Nan 			pr_err("Couldn't synthesize attrs.\n");
1130c45c86ebSWang Nan 			goto out;
1131c45c86ebSWang Nan 		}
1132c45c86ebSWang Nan 
1133a2015516SJiri Olsa 		err = perf_event__synthesize_features(tool, session, rec->evlist,
1134a2015516SJiri Olsa 						      process_synthesized_event);
1135a2015516SJiri Olsa 		if (err < 0) {
1136a2015516SJiri Olsa 			pr_err("Couldn't synthesize features.\n");
1137a2015516SJiri Olsa 			return err;
1138a2015516SJiri Olsa 		}
1139a2015516SJiri Olsa 
1140c45c86ebSWang Nan 		if (have_tracepoints(&rec->evlist->entries)) {
1141c45c86ebSWang Nan 			/*
1142c45c86ebSWang Nan 			 * FIXME err <= 0 here actually means that
1143c45c86ebSWang Nan 			 * there were no tracepoints so its not really
1144c45c86ebSWang Nan 			 * an error, just that we don't need to
1145c45c86ebSWang Nan 			 * synthesize anything.  We really have to
1146c45c86ebSWang Nan 			 * return this more properly and also
1147c45c86ebSWang Nan 			 * propagate errors that now are calling die()
1148c45c86ebSWang Nan 			 */
1149c45c86ebSWang Nan 			err = perf_event__synthesize_tracing_data(tool,	fd, rec->evlist,
1150c45c86ebSWang Nan 								  process_synthesized_event);
1151c45c86ebSWang Nan 			if (err <= 0) {
1152c45c86ebSWang Nan 				pr_err("Couldn't record tracing data.\n");
1153c45c86ebSWang Nan 				goto out;
1154c45c86ebSWang Nan 			}
1155c45c86ebSWang Nan 			rec->bytes_written += err;
1156c45c86ebSWang Nan 		}
1157c45c86ebSWang Nan 	}
1158c45c86ebSWang Nan 
1159c45628b0SWang Nan 	err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
116046bc29b9SAdrian Hunter 					  process_synthesized_event, machine);
116146bc29b9SAdrian Hunter 	if (err)
116246bc29b9SAdrian Hunter 		goto out;
116346bc29b9SAdrian Hunter 
1164c45c86ebSWang Nan 	if (rec->opts.full_auxtrace) {
1165c45c86ebSWang Nan 		err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
1166c45c86ebSWang Nan 					session, process_synthesized_event);
1167c45c86ebSWang Nan 		if (err)
1168c45c86ebSWang Nan 			goto out;
1169c45c86ebSWang Nan 	}
1170c45c86ebSWang Nan 
11716c443954SArnaldo Carvalho de Melo 	if (!perf_evlist__exclude_kernel(rec->evlist)) {
1172c45c86ebSWang Nan 		err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
1173c45c86ebSWang Nan 							 machine);
1174c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
1175c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1176c45c86ebSWang Nan 				   "Check /proc/kallsyms permission or run as root.\n");
1177c45c86ebSWang Nan 
1178c45c86ebSWang Nan 		err = perf_event__synthesize_modules(tool, process_synthesized_event,
1179c45c86ebSWang Nan 						     machine);
1180c45c86ebSWang Nan 		WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
1181c45c86ebSWang Nan 				   "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
1182c45c86ebSWang Nan 				   "Check /proc/modules permission or run as root.\n");
11836c443954SArnaldo Carvalho de Melo 	}
1184c45c86ebSWang Nan 
1185c45c86ebSWang Nan 	if (perf_guest) {
1186c45c86ebSWang Nan 		machines__process_guests(&session->machines,
1187c45c86ebSWang Nan 					 perf_event__synthesize_guest_os, tool);
1188c45c86ebSWang Nan 	}
1189c45c86ebSWang Nan 
1190bfd8f72cSAndi Kleen 	err = perf_event__synthesize_extra_attr(&rec->tool,
1191bfd8f72cSAndi Kleen 						rec->evlist,
1192bfd8f72cSAndi Kleen 						process_synthesized_event,
1193bfd8f72cSAndi Kleen 						data->is_pipe);
1194bfd8f72cSAndi Kleen 	if (err)
1195bfd8f72cSAndi Kleen 		goto out;
1196bfd8f72cSAndi Kleen 
1197373565d2SAndi Kleen 	err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads,
1198373565d2SAndi Kleen 						 process_synthesized_event,
1199373565d2SAndi Kleen 						NULL);
1200373565d2SAndi Kleen 	if (err < 0) {
1201373565d2SAndi Kleen 		pr_err("Couldn't synthesize thread map.\n");
1202373565d2SAndi Kleen 		return err;
1203373565d2SAndi Kleen 	}
1204373565d2SAndi Kleen 
1205373565d2SAndi Kleen 	err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus,
1206373565d2SAndi Kleen 					     process_synthesized_event, NULL);
1207373565d2SAndi Kleen 	if (err < 0) {
1208373565d2SAndi Kleen 		pr_err("Couldn't synthesize cpu map.\n");
1209373565d2SAndi Kleen 		return err;
1210373565d2SAndi Kleen 	}
1211373565d2SAndi Kleen 
1212e5416950SSong Liu 	err = perf_event__synthesize_bpf_events(session, process_synthesized_event,
12137b612e29SSong Liu 						machine, opts);
12147b612e29SSong Liu 	if (err < 0)
12157b612e29SSong Liu 		pr_warning("Couldn't synthesize bpf events.\n");
12167b612e29SSong Liu 
1217c45c86ebSWang Nan 	err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
1218c45c86ebSWang Nan 					    process_synthesized_event, opts->sample_address,
12193fcb10e4SMark Drayton 					    1);
1220c45c86ebSWang Nan out:
1221c45c86ebSWang Nan 	return err;
1222c45c86ebSWang Nan }
1223c45c86ebSWang Nan 
12248c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv)
122586470930SIngo Molnar {
122657706abcSDavid Ahern 	int err;
122745604710SNamhyung Kim 	int status = 0;
12288b412664SPeter Zijlstra 	unsigned long waking = 0;
122946be604bSZhang, Yanmin 	const bool forks = argc > 0;
123045694aa7SArnaldo Carvalho de Melo 	struct perf_tool *tool = &rec->tool;
1231b4006796SArnaldo Carvalho de Melo 	struct record_opts *opts = &rec->opts;
12328ceb41d7SJiri Olsa 	struct perf_data *data = &rec->data;
1233d20deb64SArnaldo Carvalho de Melo 	struct perf_session *session;
12346dcf45efSArnaldo Carvalho de Melo 	bool disabled = false, draining = false;
1235657ee553SSong Liu 	struct perf_evlist *sb_evlist = NULL;
123642aa276fSNamhyung Kim 	int fd;
1237d3c8c08eSAlexey Budankov 	float ratio = 0;
123886470930SIngo Molnar 
123945604710SNamhyung Kim 	atexit(record__sig_exit);
1240f5970550SPeter Zijlstra 	signal(SIGCHLD, sig_handler);
1241f5970550SPeter Zijlstra 	signal(SIGINT, sig_handler);
1242804f7ac7SDavid Ahern 	signal(SIGTERM, sig_handler);
1243a074865eSWang Nan 	signal(SIGSEGV, sigsegv_handler);
1244c0bdc1c4SWang Nan 
1245f3b3614aSHari Bathini 	if (rec->opts.record_namespaces)
1246f3b3614aSHari Bathini 		tool->namespace_events = true;
1247f3b3614aSHari Bathini 
1248dc0c6127SJiri Olsa 	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
12492dd6d8a1SAdrian Hunter 		signal(SIGUSR2, snapshot_sig_handler);
12503c1cb7e3SWang Nan 		if (rec->opts.auxtrace_snapshot_mode)
12515f9cf599SWang Nan 			trigger_on(&auxtrace_snapshot_trigger);
1252dc0c6127SJiri Olsa 		if (rec->switch_output.enabled)
12533c1cb7e3SWang Nan 			trigger_on(&switch_output_trigger);
1254c0bdc1c4SWang Nan 	} else {
12552dd6d8a1SAdrian Hunter 		signal(SIGUSR2, SIG_IGN);
1256c0bdc1c4SWang Nan 	}
1257f5970550SPeter Zijlstra 
12588ceb41d7SJiri Olsa 	session = perf_session__new(data, false, tool);
125994c744b6SArnaldo Carvalho de Melo 	if (session == NULL) {
1260ffa91880SAdrien BAK 		pr_err("Perf session creation failed.\n");
1261a9a70bbcSArnaldo Carvalho de Melo 		return -1;
1262a9a70bbcSArnaldo Carvalho de Melo 	}
1263a9a70bbcSArnaldo Carvalho de Melo 
12648ceb41d7SJiri Olsa 	fd = perf_data__fd(data);
1265d20deb64SArnaldo Carvalho de Melo 	rec->session = session;
1266d20deb64SArnaldo Carvalho de Melo 
1267*5d7f4116SAlexey Budankov 	if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) {
1268*5d7f4116SAlexey Budankov 		pr_err("Compression initialization failed.\n");
1269*5d7f4116SAlexey Budankov 		return -1;
1270*5d7f4116SAlexey Budankov 	}
1271*5d7f4116SAlexey Budankov 
1272*5d7f4116SAlexey Budankov 	session->header.env.comp_type  = PERF_COMP_ZSTD;
1273*5d7f4116SAlexey Budankov 	session->header.env.comp_level = rec->opts.comp_level;
1274*5d7f4116SAlexey Budankov 
12758c6f45a7SArnaldo Carvalho de Melo 	record__init_features(rec);
1276330aa675SStephane Eranian 
1277cf790516SAlexey Budankov 	if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
1278cf790516SAlexey Budankov 		session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
1279cf790516SAlexey Budankov 
1280d4db3f16SArnaldo Carvalho de Melo 	if (forks) {
12813e2be2daSArnaldo Carvalho de Melo 		err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
12828ceb41d7SJiri Olsa 						    argv, data->is_pipe,
1283735f7e0bSArnaldo Carvalho de Melo 						    workload_exec_failed_signal);
128435b9d88eSArnaldo Carvalho de Melo 		if (err < 0) {
128535b9d88eSArnaldo Carvalho de Melo 			pr_err("Couldn't run the workload!\n");
128645604710SNamhyung Kim 			status = err;
128735b9d88eSArnaldo Carvalho de Melo 			goto out_delete_session;
1288856e9660SPeter Zijlstra 		}
1289856e9660SPeter Zijlstra 	}
1290856e9660SPeter Zijlstra 
1291ad46e48cSJiri Olsa 	/*
1292ad46e48cSJiri Olsa 	 * If we have just single event and are sending data
1293ad46e48cSJiri Olsa 	 * through pipe, we need to force the ids allocation,
1294ad46e48cSJiri Olsa 	 * because we synthesize event name through the pipe
1295ad46e48cSJiri Olsa 	 * and need the id for that.
1296ad46e48cSJiri Olsa 	 */
1297ad46e48cSJiri Olsa 	if (data->is_pipe && rec->evlist->nr_entries == 1)
1298ad46e48cSJiri Olsa 		rec->opts.sample_id = true;
1299ad46e48cSJiri Olsa 
13008c6f45a7SArnaldo Carvalho de Melo 	if (record__open(rec) != 0) {
13018d3eca20SDavid Ahern 		err = -1;
130245604710SNamhyung Kim 		goto out_child;
13038d3eca20SDavid Ahern 	}
130442e1fd80SAlexey Budankov 	session->header.env.comp_mmap_len = session->evlist->mmap_len;
130586470930SIngo Molnar 
13068690a2a7SWang Nan 	err = bpf__apply_obj_config();
13078690a2a7SWang Nan 	if (err) {
13088690a2a7SWang Nan 		char errbuf[BUFSIZ];
13098690a2a7SWang Nan 
13108690a2a7SWang Nan 		bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
13118690a2a7SWang Nan 		pr_err("ERROR: Apply config to BPF failed: %s\n",
13128690a2a7SWang Nan 			 errbuf);
13138690a2a7SWang Nan 		goto out_child;
13148690a2a7SWang Nan 	}
13158690a2a7SWang Nan 
1316cca8482cSAdrian Hunter 	/*
1317cca8482cSAdrian Hunter 	 * Normally perf_session__new would do this, but it doesn't have the
1318cca8482cSAdrian Hunter 	 * evlist.
1319cca8482cSAdrian Hunter 	 */
1320cca8482cSAdrian Hunter 	if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
1321cca8482cSAdrian Hunter 		pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
1322cca8482cSAdrian Hunter 		rec->tool.ordered_events = false;
1323cca8482cSAdrian Hunter 	}
1324cca8482cSAdrian Hunter 
13253e2be2daSArnaldo Carvalho de Melo 	if (!rec->evlist->nr_groups)
1326a8bb559bSNamhyung Kim 		perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
1327a8bb559bSNamhyung Kim 
13288ceb41d7SJiri Olsa 	if (data->is_pipe) {
132942aa276fSNamhyung Kim 		err = perf_header__write_pipe(fd);
1330529870e3STom Zanussi 		if (err < 0)
133145604710SNamhyung Kim 			goto out_child;
1332563aecb2SJiri Olsa 	} else {
133342aa276fSNamhyung Kim 		err = perf_session__write_header(session, rec->evlist, fd, false);
1334d5eed904SArnaldo Carvalho de Melo 		if (err < 0)
133545604710SNamhyung Kim 			goto out_child;
1336d5eed904SArnaldo Carvalho de Melo 	}
13377c6a1c65SPeter Zijlstra 
1338d3665498SDavid Ahern 	if (!rec->no_buildid
1339e20960c0SRobert Richter 	    && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
1340d3665498SDavid Ahern 		pr_err("Couldn't generate buildids. "
1341e20960c0SRobert Richter 		       "Use --no-buildid to profile anyway.\n");
13428d3eca20SDavid Ahern 		err = -1;
134345604710SNamhyung Kim 		goto out_child;
1344e20960c0SRobert Richter 	}
1345e20960c0SRobert Richter 
1346d56354dcSSong Liu 	if (!opts->no_bpf_event)
1347d56354dcSSong Liu 		bpf_event__add_sb_event(&sb_evlist, &session->header.env);
1348d56354dcSSong Liu 
1349657ee553SSong Liu 	if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) {
1350657ee553SSong Liu 		pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
1351657ee553SSong Liu 		opts->no_bpf_event = true;
1352657ee553SSong Liu 	}
1353657ee553SSong Liu 
13544ea648aeSWang Nan 	err = record__synthesize(rec, false);
1355c45c86ebSWang Nan 	if (err < 0)
135645604710SNamhyung Kim 		goto out_child;
13578d3eca20SDavid Ahern 
1358d20deb64SArnaldo Carvalho de Melo 	if (rec->realtime_prio) {
135986470930SIngo Molnar 		struct sched_param param;
136086470930SIngo Molnar 
1361d20deb64SArnaldo Carvalho de Melo 		param.sched_priority = rec->realtime_prio;
136286470930SIngo Molnar 		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
13636beba7adSArnaldo Carvalho de Melo 			pr_err("Could not set realtime priority.\n");
13648d3eca20SDavid Ahern 			err = -1;
136545604710SNamhyung Kim 			goto out_child;
136686470930SIngo Molnar 		}
136786470930SIngo Molnar 	}
136886470930SIngo Molnar 
1369774cb499SJiri Olsa 	/*
1370774cb499SJiri Olsa 	 * When perf is starting the traced process, all the events
1371774cb499SJiri Olsa 	 * (apart from group members) have enable_on_exec=1 set,
1372774cb499SJiri Olsa 	 * so don't spoil it by prematurely enabling them.
1373774cb499SJiri Olsa 	 */
13746619a53eSAndi Kleen 	if (!target__none(&opts->target) && !opts->initial_delay)
13753e2be2daSArnaldo Carvalho de Melo 		perf_evlist__enable(rec->evlist);
1376764e16a3SDavid Ahern 
1377856e9660SPeter Zijlstra 	/*
1378856e9660SPeter Zijlstra 	 * Let the child rip
1379856e9660SPeter Zijlstra 	 */
1380e803cf97SNamhyung Kim 	if (forks) {
138120a8a3cfSJiri Olsa 		struct machine *machine = &session->machines.host;
1382e5bed564SNamhyung Kim 		union perf_event *event;
1383e907caf3SHari Bathini 		pid_t tgid;
1384e5bed564SNamhyung Kim 
1385e5bed564SNamhyung Kim 		event = malloc(sizeof(event->comm) + machine->id_hdr_size);
1386e5bed564SNamhyung Kim 		if (event == NULL) {
1387e5bed564SNamhyung Kim 			err = -ENOMEM;
1388e5bed564SNamhyung Kim 			goto out_child;
1389e5bed564SNamhyung Kim 		}
1390e5bed564SNamhyung Kim 
1391e803cf97SNamhyung Kim 		/*
1392e803cf97SNamhyung Kim 		 * Some H/W events are generated before COMM event
1393e803cf97SNamhyung Kim 		 * which is emitted during exec(), so perf script
1394e803cf97SNamhyung Kim 		 * cannot see a correct process name for those events.
1395e803cf97SNamhyung Kim 		 * Synthesize COMM event to prevent it.
1396e803cf97SNamhyung Kim 		 */
1397e907caf3SHari Bathini 		tgid = perf_event__synthesize_comm(tool, event,
1398e803cf97SNamhyung Kim 						   rec->evlist->workload.pid,
1399e803cf97SNamhyung Kim 						   process_synthesized_event,
1400e803cf97SNamhyung Kim 						   machine);
1401e5bed564SNamhyung Kim 		free(event);
1402e803cf97SNamhyung Kim 
1403e907caf3SHari Bathini 		if (tgid == -1)
1404e907caf3SHari Bathini 			goto out_child;
1405e907caf3SHari Bathini 
1406e907caf3SHari Bathini 		event = malloc(sizeof(event->namespaces) +
1407e907caf3SHari Bathini 			       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
1408e907caf3SHari Bathini 			       machine->id_hdr_size);
1409e907caf3SHari Bathini 		if (event == NULL) {
1410e907caf3SHari Bathini 			err = -ENOMEM;
1411e907caf3SHari Bathini 			goto out_child;
1412e907caf3SHari Bathini 		}
1413e907caf3SHari Bathini 
1414e907caf3SHari Bathini 		/*
1415e907caf3SHari Bathini 		 * Synthesize NAMESPACES event for the command specified.
1416e907caf3SHari Bathini 		 */
1417e907caf3SHari Bathini 		perf_event__synthesize_namespaces(tool, event,
1418e907caf3SHari Bathini 						  rec->evlist->workload.pid,
1419e907caf3SHari Bathini 						  tgid, process_synthesized_event,
1420e907caf3SHari Bathini 						  machine);
1421e907caf3SHari Bathini 		free(event);
1422e907caf3SHari Bathini 
14233e2be2daSArnaldo Carvalho de Melo 		perf_evlist__start_workload(rec->evlist);
1424e803cf97SNamhyung Kim 	}
1425856e9660SPeter Zijlstra 
14266619a53eSAndi Kleen 	if (opts->initial_delay) {
14270693e680SArnaldo Carvalho de Melo 		usleep(opts->initial_delay * USEC_PER_MSEC);
14286619a53eSAndi Kleen 		perf_evlist__enable(rec->evlist);
14296619a53eSAndi Kleen 	}
14306619a53eSAndi Kleen 
14315f9cf599SWang Nan 	trigger_ready(&auxtrace_snapshot_trigger);
14323c1cb7e3SWang Nan 	trigger_ready(&switch_output_trigger);
1433a074865eSWang Nan 	perf_hooks__invoke_record_start();
1434649c48a9SPeter Zijlstra 	for (;;) {
14359f065194SYang Shi 		unsigned long long hits = rec->samples;
143686470930SIngo Molnar 
143705737464SWang Nan 		/*
143805737464SWang Nan 		 * rec->evlist->bkw_mmap_state is possible to be
143905737464SWang Nan 		 * BKW_MMAP_EMPTY here: when done == true and
144005737464SWang Nan 		 * hits != rec->samples in previous round.
144105737464SWang Nan 		 *
144205737464SWang Nan 		 * perf_evlist__toggle_bkw_mmap ensure we never
144305737464SWang Nan 		 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
144405737464SWang Nan 		 */
144505737464SWang Nan 		if (trigger_is_hit(&switch_output_trigger) || done || draining)
144605737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
144705737464SWang Nan 
1448470530bbSAlexey Budankov 		if (record__mmap_read_all(rec, false) < 0) {
14495f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
14503c1cb7e3SWang Nan 			trigger_error(&switch_output_trigger);
14518d3eca20SDavid Ahern 			err = -1;
145245604710SNamhyung Kim 			goto out_child;
14538d3eca20SDavid Ahern 		}
145486470930SIngo Molnar 
14552dd6d8a1SAdrian Hunter 		if (auxtrace_record__snapshot_started) {
14562dd6d8a1SAdrian Hunter 			auxtrace_record__snapshot_started = 0;
14575f9cf599SWang Nan 			if (!trigger_is_error(&auxtrace_snapshot_trigger))
14582dd6d8a1SAdrian Hunter 				record__read_auxtrace_snapshot(rec);
14595f9cf599SWang Nan 			if (trigger_is_error(&auxtrace_snapshot_trigger)) {
14602dd6d8a1SAdrian Hunter 				pr_err("AUX area tracing snapshot failed\n");
14612dd6d8a1SAdrian Hunter 				err = -1;
14622dd6d8a1SAdrian Hunter 				goto out_child;
14632dd6d8a1SAdrian Hunter 			}
14642dd6d8a1SAdrian Hunter 		}
14652dd6d8a1SAdrian Hunter 
14663c1cb7e3SWang Nan 		if (trigger_is_hit(&switch_output_trigger)) {
146705737464SWang Nan 			/*
146805737464SWang Nan 			 * If switch_output_trigger is hit, the data in
146905737464SWang Nan 			 * overwritable ring buffer should have been collected,
147005737464SWang Nan 			 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
147105737464SWang Nan 			 *
147205737464SWang Nan 			 * If SIGUSR2 raise after or during record__mmap_read_all(),
147305737464SWang Nan 			 * record__mmap_read_all() didn't collect data from
147405737464SWang Nan 			 * overwritable ring buffer. Read again.
147505737464SWang Nan 			 */
147605737464SWang Nan 			if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
147705737464SWang Nan 				continue;
14783c1cb7e3SWang Nan 			trigger_ready(&switch_output_trigger);
14793c1cb7e3SWang Nan 
148005737464SWang Nan 			/*
148105737464SWang Nan 			 * Reenable events in overwrite ring buffer after
148205737464SWang Nan 			 * record__mmap_read_all(): we should have collected
148305737464SWang Nan 			 * data from it.
148405737464SWang Nan 			 */
148505737464SWang Nan 			perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
148605737464SWang Nan 
14873c1cb7e3SWang Nan 			if (!quiet)
14883c1cb7e3SWang Nan 				fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
14893c1cb7e3SWang Nan 					waking);
14903c1cb7e3SWang Nan 			waking = 0;
14913c1cb7e3SWang Nan 			fd = record__switch_output(rec, false);
14923c1cb7e3SWang Nan 			if (fd < 0) {
14933c1cb7e3SWang Nan 				pr_err("Failed to switch to new file\n");
14943c1cb7e3SWang Nan 				trigger_error(&switch_output_trigger);
14953c1cb7e3SWang Nan 				err = fd;
14963c1cb7e3SWang Nan 				goto out_child;
14973c1cb7e3SWang Nan 			}
1498bfacbe3bSJiri Olsa 
1499bfacbe3bSJiri Olsa 			/* re-arm the alarm */
1500bfacbe3bSJiri Olsa 			if (rec->switch_output.time)
1501bfacbe3bSJiri Olsa 				alarm(rec->switch_output.time);
15023c1cb7e3SWang Nan 		}
15033c1cb7e3SWang Nan 
1504d20deb64SArnaldo Carvalho de Melo 		if (hits == rec->samples) {
15056dcf45efSArnaldo Carvalho de Melo 			if (done || draining)
1506649c48a9SPeter Zijlstra 				break;
1507f66a889dSArnaldo Carvalho de Melo 			err = perf_evlist__poll(rec->evlist, -1);
1508a515114fSJiri Olsa 			/*
1509a515114fSJiri Olsa 			 * Propagate error, only if there's any. Ignore positive
1510a515114fSJiri Olsa 			 * number of returned events and interrupt error.
1511a515114fSJiri Olsa 			 */
1512a515114fSJiri Olsa 			if (err > 0 || (err < 0 && errno == EINTR))
151345604710SNamhyung Kim 				err = 0;
15148b412664SPeter Zijlstra 			waking++;
15156dcf45efSArnaldo Carvalho de Melo 
15166dcf45efSArnaldo Carvalho de Melo 			if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
15176dcf45efSArnaldo Carvalho de Melo 				draining = true;
15188b412664SPeter Zijlstra 		}
15198b412664SPeter Zijlstra 
1520774cb499SJiri Olsa 		/*
1521774cb499SJiri Olsa 		 * When perf is starting the traced process, at the end events
1522774cb499SJiri Olsa 		 * die with the process and we wait for that. Thus no need to
1523774cb499SJiri Olsa 		 * disable events in this case.
1524774cb499SJiri Olsa 		 */
1525602ad878SArnaldo Carvalho de Melo 		if (done && !disabled && !target__none(&opts->target)) {
15265f9cf599SWang Nan 			trigger_off(&auxtrace_snapshot_trigger);
15273e2be2daSArnaldo Carvalho de Melo 			perf_evlist__disable(rec->evlist);
15282711926aSJiri Olsa 			disabled = true;
15292711926aSJiri Olsa 		}
15308b412664SPeter Zijlstra 	}
15315f9cf599SWang Nan 	trigger_off(&auxtrace_snapshot_trigger);
15323c1cb7e3SWang Nan 	trigger_off(&switch_output_trigger);
15338b412664SPeter Zijlstra 
1534f33cbe72SArnaldo Carvalho de Melo 	if (forks && workload_exec_errno) {
153535550da3SMasami Hiramatsu 		char msg[STRERR_BUFSIZE];
1536c8b5f2c9SArnaldo Carvalho de Melo 		const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
1537f33cbe72SArnaldo Carvalho de Melo 		pr_err("Workload failed: %s\n", emsg);
1538f33cbe72SArnaldo Carvalho de Melo 		err = -1;
153945604710SNamhyung Kim 		goto out_child;
1540f33cbe72SArnaldo Carvalho de Melo 	}
1541f33cbe72SArnaldo Carvalho de Melo 
1542e3d59112SNamhyung Kim 	if (!quiet)
15438b412664SPeter Zijlstra 		fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
154486470930SIngo Molnar 
15454ea648aeSWang Nan 	if (target__none(&rec->opts.target))
15464ea648aeSWang Nan 		record__synthesize_workload(rec, true);
15474ea648aeSWang Nan 
154845604710SNamhyung Kim out_child:
1549470530bbSAlexey Budankov 	record__mmap_read_all(rec, true);
1550d3d1af6fSAlexey Budankov 	record__aio_mmap_read_sync(rec);
1551d3d1af6fSAlexey Budankov 
1552d3c8c08eSAlexey Budankov 	if (rec->session->bytes_transferred && rec->session->bytes_compressed) {
1553d3c8c08eSAlexey Budankov 		ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed;
1554d3c8c08eSAlexey Budankov 		session->header.env.comp_ratio = ratio + 0.5;
1555d3c8c08eSAlexey Budankov 	}
1556d3c8c08eSAlexey Budankov 
155745604710SNamhyung Kim 	if (forks) {
155845604710SNamhyung Kim 		int exit_status;
155945604710SNamhyung Kim 
156045604710SNamhyung Kim 		if (!child_finished)
156145604710SNamhyung Kim 			kill(rec->evlist->workload.pid, SIGTERM);
156245604710SNamhyung Kim 
156345604710SNamhyung Kim 		wait(&exit_status);
156445604710SNamhyung Kim 
156545604710SNamhyung Kim 		if (err < 0)
156645604710SNamhyung Kim 			status = err;
156745604710SNamhyung Kim 		else if (WIFEXITED(exit_status))
156845604710SNamhyung Kim 			status = WEXITSTATUS(exit_status);
156945604710SNamhyung Kim 		else if (WIFSIGNALED(exit_status))
157045604710SNamhyung Kim 			signr = WTERMSIG(exit_status);
157145604710SNamhyung Kim 	} else
157245604710SNamhyung Kim 		status = err;
157345604710SNamhyung Kim 
15744ea648aeSWang Nan 	record__synthesize(rec, true);
1575e3d59112SNamhyung Kim 	/* this will be recalculated during process_buildids() */
1576e3d59112SNamhyung Kim 	rec->samples = 0;
1577e3d59112SNamhyung Kim 
1578ecfd7a9cSWang Nan 	if (!err) {
1579ecfd7a9cSWang Nan 		if (!rec->timestamp_filename) {
1580e1ab48baSWang Nan 			record__finish_output(rec);
1581ecfd7a9cSWang Nan 		} else {
1582ecfd7a9cSWang Nan 			fd = record__switch_output(rec, true);
1583ecfd7a9cSWang Nan 			if (fd < 0) {
1584ecfd7a9cSWang Nan 				status = fd;
1585ecfd7a9cSWang Nan 				goto out_delete_session;
1586ecfd7a9cSWang Nan 			}
1587ecfd7a9cSWang Nan 		}
1588ecfd7a9cSWang Nan 	}
158939d17dacSArnaldo Carvalho de Melo 
1590a074865eSWang Nan 	perf_hooks__invoke_record_end();
1591a074865eSWang Nan 
1592e3d59112SNamhyung Kim 	if (!err && !quiet) {
1593e3d59112SNamhyung Kim 		char samples[128];
1594ecfd7a9cSWang Nan 		const char *postfix = rec->timestamp_filename ?
1595ecfd7a9cSWang Nan 					".<timestamp>" : "";
1596e3d59112SNamhyung Kim 
1597ef149c25SAdrian Hunter 		if (rec->samples && !rec->opts.full_auxtrace)
1598e3d59112SNamhyung Kim 			scnprintf(samples, sizeof(samples),
1599e3d59112SNamhyung Kim 				  " (%" PRIu64 " samples)", rec->samples);
1600e3d59112SNamhyung Kim 		else
1601e3d59112SNamhyung Kim 			samples[0] = '\0';
1602e3d59112SNamhyung Kim 
1603d3c8c08eSAlexey Budankov 		fprintf(stderr,	"[ perf record: Captured and wrote %.3f MB %s%s%s",
16048ceb41d7SJiri Olsa 			perf_data__size(data) / 1024.0 / 1024.0,
16052d4f2799SJiri Olsa 			data->path, postfix, samples);
1606d3c8c08eSAlexey Budankov 		if (ratio) {
1607d3c8c08eSAlexey Budankov 			fprintf(stderr,	", compressed (original %.3f MB, ratio is %.3f)",
1608d3c8c08eSAlexey Budankov 					rec->session->bytes_transferred / 1024.0 / 1024.0,
1609d3c8c08eSAlexey Budankov 					ratio);
1610d3c8c08eSAlexey Budankov 		}
1611d3c8c08eSAlexey Budankov 		fprintf(stderr, " ]\n");
1612e3d59112SNamhyung Kim 	}
1613e3d59112SNamhyung Kim 
161439d17dacSArnaldo Carvalho de Melo out_delete_session:
1615*5d7f4116SAlexey Budankov 	zstd_fini(&session->zstd_data);
161639d17dacSArnaldo Carvalho de Melo 	perf_session__delete(session);
1617657ee553SSong Liu 
1618657ee553SSong Liu 	if (!opts->no_bpf_event)
1619657ee553SSong Liu 		perf_evlist__stop_sb_thread(sb_evlist);
162045604710SNamhyung Kim 	return status;
162186470930SIngo Molnar }
162286470930SIngo Molnar 
16230883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain)
162409b0fd45SJiri Olsa {
1625aad2b21cSKan Liang 	static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
1626a601fdffSJiri Olsa 
16270883e820SArnaldo Carvalho de Melo 	pr_debug("callchain: type %s\n", str[callchain->record_mode]);
162826d33022SJiri Olsa 
16290883e820SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_DWARF)
163009b0fd45SJiri Olsa 		pr_debug("callchain: stack dump size %d\n",
16310883e820SArnaldo Carvalho de Melo 			 callchain->dump_size);
16320883e820SArnaldo Carvalho de Melo }
16330883e820SArnaldo Carvalho de Melo 
16340883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record,
16350883e820SArnaldo Carvalho de Melo 				 struct callchain_param *callchain,
16360883e820SArnaldo Carvalho de Melo 				 const char *arg, bool unset)
16370883e820SArnaldo Carvalho de Melo {
16380883e820SArnaldo Carvalho de Melo 	int ret;
16390883e820SArnaldo Carvalho de Melo 	callchain->enabled = !unset;
16400883e820SArnaldo Carvalho de Melo 
16410883e820SArnaldo Carvalho de Melo 	/* --no-call-graph */
16420883e820SArnaldo Carvalho de Melo 	if (unset) {
16430883e820SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_NONE;
16440883e820SArnaldo Carvalho de Melo 		pr_debug("callchain: disabled\n");
16450883e820SArnaldo Carvalho de Melo 		return 0;
16460883e820SArnaldo Carvalho de Melo 	}
16470883e820SArnaldo Carvalho de Melo 
16480883e820SArnaldo Carvalho de Melo 	ret = parse_callchain_record_opt(arg, callchain);
16490883e820SArnaldo Carvalho de Melo 	if (!ret) {
16500883e820SArnaldo Carvalho de Melo 		/* Enable data address sampling for DWARF unwind. */
16510883e820SArnaldo Carvalho de Melo 		if (callchain->record_mode == CALLCHAIN_DWARF)
16520883e820SArnaldo Carvalho de Melo 			record->sample_address = true;
16530883e820SArnaldo Carvalho de Melo 		callchain_debug(callchain);
16540883e820SArnaldo Carvalho de Melo 	}
16550883e820SArnaldo Carvalho de Melo 
16560883e820SArnaldo Carvalho de Melo 	return ret;
165709b0fd45SJiri Olsa }
165809b0fd45SJiri Olsa 
1659c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt,
166009b0fd45SJiri Olsa 			       const char *arg,
166109b0fd45SJiri Olsa 			       int unset)
166209b0fd45SJiri Olsa {
16630883e820SArnaldo Carvalho de Melo 	return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
166426d33022SJiri Olsa }
166526d33022SJiri Olsa 
1666c421e80bSKan Liang int record_callchain_opt(const struct option *opt,
166709b0fd45SJiri Olsa 			 const char *arg __maybe_unused,
166809b0fd45SJiri Olsa 			 int unset __maybe_unused)
166909b0fd45SJiri Olsa {
16702ddd5c04SArnaldo Carvalho de Melo 	struct callchain_param *callchain = opt->value;
1671c421e80bSKan Liang 
16722ddd5c04SArnaldo Carvalho de Melo 	callchain->enabled = true;
167309b0fd45SJiri Olsa 
16742ddd5c04SArnaldo Carvalho de Melo 	if (callchain->record_mode == CALLCHAIN_NONE)
16752ddd5c04SArnaldo Carvalho de Melo 		callchain->record_mode = CALLCHAIN_FP;
1676eb853e80SJiri Olsa 
16772ddd5c04SArnaldo Carvalho de Melo 	callchain_debug(callchain);
167809b0fd45SJiri Olsa 	return 0;
167909b0fd45SJiri Olsa }
168009b0fd45SJiri Olsa 
1681eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb)
1682eb853e80SJiri Olsa {
16837a29c087SNamhyung Kim 	struct record *rec = cb;
16847a29c087SNamhyung Kim 
16857a29c087SNamhyung Kim 	if (!strcmp(var, "record.build-id")) {
16867a29c087SNamhyung Kim 		if (!strcmp(value, "cache"))
16877a29c087SNamhyung Kim 			rec->no_buildid_cache = false;
16887a29c087SNamhyung Kim 		else if (!strcmp(value, "no-cache"))
16897a29c087SNamhyung Kim 			rec->no_buildid_cache = true;
16907a29c087SNamhyung Kim 		else if (!strcmp(value, "skip"))
16917a29c087SNamhyung Kim 			rec->no_buildid = true;
16927a29c087SNamhyung Kim 		else
16937a29c087SNamhyung Kim 			return -1;
16947a29c087SNamhyung Kim 		return 0;
16957a29c087SNamhyung Kim 	}
1696cff17205SYisheng Xie 	if (!strcmp(var, "record.call-graph")) {
1697cff17205SYisheng Xie 		var = "call-graph.record-mode";
1698eb853e80SJiri Olsa 		return perf_default_config(var, value, cb);
1699eb853e80SJiri Olsa 	}
170093f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
170193f20c0fSAlexey Budankov 	if (!strcmp(var, "record.aio")) {
170293f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = strtol(value, NULL, 0);
170393f20c0fSAlexey Budankov 		if (!rec->opts.nr_cblocks)
170493f20c0fSAlexey Budankov 			rec->opts.nr_cblocks = nr_cblocks_default;
170593f20c0fSAlexey Budankov 	}
170693f20c0fSAlexey Budankov #endif
1707eb853e80SJiri Olsa 
1708cff17205SYisheng Xie 	return 0;
1709cff17205SYisheng Xie }
1710cff17205SYisheng Xie 
1711814c8c38SPeter Zijlstra struct clockid_map {
1712814c8c38SPeter Zijlstra 	const char *name;
1713814c8c38SPeter Zijlstra 	int clockid;
1714814c8c38SPeter Zijlstra };
1715814c8c38SPeter Zijlstra 
1716814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c)	\
1717814c8c38SPeter Zijlstra 	{ .name = n, .clockid = (c), }
1718814c8c38SPeter Zijlstra 
1719814c8c38SPeter Zijlstra #define CLOCKID_END	{ .name = NULL, }
1720814c8c38SPeter Zijlstra 
1721814c8c38SPeter Zijlstra 
1722814c8c38SPeter Zijlstra /*
1723814c8c38SPeter Zijlstra  * Add the missing ones, we need to build on many distros...
1724814c8c38SPeter Zijlstra  */
1725814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW
1726814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4
1727814c8c38SPeter Zijlstra #endif
1728814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME
1729814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7
1730814c8c38SPeter Zijlstra #endif
1731814c8c38SPeter Zijlstra #ifndef CLOCK_TAI
1732814c8c38SPeter Zijlstra #define CLOCK_TAI 11
1733814c8c38SPeter Zijlstra #endif
1734814c8c38SPeter Zijlstra 
1735814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = {
1736814c8c38SPeter Zijlstra 	/* available for all events, NMI safe */
1737814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
1738814c8c38SPeter Zijlstra 	CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
1739814c8c38SPeter Zijlstra 
1740814c8c38SPeter Zijlstra 	/* available for some events */
1741814c8c38SPeter Zijlstra 	CLOCKID_MAP("realtime", CLOCK_REALTIME),
1742814c8c38SPeter Zijlstra 	CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
1743814c8c38SPeter Zijlstra 	CLOCKID_MAP("tai", CLOCK_TAI),
1744814c8c38SPeter Zijlstra 
1745814c8c38SPeter Zijlstra 	/* available for the lazy */
1746814c8c38SPeter Zijlstra 	CLOCKID_MAP("mono", CLOCK_MONOTONIC),
1747814c8c38SPeter Zijlstra 	CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
1748814c8c38SPeter Zijlstra 	CLOCKID_MAP("real", CLOCK_REALTIME),
1749814c8c38SPeter Zijlstra 	CLOCKID_MAP("boot", CLOCK_BOOTTIME),
1750814c8c38SPeter Zijlstra 
1751814c8c38SPeter Zijlstra 	CLOCKID_END,
1752814c8c38SPeter Zijlstra };
1753814c8c38SPeter Zijlstra 
1754cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
1755cf790516SAlexey Budankov {
1756cf790516SAlexey Budankov 	struct timespec res;
1757cf790516SAlexey Budankov 
1758cf790516SAlexey Budankov 	*res_ns = 0;
1759cf790516SAlexey Budankov 	if (!clock_getres(clk_id, &res))
1760cf790516SAlexey Budankov 		*res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
1761cf790516SAlexey Budankov 	else
1762cf790516SAlexey Budankov 		pr_warning("WARNING: Failed to determine specified clock resolution.\n");
1763cf790516SAlexey Budankov 
1764cf790516SAlexey Budankov 	return 0;
1765cf790516SAlexey Budankov }
1766cf790516SAlexey Budankov 
1767814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset)
1768814c8c38SPeter Zijlstra {
1769814c8c38SPeter Zijlstra 	struct record_opts *opts = (struct record_opts *)opt->value;
1770814c8c38SPeter Zijlstra 	const struct clockid_map *cm;
1771814c8c38SPeter Zijlstra 	const char *ostr = str;
1772814c8c38SPeter Zijlstra 
1773814c8c38SPeter Zijlstra 	if (unset) {
1774814c8c38SPeter Zijlstra 		opts->use_clockid = 0;
1775814c8c38SPeter Zijlstra 		return 0;
1776814c8c38SPeter Zijlstra 	}
1777814c8c38SPeter Zijlstra 
1778814c8c38SPeter Zijlstra 	/* no arg passed */
1779814c8c38SPeter Zijlstra 	if (!str)
1780814c8c38SPeter Zijlstra 		return 0;
1781814c8c38SPeter Zijlstra 
1782814c8c38SPeter Zijlstra 	/* no setting it twice */
1783814c8c38SPeter Zijlstra 	if (opts->use_clockid)
1784814c8c38SPeter Zijlstra 		return -1;
1785814c8c38SPeter Zijlstra 
1786814c8c38SPeter Zijlstra 	opts->use_clockid = true;
1787814c8c38SPeter Zijlstra 
1788814c8c38SPeter Zijlstra 	/* if its a number, we're done */
1789814c8c38SPeter Zijlstra 	if (sscanf(str, "%d", &opts->clockid) == 1)
1790cf790516SAlexey Budankov 		return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
1791814c8c38SPeter Zijlstra 
1792814c8c38SPeter Zijlstra 	/* allow a "CLOCK_" prefix to the name */
1793814c8c38SPeter Zijlstra 	if (!strncasecmp(str, "CLOCK_", 6))
1794814c8c38SPeter Zijlstra 		str += 6;
1795814c8c38SPeter Zijlstra 
1796814c8c38SPeter Zijlstra 	for (cm = clockids; cm->name; cm++) {
1797814c8c38SPeter Zijlstra 		if (!strcasecmp(str, cm->name)) {
1798814c8c38SPeter Zijlstra 			opts->clockid = cm->clockid;
1799cf790516SAlexey Budankov 			return get_clockid_res(opts->clockid,
1800cf790516SAlexey Budankov 					       &opts->clockid_res_ns);
1801814c8c38SPeter Zijlstra 		}
1802814c8c38SPeter Zijlstra 	}
1803814c8c38SPeter Zijlstra 
1804814c8c38SPeter Zijlstra 	opts->use_clockid = false;
1805814c8c38SPeter Zijlstra 	ui__warning("unknown clockid %s, check man page\n", ostr);
1806814c8c38SPeter Zijlstra 	return -1;
1807814c8c38SPeter Zijlstra }
1808814c8c38SPeter Zijlstra 
1809f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset)
1810f4fe11b7SAlexey Budankov {
1811f4fe11b7SAlexey Budankov 	struct record_opts *opts = (struct record_opts *)opt->value;
1812f4fe11b7SAlexey Budankov 
1813f4fe11b7SAlexey Budankov 	if (unset || !str)
1814f4fe11b7SAlexey Budankov 		return 0;
1815f4fe11b7SAlexey Budankov 
1816f4fe11b7SAlexey Budankov 	if (!strcasecmp(str, "node"))
1817f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_NODE;
1818f4fe11b7SAlexey Budankov 	else if (!strcasecmp(str, "cpu"))
1819f4fe11b7SAlexey Budankov 		opts->affinity = PERF_AFFINITY_CPU;
1820f4fe11b7SAlexey Budankov 
1821f4fe11b7SAlexey Budankov 	return 0;
1822f4fe11b7SAlexey Budankov }
1823f4fe11b7SAlexey Budankov 
1824e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt,
1825e9db1310SAdrian Hunter 				    const char *str,
1826e9db1310SAdrian Hunter 				    int unset __maybe_unused)
1827e9db1310SAdrian Hunter {
1828e9db1310SAdrian Hunter 	struct record_opts *opts = opt->value;
1829e9db1310SAdrian Hunter 	char *s, *p;
1830e9db1310SAdrian Hunter 	unsigned int mmap_pages;
1831e9db1310SAdrian Hunter 	int ret;
1832e9db1310SAdrian Hunter 
1833e9db1310SAdrian Hunter 	if (!str)
1834e9db1310SAdrian Hunter 		return -EINVAL;
1835e9db1310SAdrian Hunter 
1836e9db1310SAdrian Hunter 	s = strdup(str);
1837e9db1310SAdrian Hunter 	if (!s)
1838e9db1310SAdrian Hunter 		return -ENOMEM;
1839e9db1310SAdrian Hunter 
1840e9db1310SAdrian Hunter 	p = strchr(s, ',');
1841e9db1310SAdrian Hunter 	if (p)
1842e9db1310SAdrian Hunter 		*p = '\0';
1843e9db1310SAdrian Hunter 
1844e9db1310SAdrian Hunter 	if (*s) {
1845e9db1310SAdrian Hunter 		ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s);
1846e9db1310SAdrian Hunter 		if (ret)
1847e9db1310SAdrian Hunter 			goto out_free;
1848e9db1310SAdrian Hunter 		opts->mmap_pages = mmap_pages;
1849e9db1310SAdrian Hunter 	}
1850e9db1310SAdrian Hunter 
1851e9db1310SAdrian Hunter 	if (!p) {
1852e9db1310SAdrian Hunter 		ret = 0;
1853e9db1310SAdrian Hunter 		goto out_free;
1854e9db1310SAdrian Hunter 	}
1855e9db1310SAdrian Hunter 
1856e9db1310SAdrian Hunter 	ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1);
1857e9db1310SAdrian Hunter 	if (ret)
1858e9db1310SAdrian Hunter 		goto out_free;
1859e9db1310SAdrian Hunter 
1860e9db1310SAdrian Hunter 	opts->auxtrace_mmap_pages = mmap_pages;
1861e9db1310SAdrian Hunter 
1862e9db1310SAdrian Hunter out_free:
1863e9db1310SAdrian Hunter 	free(s);
1864e9db1310SAdrian Hunter 	return ret;
1865e9db1310SAdrian Hunter }
1866e9db1310SAdrian Hunter 
18670c582449SJiri Olsa static void switch_output_size_warn(struct record *rec)
18680c582449SJiri Olsa {
18690c582449SJiri Olsa 	u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
18700c582449SJiri Olsa 	struct switch_output *s = &rec->switch_output;
18710c582449SJiri Olsa 
18720c582449SJiri Olsa 	wakeup_size /= 2;
18730c582449SJiri Olsa 
18740c582449SJiri Olsa 	if (s->size < wakeup_size) {
18750c582449SJiri Olsa 		char buf[100];
18760c582449SJiri Olsa 
18770c582449SJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
18780c582449SJiri Olsa 		pr_warning("WARNING: switch-output data size lower than "
18790c582449SJiri Olsa 			   "wakeup kernel buffer size (%s) "
18800c582449SJiri Olsa 			   "expect bigger perf.data sizes\n", buf);
18810c582449SJiri Olsa 	}
18820c582449SJiri Olsa }
18830c582449SJiri Olsa 
1884cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec)
1885cb4e1ebbSJiri Olsa {
1886cb4e1ebbSJiri Olsa 	struct switch_output *s = &rec->switch_output;
1887dc0c6127SJiri Olsa 	static struct parse_tag tags_size[] = {
1888dc0c6127SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
1889dc0c6127SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
1890dc0c6127SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
1891dc0c6127SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
1892dc0c6127SJiri Olsa 		{ .tag  = 0 },
1893dc0c6127SJiri Olsa 	};
1894bfacbe3bSJiri Olsa 	static struct parse_tag tags_time[] = {
1895bfacbe3bSJiri Olsa 		{ .tag  = 's', .mult = 1        },
1896bfacbe3bSJiri Olsa 		{ .tag  = 'm', .mult = 60       },
1897bfacbe3bSJiri Olsa 		{ .tag  = 'h', .mult = 60*60    },
1898bfacbe3bSJiri Olsa 		{ .tag  = 'd', .mult = 60*60*24 },
1899bfacbe3bSJiri Olsa 		{ .tag  = 0 },
1900bfacbe3bSJiri Olsa 	};
1901dc0c6127SJiri Olsa 	unsigned long val;
1902cb4e1ebbSJiri Olsa 
1903cb4e1ebbSJiri Olsa 	if (!s->set)
1904cb4e1ebbSJiri Olsa 		return 0;
1905cb4e1ebbSJiri Olsa 
1906cb4e1ebbSJiri Olsa 	if (!strcmp(s->str, "signal")) {
1907cb4e1ebbSJiri Olsa 		s->signal = true;
1908cb4e1ebbSJiri Olsa 		pr_debug("switch-output with SIGUSR2 signal\n");
1909dc0c6127SJiri Olsa 		goto enabled;
1910dc0c6127SJiri Olsa 	}
1911dc0c6127SJiri Olsa 
1912dc0c6127SJiri Olsa 	val = parse_tag_value(s->str, tags_size);
1913dc0c6127SJiri Olsa 	if (val != (unsigned long) -1) {
1914dc0c6127SJiri Olsa 		s->size = val;
1915dc0c6127SJiri Olsa 		pr_debug("switch-output with %s size threshold\n", s->str);
1916dc0c6127SJiri Olsa 		goto enabled;
1917cb4e1ebbSJiri Olsa 	}
1918cb4e1ebbSJiri Olsa 
1919bfacbe3bSJiri Olsa 	val = parse_tag_value(s->str, tags_time);
1920bfacbe3bSJiri Olsa 	if (val != (unsigned long) -1) {
1921bfacbe3bSJiri Olsa 		s->time = val;
1922bfacbe3bSJiri Olsa 		pr_debug("switch-output with %s time threshold (%lu seconds)\n",
1923bfacbe3bSJiri Olsa 			 s->str, s->time);
1924bfacbe3bSJiri Olsa 		goto enabled;
1925bfacbe3bSJiri Olsa 	}
1926bfacbe3bSJiri Olsa 
1927cb4e1ebbSJiri Olsa 	return -1;
1928dc0c6127SJiri Olsa 
1929dc0c6127SJiri Olsa enabled:
1930dc0c6127SJiri Olsa 	rec->timestamp_filename = true;
1931dc0c6127SJiri Olsa 	s->enabled              = true;
19320c582449SJiri Olsa 
19330c582449SJiri Olsa 	if (s->size && !rec->opts.no_buffering)
19340c582449SJiri Olsa 		switch_output_size_warn(rec);
19350c582449SJiri Olsa 
1936dc0c6127SJiri Olsa 	return 0;
1937cb4e1ebbSJiri Olsa }
1938cb4e1ebbSJiri Olsa 
1939e5b2c207SNamhyung Kim static const char * const __record_usage[] = {
194086470930SIngo Molnar 	"perf record [<options>] [<command>]",
194186470930SIngo Molnar 	"perf record [<options>] -- <command> [<options>]",
194286470930SIngo Molnar 	NULL
194386470930SIngo Molnar };
1944e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage;
194586470930SIngo Molnar 
1946d20deb64SArnaldo Carvalho de Melo /*
19478c6f45a7SArnaldo Carvalho de Melo  * XXX Ideally would be local to cmd_record() and passed to a record__new
19488c6f45a7SArnaldo Carvalho de Melo  * because we need to have access to it in record__exit, that is called
1949d20deb64SArnaldo Carvalho de Melo  * after cmd_record() exits, but since record_options need to be accessible to
1950d20deb64SArnaldo Carvalho de Melo  * builtin-script, leave it here.
1951d20deb64SArnaldo Carvalho de Melo  *
1952d20deb64SArnaldo Carvalho de Melo  * At least we don't ouch it in all the other functions here directly.
1953d20deb64SArnaldo Carvalho de Melo  *
1954d20deb64SArnaldo Carvalho de Melo  * Just say no to tons of global variables, sigh.
1955d20deb64SArnaldo Carvalho de Melo  */
19568c6f45a7SArnaldo Carvalho de Melo static struct record record = {
1957d20deb64SArnaldo Carvalho de Melo 	.opts = {
19588affc2b8SAndi Kleen 		.sample_time	     = true,
1959d20deb64SArnaldo Carvalho de Melo 		.mmap_pages	     = UINT_MAX,
1960d20deb64SArnaldo Carvalho de Melo 		.user_freq	     = UINT_MAX,
1961d20deb64SArnaldo Carvalho de Melo 		.user_interval	     = ULLONG_MAX,
1962447a6013SArnaldo Carvalho de Melo 		.freq		     = 4000,
1963d1cb9fceSNamhyung Kim 		.target		     = {
1964d1cb9fceSNamhyung Kim 			.uses_mmap   = true,
19653aa5939dSAdrian Hunter 			.default_per_cpu = true,
1966d1cb9fceSNamhyung Kim 		},
1967470530bbSAlexey Budankov 		.mmap_flush          = MMAP_FLUSH_DEFAULT,
1968d20deb64SArnaldo Carvalho de Melo 	},
1969e3d59112SNamhyung Kim 	.tool = {
1970e3d59112SNamhyung Kim 		.sample		= process_sample_event,
1971e3d59112SNamhyung Kim 		.fork		= perf_event__process_fork,
1972cca8482cSAdrian Hunter 		.exit		= perf_event__process_exit,
1973e3d59112SNamhyung Kim 		.comm		= perf_event__process_comm,
1974f3b3614aSHari Bathini 		.namespaces	= perf_event__process_namespaces,
1975e3d59112SNamhyung Kim 		.mmap		= perf_event__process_mmap,
1976e3d59112SNamhyung Kim 		.mmap2		= perf_event__process_mmap2,
1977cca8482cSAdrian Hunter 		.ordered_events	= true,
1978e3d59112SNamhyung Kim 	},
1979d20deb64SArnaldo Carvalho de Melo };
19807865e817SFrederic Weisbecker 
198176a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
198276a26549SNamhyung Kim 	"\n\t\t\t\tDefault: fp";
198361eaa3beSArnaldo Carvalho de Melo 
19840aab2136SWang Nan static bool dry_run;
19850aab2136SWang Nan 
1986d20deb64SArnaldo Carvalho de Melo /*
1987d20deb64SArnaldo Carvalho de Melo  * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1988d20deb64SArnaldo Carvalho de Melo  * with it and switch to use the library functions in perf_evlist that came
1989b4006796SArnaldo Carvalho de Melo  * from builtin-record.c, i.e. use record_opts,
1990d20deb64SArnaldo Carvalho de Melo  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
1991d20deb64SArnaldo Carvalho de Melo  * using pipes, etc.
1992d20deb64SArnaldo Carvalho de Melo  */
1993efd21307SJiri Olsa static struct option __record_options[] = {
1994d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('e', "event", &record.evlist, "event",
199586470930SIngo Molnar 		     "event selector. use 'perf list' to list available events",
1996f120f9d5SJiri Olsa 		     parse_events_option),
1997d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK(0, "filter", &record.evlist, "filter",
1998c171b552SLi Zefan 		     "event filter", parse_filter),
19994ba1faa1SWang Nan 	OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist,
20004ba1faa1SWang Nan 			   NULL, "don't record events from perf itself",
20014ba1faa1SWang Nan 			   exclude_perf),
2002bea03405SNamhyung Kim 	OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
2003d6d901c2SZhang, Yanmin 		    "record events on existing process id"),
2004bea03405SNamhyung Kim 	OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
2005d6d901c2SZhang, Yanmin 		    "record events on existing thread id"),
2006d20deb64SArnaldo Carvalho de Melo 	OPT_INTEGER('r', "realtime", &record.realtime_prio,
200786470930SIngo Molnar 		    "collect data with this RT SCHED_FIFO priority"),
2008509051eaSArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
2009acac03faSKirill Smelkov 		    "collect data without buffering"),
2010d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
2011daac07b2SFrederic Weisbecker 		    "collect raw sample records from all opened counters"),
2012bea03405SNamhyung Kim 	OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
201386470930SIngo Molnar 			    "system-wide collection from all CPUs"),
2014bea03405SNamhyung Kim 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
2015c45c6ea2SStephane Eranian 		    "list of cpus to monitor"),
2016d20deb64SArnaldo Carvalho de Melo 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
20172d4f2799SJiri Olsa 	OPT_STRING('o', "output", &record.data.path, "file",
201886470930SIngo Molnar 		    "output file name"),
201969e7e5b0SAdrian Hunter 	OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
202069e7e5b0SAdrian Hunter 			&record.opts.no_inherit_set,
20212e6cdf99SStephane Eranian 			"child tasks do not inherit counters"),
20224ea648aeSWang Nan 	OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
20234ea648aeSWang Nan 		    "synthesize non-sample events at the end of output"),
2024626a6b78SWang Nan 	OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
202571184c6aSSong Liu 	OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"),
2026b09c2364SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
2027b09c2364SArnaldo Carvalho de Melo 		    "Fail if the specified frequency can't be used"),
202867230479SArnaldo Carvalho de Melo 	OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
202967230479SArnaldo Carvalho de Melo 		     "profile at this frequency",
203067230479SArnaldo Carvalho de Melo 		      record__parse_freq),
2031e9db1310SAdrian Hunter 	OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
2032e9db1310SAdrian Hunter 		     "number of mmap data pages and AUX area tracing mmap pages",
2033e9db1310SAdrian Hunter 		     record__parse_mmap_pages),
2034470530bbSAlexey Budankov 	OPT_CALLBACK(0, "mmap-flush", &record.opts, "number",
2035470530bbSAlexey Budankov 		     "Minimal number of bytes that is extracted from mmap data pages (default: 1)",
2036470530bbSAlexey Budankov 		     record__mmap_flush_parse),
2037d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN(0, "group", &record.opts.group,
203843bece79SLin Ming 		    "put the counters into a counter group"),
20392ddd5c04SArnaldo Carvalho de Melo 	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
204009b0fd45SJiri Olsa 			   NULL, "enables call-graph recording" ,
204109b0fd45SJiri Olsa 			   &record_callchain_opt),
204209b0fd45SJiri Olsa 	OPT_CALLBACK(0, "call-graph", &record.opts,
204376a26549SNamhyung Kim 		     "record_mode[,record_size]", record_callchain_help,
204409b0fd45SJiri Olsa 		     &record_parse_callchain_opt),
2045c0555642SIan Munsie 	OPT_INCR('v', "verbose", &verbose,
20463da297a6SIngo Molnar 		    "be more verbose (show counter open errors, etc)"),
2047b44308f5SArnaldo Carvalho de Melo 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
2048d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
2049649c48a9SPeter Zijlstra 		    "per thread counts"),
205056100321SPeter Zijlstra 	OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
20513b0a5daaSKan Liang 	OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr,
20523b0a5daaSKan Liang 		    "Record the sample physical addresses"),
2053b6f35ed7SJiri Olsa 	OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
20543abebc55SAdrian Hunter 	OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
20553abebc55SAdrian Hunter 			&record.opts.sample_time_set,
20563abebc55SAdrian Hunter 			"Record the sample timestamps"),
2057f290aa1fSJiri Olsa 	OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set,
2058f290aa1fSJiri Olsa 			"Record the sample period"),
2059d20deb64SArnaldo Carvalho de Melo 	OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
2060649c48a9SPeter Zijlstra 		    "don't sample"),
2061d2db9a98SWang Nan 	OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
2062d2db9a98SWang Nan 			&record.no_buildid_cache_set,
2063a1ac1d3cSStephane Eranian 			"do not update the buildid cache"),
2064d2db9a98SWang Nan 	OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
2065d2db9a98SWang Nan 			&record.no_buildid_set,
2066baa2f6ceSArnaldo Carvalho de Melo 			"do not collect buildids in perf.data"),
2067d20deb64SArnaldo Carvalho de Melo 	OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
2068023695d9SStephane Eranian 		     "monitor event in cgroup name only",
2069023695d9SStephane Eranian 		     parse_cgroups),
2070a6205a35SArnaldo Carvalho de Melo 	OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
20716619a53eSAndi Kleen 		  "ms to wait before starting measurement after program start"),
2072bea03405SNamhyung Kim 	OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
2073bea03405SNamhyung Kim 		   "user to profile"),
2074a5aabdacSStephane Eranian 
2075a5aabdacSStephane Eranian 	OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
2076a5aabdacSStephane Eranian 		     "branch any", "sample any taken branches",
2077a5aabdacSStephane Eranian 		     parse_branch_stack),
2078a5aabdacSStephane Eranian 
2079a5aabdacSStephane Eranian 	OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack,
2080a5aabdacSStephane Eranian 		     "branch filter mask", "branch stack filter modes",
2081bdfebd84SRoberto Agostino Vitillo 		     parse_branch_stack),
208205484298SAndi Kleen 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
208305484298SAndi Kleen 		    "sample by weight (on special events only)"),
2084475eeab9SAndi Kleen 	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
2085475eeab9SAndi Kleen 		    "sample transaction flags (special events only)"),
20863aa5939dSAdrian Hunter 	OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
20873aa5939dSAdrian Hunter 		    "use per-thread mmaps"),
2088bcc84ec6SStephane Eranian 	OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register",
2089bcc84ec6SStephane Eranian 		    "sample selected machine registers on interrupt,"
20908e5bc76fSArnaldo Carvalho de Melo 		    " use '-I?' to list register names", parse_regs),
209184c41742SAndi Kleen 	OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register",
209284c41742SAndi Kleen 		    "sample selected machine registers on interrupt,"
20938e5bc76fSArnaldo Carvalho de Melo 		    " use '-I?' to list register names", parse_regs),
209485c273d2SAndi Kleen 	OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
209585c273d2SAndi Kleen 		    "Record running/enabled time of read (:S) events"),
2096814c8c38SPeter Zijlstra 	OPT_CALLBACK('k', "clockid", &record.opts,
2097814c8c38SPeter Zijlstra 	"clockid", "clockid to use for events, see clock_gettime()",
2098814c8c38SPeter Zijlstra 	parse_clockid),
20992dd6d8a1SAdrian Hunter 	OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts,
21002dd6d8a1SAdrian Hunter 			  "opts", "AUX area tracing Snapshot Mode", ""),
21013fcb10e4SMark Drayton 	OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
21029d9cad76SKan Liang 			"per thread proc mmap processing timeout in ms"),
2103f3b3614aSHari Bathini 	OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
2104f3b3614aSHari Bathini 		    "Record namespaces events"),
2105b757bb09SAdrian Hunter 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
2106b757bb09SAdrian Hunter 		    "Record context switch events"),
210785723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
210885723885SJiri Olsa 			 "Configure all used events to run in kernel space.",
210985723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
211085723885SJiri Olsa 	OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
211185723885SJiri Olsa 			 "Configure all used events to run in user space.",
211285723885SJiri Olsa 			 PARSE_OPT_EXCLUSIVE),
211371dc2326SWang Nan 	OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
211471dc2326SWang Nan 		   "clang binary to use for compiling BPF scriptlets"),
211571dc2326SWang Nan 	OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
211671dc2326SWang Nan 		   "options passed to clang when compiling BPF scriptlets"),
21177efe0e03SHe Kuang 	OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
21187efe0e03SHe Kuang 		   "file", "vmlinux pathname"),
21196156681bSNamhyung Kim 	OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
21206156681bSNamhyung Kim 		    "Record build-id of all DSOs regardless of hits"),
2121ecfd7a9cSWang Nan 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
2122ecfd7a9cSWang Nan 		    "append timestamp to output filename"),
212368588bafSJin Yao 	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
212468588bafSJin Yao 		    "Record timestamp boundary (time of first/last samples)"),
2125cb4e1ebbSJiri Olsa 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
2126c38dab7dSAndi Kleen 			  &record.switch_output.set, "signal or size[BKMG] or time[smhd]",
2127c38dab7dSAndi Kleen 			  "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold",
2128dc0c6127SJiri Olsa 			  "signal"),
212903724b2eSAndi Kleen 	OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
213003724b2eSAndi Kleen 		   "Limit number of switch output generated files"),
21310aab2136SWang Nan 	OPT_BOOLEAN(0, "dry-run", &dry_run,
21320aab2136SWang Nan 		    "Parse options then exit"),
2133d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT
213493f20c0fSAlexey Budankov 	OPT_CALLBACK_OPTARG(0, "aio", &record.opts,
213593f20c0fSAlexey Budankov 		     &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)",
2136d3d1af6fSAlexey Budankov 		     record__aio_parse),
2137d3d1af6fSAlexey Budankov #endif
2138f4fe11b7SAlexey Budankov 	OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu",
2139f4fe11b7SAlexey Budankov 		     "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer",
2140f4fe11b7SAlexey Budankov 		     record__parse_affinity),
214186470930SIngo Molnar 	OPT_END()
214286470930SIngo Molnar };
214386470930SIngo Molnar 
2144e5b2c207SNamhyung Kim struct option *record_options = __record_options;
2145e5b2c207SNamhyung Kim 
2146b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv)
214786470930SIngo Molnar {
2148ef149c25SAdrian Hunter 	int err;
21498c6f45a7SArnaldo Carvalho de Melo 	struct record *rec = &record;
215016ad2ffbSNamhyung Kim 	char errbuf[BUFSIZ];
215186470930SIngo Molnar 
215267230479SArnaldo Carvalho de Melo 	setlocale(LC_ALL, "");
215367230479SArnaldo Carvalho de Melo 
215448e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT
215548e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
215648e1cab1SWang Nan 	set_nobuild('\0', "clang-path", true);
215748e1cab1SWang Nan 	set_nobuild('\0', "clang-opt", true);
215848e1cab1SWang Nan # undef set_nobuild
215948e1cab1SWang Nan #endif
216048e1cab1SWang Nan 
21617efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE
21627efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT)
21637efe0e03SHe Kuang #  define REASON  "NO_DWARF=1"
21647efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT)
21657efe0e03SHe Kuang #  define REASON  "NO_LIBBPF=1"
21667efe0e03SHe Kuang # else
21677efe0e03SHe Kuang #  define REASON  "this architecture doesn't support BPF prologue"
21687efe0e03SHe Kuang # endif
21697efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c)
21707efe0e03SHe Kuang 	set_nobuild('\0', "vmlinux", true);
21717efe0e03SHe Kuang # undef set_nobuild
21727efe0e03SHe Kuang # undef REASON
21737efe0e03SHe Kuang #endif
21747efe0e03SHe Kuang 
21759d2ed645SAlexey Budankov 	CPU_ZERO(&rec->affinity_mask);
21769d2ed645SAlexey Budankov 	rec->opts.affinity = PERF_AFFINITY_SYS;
21779d2ed645SAlexey Budankov 
21783e2be2daSArnaldo Carvalho de Melo 	rec->evlist = perf_evlist__new();
21793e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist == NULL)
2180361c99a6SArnaldo Carvalho de Melo 		return -ENOMEM;
2181361c99a6SArnaldo Carvalho de Melo 
2182ecc4c561SArnaldo Carvalho de Melo 	err = perf_config(perf_record_config, rec);
2183ecc4c561SArnaldo Carvalho de Melo 	if (err)
2184ecc4c561SArnaldo Carvalho de Melo 		return err;
2185eb853e80SJiri Olsa 
2186bca647aaSTom Zanussi 	argc = parse_options(argc, argv, record_options, record_usage,
2187a0541234SAnton Blanchard 			    PARSE_OPT_STOP_AT_NON_OPTION);
218868ba3235SNamhyung Kim 	if (quiet)
218968ba3235SNamhyung Kim 		perf_quiet_option();
2190483635a9SJiri Olsa 
2191483635a9SJiri Olsa 	/* Make system wide (-a) the default target. */
2192602ad878SArnaldo Carvalho de Melo 	if (!argc && target__none(&rec->opts.target))
2193483635a9SJiri Olsa 		rec->opts.target.system_wide = true;
219486470930SIngo Molnar 
2195bea03405SNamhyung Kim 	if (nr_cgroups && !rec->opts.target.system_wide) {
2196c7118369SNamhyung Kim 		usage_with_options_msg(record_usage, record_options,
2197c7118369SNamhyung Kim 			"cgroup monitoring only available in system-wide mode");
2198c7118369SNamhyung Kim 
2199023695d9SStephane Eranian 	}
2200b757bb09SAdrian Hunter 	if (rec->opts.record_switch_events &&
2201b757bb09SAdrian Hunter 	    !perf_can_record_switch_events()) {
2202c7118369SNamhyung Kim 		ui__error("kernel does not support recording context switch events\n");
2203c7118369SNamhyung Kim 		parse_options_usage(record_usage, record_options, "switch-events", 0);
2204c7118369SNamhyung Kim 		return -EINVAL;
2205b757bb09SAdrian Hunter 	}
2206023695d9SStephane Eranian 
2207cb4e1ebbSJiri Olsa 	if (switch_output_setup(rec)) {
2208cb4e1ebbSJiri Olsa 		parse_options_usage(record_usage, record_options, "switch-output", 0);
2209cb4e1ebbSJiri Olsa 		return -EINVAL;
2210cb4e1ebbSJiri Olsa 	}
2211cb4e1ebbSJiri Olsa 
2212bfacbe3bSJiri Olsa 	if (rec->switch_output.time) {
2213bfacbe3bSJiri Olsa 		signal(SIGALRM, alarm_sig_handler);
2214bfacbe3bSJiri Olsa 		alarm(rec->switch_output.time);
2215bfacbe3bSJiri Olsa 	}
2216bfacbe3bSJiri Olsa 
221703724b2eSAndi Kleen 	if (rec->switch_output.num_files) {
221803724b2eSAndi Kleen 		rec->switch_output.filenames = calloc(sizeof(char *),
221903724b2eSAndi Kleen 						      rec->switch_output.num_files);
222003724b2eSAndi Kleen 		if (!rec->switch_output.filenames)
222103724b2eSAndi Kleen 			return -EINVAL;
222203724b2eSAndi Kleen 	}
222303724b2eSAndi Kleen 
22241b36c03eSAdrian Hunter 	/*
22251b36c03eSAdrian Hunter 	 * Allow aliases to facilitate the lookup of symbols for address
22261b36c03eSAdrian Hunter 	 * filters. Refer to auxtrace_parse_filters().
22271b36c03eSAdrian Hunter 	 */
22281b36c03eSAdrian Hunter 	symbol_conf.allow_aliases = true;
22291b36c03eSAdrian Hunter 
22301b36c03eSAdrian Hunter 	symbol__init(NULL);
22311b36c03eSAdrian Hunter 
22324b5ea3bdSAdrian Hunter 	err = record__auxtrace_init(rec);
22331b36c03eSAdrian Hunter 	if (err)
22341b36c03eSAdrian Hunter 		goto out;
22351b36c03eSAdrian Hunter 
22360aab2136SWang Nan 	if (dry_run)
22375c01ad60SAdrian Hunter 		goto out;
22380aab2136SWang Nan 
2239d7888573SWang Nan 	err = bpf__setup_stdout(rec->evlist);
2240d7888573SWang Nan 	if (err) {
2241d7888573SWang Nan 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
2242d7888573SWang Nan 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
2243d7888573SWang Nan 			 errbuf);
22445c01ad60SAdrian Hunter 		goto out;
2245d7888573SWang Nan 	}
2246d7888573SWang Nan 
2247ef149c25SAdrian Hunter 	err = -ENOMEM;
2248ef149c25SAdrian Hunter 
22496c443954SArnaldo Carvalho de Melo 	if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(rec->evlist))
2250646aaea6SArnaldo Carvalho de Melo 		pr_warning(
2251646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
2252ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n"
2253646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n"
2254646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n"
2255646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n"
2256646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
2257646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n");
2258ec80fde7SArnaldo Carvalho de Melo 
22590c1d46a8SWang Nan 	if (rec->no_buildid_cache || rec->no_buildid) {
2260a1ac1d3cSStephane Eranian 		disable_buildid_cache();
2261dc0c6127SJiri Olsa 	} else if (rec->switch_output.enabled) {
22620c1d46a8SWang Nan 		/*
22630c1d46a8SWang Nan 		 * In 'perf record --switch-output', disable buildid
22640c1d46a8SWang Nan 		 * generation by default to reduce data file switching
22650c1d46a8SWang Nan 		 * overhead. Still generate buildid if they are required
22660c1d46a8SWang Nan 		 * explicitly using
22670c1d46a8SWang Nan 		 *
226860437ac0SJiri Olsa 		 *  perf record --switch-output --no-no-buildid \
22690c1d46a8SWang Nan 		 *              --no-no-buildid-cache
22700c1d46a8SWang Nan 		 *
22710c1d46a8SWang Nan 		 * Following code equals to:
22720c1d46a8SWang Nan 		 *
22730c1d46a8SWang Nan 		 * if ((rec->no_buildid || !rec->no_buildid_set) &&
22740c1d46a8SWang Nan 		 *     (rec->no_buildid_cache || !rec->no_buildid_cache_set))
22750c1d46a8SWang Nan 		 *         disable_buildid_cache();
22760c1d46a8SWang Nan 		 */
22770c1d46a8SWang Nan 		bool disable = true;
22780c1d46a8SWang Nan 
22790c1d46a8SWang Nan 		if (rec->no_buildid_set && !rec->no_buildid)
22800c1d46a8SWang Nan 			disable = false;
22810c1d46a8SWang Nan 		if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
22820c1d46a8SWang Nan 			disable = false;
22830c1d46a8SWang Nan 		if (disable) {
22840c1d46a8SWang Nan 			rec->no_buildid = true;
22850c1d46a8SWang Nan 			rec->no_buildid_cache = true;
22860c1d46a8SWang Nan 			disable_buildid_cache();
22870c1d46a8SWang Nan 		}
22880c1d46a8SWang Nan 	}
2289655000e7SArnaldo Carvalho de Melo 
22904ea648aeSWang Nan 	if (record.opts.overwrite)
22914ea648aeSWang Nan 		record.opts.tail_synthesize = true;
22924ea648aeSWang Nan 
22933e2be2daSArnaldo Carvalho de Melo 	if (rec->evlist->nr_entries == 0 &&
22944b4cd503SArnaldo Carvalho de Melo 	    __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
229569aad6f1SArnaldo Carvalho de Melo 		pr_err("Not enough memory for event selector list\n");
2296394c01edSAdrian Hunter 		goto out;
2297bbd36e5eSPeter Zijlstra 	}
229886470930SIngo Molnar 
229969e7e5b0SAdrian Hunter 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
230069e7e5b0SAdrian Hunter 		rec->opts.no_inherit = true;
230169e7e5b0SAdrian Hunter 
2302602ad878SArnaldo Carvalho de Melo 	err = target__validate(&rec->opts.target);
230316ad2ffbSNamhyung Kim 	if (err) {
2304602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
2305c3dec27bSJiri Olsa 		ui__warning("%s\n", errbuf);
230616ad2ffbSNamhyung Kim 	}
23074bd0f2d2SNamhyung Kim 
2308602ad878SArnaldo Carvalho de Melo 	err = target__parse_uid(&rec->opts.target);
230916ad2ffbSNamhyung Kim 	if (err) {
231016ad2ffbSNamhyung Kim 		int saved_errno = errno;
231116ad2ffbSNamhyung Kim 
2312602ad878SArnaldo Carvalho de Melo 		target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
23133780f488SNamhyung Kim 		ui__error("%s", errbuf);
231416ad2ffbSNamhyung Kim 
231516ad2ffbSNamhyung Kim 		err = -saved_errno;
2316394c01edSAdrian Hunter 		goto out;
231716ad2ffbSNamhyung Kim 	}
23180d37aa34SArnaldo Carvalho de Melo 
2319ca800068SMengting Zhang 	/* Enable ignoring missing threads when -u/-p option is defined. */
2320ca800068SMengting Zhang 	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
232123dc4f15SJiri Olsa 
232216ad2ffbSNamhyung Kim 	err = -ENOMEM;
23233e2be2daSArnaldo Carvalho de Melo 	if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
2324dd7927f4SArnaldo Carvalho de Melo 		usage_with_options(record_usage, record_options);
232569aad6f1SArnaldo Carvalho de Melo 
2326ef149c25SAdrian Hunter 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
2327ef149c25SAdrian Hunter 	if (err)
2328394c01edSAdrian Hunter 		goto out;
2329ef149c25SAdrian Hunter 
23306156681bSNamhyung Kim 	/*
23316156681bSNamhyung Kim 	 * We take all buildids when the file contains
23326156681bSNamhyung Kim 	 * AUX area tracing data because we do not decode the
23336156681bSNamhyung Kim 	 * trace because it would take too long.
23346156681bSNamhyung Kim 	 */
23356156681bSNamhyung Kim 	if (rec->opts.full_auxtrace)
23366156681bSNamhyung Kim 		rec->buildid_all = true;
23376156681bSNamhyung Kim 
2338b4006796SArnaldo Carvalho de Melo 	if (record_opts__config(&rec->opts)) {
233939d17dacSArnaldo Carvalho de Melo 		err = -EINVAL;
2340394c01edSAdrian Hunter 		goto out;
23417e4ff9e3SMike Galbraith 	}
23427e4ff9e3SMike Galbraith 
234393f20c0fSAlexey Budankov 	if (rec->opts.nr_cblocks > nr_cblocks_max)
234493f20c0fSAlexey Budankov 		rec->opts.nr_cblocks = nr_cblocks_max;
2345*5d7f4116SAlexey Budankov 	pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks);
2346d3d1af6fSAlexey Budankov 
23479d2ed645SAlexey Budankov 	pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]);
2348470530bbSAlexey Budankov 	pr_debug("mmap flush: %d\n", rec->opts.mmap_flush);
23499d2ed645SAlexey Budankov 
235051255a8aSAlexey Budankov 	if (rec->opts.comp_level > comp_level_max)
235151255a8aSAlexey Budankov 		rec->opts.comp_level = comp_level_max;
235251255a8aSAlexey Budankov 	pr_debug("comp level: %d\n", rec->opts.comp_level);
235351255a8aSAlexey Budankov 
2354d20deb64SArnaldo Carvalho de Melo 	err = __cmd_record(&record, argc, argv);
2355394c01edSAdrian Hunter out:
235645604710SNamhyung Kim 	perf_evlist__delete(rec->evlist);
2357d65a458bSArnaldo Carvalho de Melo 	symbol__exit();
2358ef149c25SAdrian Hunter 	auxtrace_record__free(rec->itr);
235939d17dacSArnaldo Carvalho de Melo 	return err;
236086470930SIngo Molnar }
23612dd6d8a1SAdrian Hunter 
23622dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused)
23632dd6d8a1SAdrian Hunter {
2364dc0c6127SJiri Olsa 	struct record *rec = &record;
2365dc0c6127SJiri Olsa 
23665f9cf599SWang Nan 	if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
23675f9cf599SWang Nan 		trigger_hit(&auxtrace_snapshot_trigger);
23682dd6d8a1SAdrian Hunter 		auxtrace_record__snapshot_started = 1;
23695f9cf599SWang Nan 		if (auxtrace_record__snapshot_start(record.itr))
23705f9cf599SWang Nan 			trigger_error(&auxtrace_snapshot_trigger);
23715f9cf599SWang Nan 	}
23723c1cb7e3SWang Nan 
2373dc0c6127SJiri Olsa 	if (switch_output_signal(rec))
23743c1cb7e3SWang Nan 		trigger_hit(&switch_output_trigger);
23752dd6d8a1SAdrian Hunter }
2376bfacbe3bSJiri Olsa 
2377bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused)
2378bfacbe3bSJiri Olsa {
2379bfacbe3bSJiri Olsa 	struct record *rec = &record;
2380bfacbe3bSJiri Olsa 
2381bfacbe3bSJiri Olsa 	if (switch_output_time(rec))
2382bfacbe3bSJiri Olsa 		trigger_hit(&switch_output_trigger);
2383bfacbe3bSJiri Olsa }
2384