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, ¶m)) { 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