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" 41c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h" 4258db1d6eSArnaldo Carvalho de Melo #include "util/units.h" 437b612e29SSong Liu #include "util/bpf-event.h" 44d8871ea7SWang Nan #include "asm/bug.h" 457c6a1c65SPeter Zijlstra 46a43783aeSArnaldo Carvalho de Melo #include <errno.h> 47fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 4867230479SArnaldo Carvalho de Melo #include <locale.h> 494208735dSArnaldo Carvalho de Melo #include <poll.h> 5086470930SIngo Molnar #include <unistd.h> 5186470930SIngo Molnar #include <sched.h> 529607ad3aSArnaldo Carvalho de Melo #include <signal.h> 53a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 544208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 550693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 5678da39faSBernhard Rosenkraenzer 571b43b704SJiri Olsa struct switch_output { 58dc0c6127SJiri Olsa bool enabled; 591b43b704SJiri Olsa bool signal; 60dc0c6127SJiri Olsa unsigned long size; 61bfacbe3bSJiri Olsa unsigned long time; 62cb4e1ebbSJiri Olsa const char *str; 63cb4e1ebbSJiri Olsa bool set; 641b43b704SJiri Olsa }; 651b43b704SJiri Olsa 668c6f45a7SArnaldo Carvalho de Melo struct record { 6745694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 68b4006796SArnaldo Carvalho de Melo struct record_opts opts; 69d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 708ceb41d7SJiri Olsa struct perf_data data; 71ef149c25SAdrian Hunter struct auxtrace_record *itr; 72d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 73d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 74d20deb64SArnaldo Carvalho de Melo int realtime_prio; 75d20deb64SArnaldo Carvalho de Melo bool no_buildid; 76d2db9a98SWang Nan bool no_buildid_set; 77d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 78d2db9a98SWang Nan bool no_buildid_cache_set; 796156681bSNamhyung Kim bool buildid_all; 80ecfd7a9cSWang Nan bool timestamp_filename; 8168588bafSJin Yao bool timestamp_boundary; 821b43b704SJiri Olsa struct switch_output switch_output; 839f065194SYang Shi unsigned long long samples; 84*9d2ed645SAlexey Budankov cpu_set_t affinity_mask; 850f82ebc4SArnaldo Carvalho de Melo }; 8686470930SIngo Molnar 87dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started; 88dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 89dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger); 90dc0c6127SJiri Olsa 91*9d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = { 92*9d2ed645SAlexey Budankov "SYS", "NODE", "CPU" 93*9d2ed645SAlexey Budankov }; 94*9d2ed645SAlexey Budankov 95dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec) 96dc0c6127SJiri Olsa { 97dc0c6127SJiri Olsa return rec->switch_output.signal && 98dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger); 99dc0c6127SJiri Olsa } 100dc0c6127SJiri Olsa 101dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec) 102dc0c6127SJiri Olsa { 103dc0c6127SJiri Olsa return rec->switch_output.size && 104dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) && 105dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size); 106dc0c6127SJiri Olsa } 107dc0c6127SJiri Olsa 108bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec) 109bfacbe3bSJiri Olsa { 110bfacbe3bSJiri Olsa return rec->switch_output.time && 111bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger); 112bfacbe3bSJiri Olsa } 113bfacbe3bSJiri Olsa 114ded2b8feSJiri Olsa static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused, 115ded2b8feSJiri Olsa void *bf, size_t size) 116f5970550SPeter Zijlstra { 117ded2b8feSJiri Olsa struct perf_data_file *file = &rec->session->data->file; 118ded2b8feSJiri Olsa 119ded2b8feSJiri Olsa if (perf_data_file__write(file, bf, size) < 0) { 1204f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 1218d3eca20SDavid Ahern return -1; 1228d3eca20SDavid Ahern } 123f5970550SPeter Zijlstra 124cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 125dc0c6127SJiri Olsa 126dc0c6127SJiri Olsa if (switch_output_size(rec)) 127dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger); 128dc0c6127SJiri Olsa 1298d3eca20SDavid Ahern return 0; 130f5970550SPeter Zijlstra } 131f5970550SPeter Zijlstra 132d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 133d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd, 134d3d1af6fSAlexey Budankov void *buf, size_t size, off_t off) 135d3d1af6fSAlexey Budankov { 136d3d1af6fSAlexey Budankov int rc; 137d3d1af6fSAlexey Budankov 138d3d1af6fSAlexey Budankov cblock->aio_fildes = trace_fd; 139d3d1af6fSAlexey Budankov cblock->aio_buf = buf; 140d3d1af6fSAlexey Budankov cblock->aio_nbytes = size; 141d3d1af6fSAlexey Budankov cblock->aio_offset = off; 142d3d1af6fSAlexey Budankov cblock->aio_sigevent.sigev_notify = SIGEV_NONE; 143d3d1af6fSAlexey Budankov 144d3d1af6fSAlexey Budankov do { 145d3d1af6fSAlexey Budankov rc = aio_write(cblock); 146d3d1af6fSAlexey Budankov if (rc == 0) { 147d3d1af6fSAlexey Budankov break; 148d3d1af6fSAlexey Budankov } else if (errno != EAGAIN) { 149d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 150d3d1af6fSAlexey Budankov pr_err("failed to queue perf data, error: %m\n"); 151d3d1af6fSAlexey Budankov break; 152d3d1af6fSAlexey Budankov } 153d3d1af6fSAlexey Budankov } while (1); 154d3d1af6fSAlexey Budankov 155d3d1af6fSAlexey Budankov return rc; 156d3d1af6fSAlexey Budankov } 157d3d1af6fSAlexey Budankov 158d3d1af6fSAlexey Budankov static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock) 159d3d1af6fSAlexey Budankov { 160d3d1af6fSAlexey Budankov void *rem_buf; 161d3d1af6fSAlexey Budankov off_t rem_off; 162d3d1af6fSAlexey Budankov size_t rem_size; 163d3d1af6fSAlexey Budankov int rc, aio_errno; 164d3d1af6fSAlexey Budankov ssize_t aio_ret, written; 165d3d1af6fSAlexey Budankov 166d3d1af6fSAlexey Budankov aio_errno = aio_error(cblock); 167d3d1af6fSAlexey Budankov if (aio_errno == EINPROGRESS) 168d3d1af6fSAlexey Budankov return 0; 169d3d1af6fSAlexey Budankov 170d3d1af6fSAlexey Budankov written = aio_ret = aio_return(cblock); 171d3d1af6fSAlexey Budankov if (aio_ret < 0) { 172d3d1af6fSAlexey Budankov if (aio_errno != EINTR) 173d3d1af6fSAlexey Budankov pr_err("failed to write perf data, error: %m\n"); 174d3d1af6fSAlexey Budankov written = 0; 175d3d1af6fSAlexey Budankov } 176d3d1af6fSAlexey Budankov 177d3d1af6fSAlexey Budankov rem_size = cblock->aio_nbytes - written; 178d3d1af6fSAlexey Budankov 179d3d1af6fSAlexey Budankov if (rem_size == 0) { 180d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 181d3d1af6fSAlexey Budankov /* 182d3d1af6fSAlexey Budankov * md->refcount is incremented in perf_mmap__push() for 183d3d1af6fSAlexey Budankov * every enqueued aio write request so decrement it because 184d3d1af6fSAlexey Budankov * the request is now complete. 185d3d1af6fSAlexey Budankov */ 186d3d1af6fSAlexey Budankov perf_mmap__put(md); 187d3d1af6fSAlexey Budankov rc = 1; 188d3d1af6fSAlexey Budankov } else { 189d3d1af6fSAlexey Budankov /* 190d3d1af6fSAlexey Budankov * aio write request may require restart with the 191d3d1af6fSAlexey Budankov * reminder if the kernel didn't write whole 192d3d1af6fSAlexey Budankov * chunk at once. 193d3d1af6fSAlexey Budankov */ 194d3d1af6fSAlexey Budankov rem_off = cblock->aio_offset + written; 195d3d1af6fSAlexey Budankov rem_buf = (void *)(cblock->aio_buf + written); 196d3d1af6fSAlexey Budankov record__aio_write(cblock, cblock->aio_fildes, 197d3d1af6fSAlexey Budankov rem_buf, rem_size, rem_off); 198d3d1af6fSAlexey Budankov rc = 0; 199d3d1af6fSAlexey Budankov } 200d3d1af6fSAlexey Budankov 201d3d1af6fSAlexey Budankov return rc; 202d3d1af6fSAlexey Budankov } 203d3d1af6fSAlexey Budankov 20493f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md, bool sync_all) 205d3d1af6fSAlexey Budankov { 20693f20c0fSAlexey Budankov struct aiocb **aiocb = md->aio.aiocb; 20793f20c0fSAlexey Budankov struct aiocb *cblocks = md->aio.cblocks; 208d3d1af6fSAlexey Budankov struct timespec timeout = { 0, 1000 * 1000 * 1 }; /* 1ms */ 20993f20c0fSAlexey Budankov int i, do_suspend; 210d3d1af6fSAlexey Budankov 211d3d1af6fSAlexey Budankov do { 21293f20c0fSAlexey Budankov do_suspend = 0; 21393f20c0fSAlexey Budankov for (i = 0; i < md->aio.nr_cblocks; ++i) { 21493f20c0fSAlexey Budankov if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) { 21593f20c0fSAlexey Budankov if (sync_all) 21693f20c0fSAlexey Budankov aiocb[i] = NULL; 21793f20c0fSAlexey Budankov else 21893f20c0fSAlexey Budankov return i; 21993f20c0fSAlexey Budankov } else { 22093f20c0fSAlexey Budankov /* 22193f20c0fSAlexey Budankov * Started aio write is not complete yet 22293f20c0fSAlexey Budankov * so it has to be waited before the 22393f20c0fSAlexey Budankov * next allocation. 22493f20c0fSAlexey Budankov */ 22593f20c0fSAlexey Budankov aiocb[i] = &cblocks[i]; 22693f20c0fSAlexey Budankov do_suspend = 1; 22793f20c0fSAlexey Budankov } 22893f20c0fSAlexey Budankov } 22993f20c0fSAlexey Budankov if (!do_suspend) 23093f20c0fSAlexey Budankov return -1; 231d3d1af6fSAlexey Budankov 23293f20c0fSAlexey Budankov while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) { 233d3d1af6fSAlexey Budankov if (!(errno == EAGAIN || errno == EINTR)) 234d3d1af6fSAlexey Budankov pr_err("failed to sync perf data, error: %m\n"); 235d3d1af6fSAlexey Budankov } 236d3d1af6fSAlexey Budankov } while (1); 237d3d1af6fSAlexey Budankov } 238d3d1af6fSAlexey Budankov 239d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t size, off_t off) 240d3d1af6fSAlexey Budankov { 241d3d1af6fSAlexey Budankov struct record *rec = to; 242d3d1af6fSAlexey Budankov int ret, trace_fd = rec->session->data->file.fd; 243d3d1af6fSAlexey Budankov 244d3d1af6fSAlexey Budankov rec->samples++; 245d3d1af6fSAlexey Budankov 246d3d1af6fSAlexey Budankov ret = record__aio_write(cblock, trace_fd, bf, size, off); 247d3d1af6fSAlexey Budankov if (!ret) { 248d3d1af6fSAlexey Budankov rec->bytes_written += size; 249d3d1af6fSAlexey Budankov if (switch_output_size(rec)) 250d3d1af6fSAlexey Budankov trigger_hit(&switch_output_trigger); 251d3d1af6fSAlexey Budankov } 252d3d1af6fSAlexey Budankov 253d3d1af6fSAlexey Budankov return ret; 254d3d1af6fSAlexey Budankov } 255d3d1af6fSAlexey Budankov 256d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd) 257d3d1af6fSAlexey Budankov { 258d3d1af6fSAlexey Budankov return lseek(trace_fd, 0, SEEK_CUR); 259d3d1af6fSAlexey Budankov } 260d3d1af6fSAlexey Budankov 261d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos) 262d3d1af6fSAlexey Budankov { 263d3d1af6fSAlexey Budankov lseek(trace_fd, pos, SEEK_SET); 264d3d1af6fSAlexey Budankov } 265d3d1af6fSAlexey Budankov 266d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec) 267d3d1af6fSAlexey Budankov { 268d3d1af6fSAlexey Budankov int i; 269d3d1af6fSAlexey Budankov struct perf_evlist *evlist = rec->evlist; 270d3d1af6fSAlexey Budankov struct perf_mmap *maps = evlist->mmap; 271d3d1af6fSAlexey Budankov 272d3d1af6fSAlexey Budankov if (!rec->opts.nr_cblocks) 273d3d1af6fSAlexey Budankov return; 274d3d1af6fSAlexey Budankov 275d3d1af6fSAlexey Budankov for (i = 0; i < evlist->nr_mmaps; i++) { 276d3d1af6fSAlexey Budankov struct perf_mmap *map = &maps[i]; 277d3d1af6fSAlexey Budankov 278d3d1af6fSAlexey Budankov if (map->base) 27993f20c0fSAlexey Budankov record__aio_sync(map, true); 280d3d1af6fSAlexey Budankov } 281d3d1af6fSAlexey Budankov } 282d3d1af6fSAlexey Budankov 283d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1; 28493f20c0fSAlexey Budankov static int nr_cblocks_max = 4; 285d3d1af6fSAlexey Budankov 286d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt, 28793f20c0fSAlexey Budankov const char *str, 288d3d1af6fSAlexey Budankov int unset) 289d3d1af6fSAlexey Budankov { 290d3d1af6fSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 291d3d1af6fSAlexey Budankov 29293f20c0fSAlexey Budankov if (unset) { 293d3d1af6fSAlexey Budankov opts->nr_cblocks = 0; 29493f20c0fSAlexey Budankov } else { 29593f20c0fSAlexey Budankov if (str) 29693f20c0fSAlexey Budankov opts->nr_cblocks = strtol(str, NULL, 0); 29793f20c0fSAlexey Budankov if (!opts->nr_cblocks) 298d3d1af6fSAlexey Budankov opts->nr_cblocks = nr_cblocks_default; 29993f20c0fSAlexey Budankov } 300d3d1af6fSAlexey Budankov 301d3d1af6fSAlexey Budankov return 0; 302d3d1af6fSAlexey Budankov } 303d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */ 30493f20c0fSAlexey Budankov static int nr_cblocks_max = 0; 30593f20c0fSAlexey Budankov 30693f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md __maybe_unused, bool sync_all __maybe_unused) 307d3d1af6fSAlexey Budankov { 30893f20c0fSAlexey Budankov return -1; 309d3d1af6fSAlexey Budankov } 310d3d1af6fSAlexey Budankov 311d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to __maybe_unused, struct aiocb *cblock __maybe_unused, 312d3d1af6fSAlexey Budankov void *bf __maybe_unused, size_t size __maybe_unused, off_t off __maybe_unused) 313d3d1af6fSAlexey Budankov { 314d3d1af6fSAlexey Budankov return -1; 315d3d1af6fSAlexey Budankov } 316d3d1af6fSAlexey Budankov 317d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused) 318d3d1af6fSAlexey Budankov { 319d3d1af6fSAlexey Budankov return -1; 320d3d1af6fSAlexey Budankov } 321d3d1af6fSAlexey Budankov 322d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused) 323d3d1af6fSAlexey Budankov { 324d3d1af6fSAlexey Budankov } 325d3d1af6fSAlexey Budankov 326d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused) 327d3d1af6fSAlexey Budankov { 328d3d1af6fSAlexey Budankov } 329d3d1af6fSAlexey Budankov #endif 330d3d1af6fSAlexey Budankov 331d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec) 332d3d1af6fSAlexey Budankov { 333d3d1af6fSAlexey Budankov return rec->opts.nr_cblocks > 0; 334d3d1af6fSAlexey Budankov } 335d3d1af6fSAlexey Budankov 33645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 337d20deb64SArnaldo Carvalho de Melo union perf_event *event, 3381d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 3391d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 340234fbbf5SArnaldo Carvalho de Melo { 3418c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 342ded2b8feSJiri Olsa return record__write(rec, NULL, event, event->header.size); 343234fbbf5SArnaldo Carvalho de Melo } 344234fbbf5SArnaldo Carvalho de Melo 345ded2b8feSJiri Olsa static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size) 346d37f1586SArnaldo Carvalho de Melo { 347d37f1586SArnaldo Carvalho de Melo struct record *rec = to; 348d37f1586SArnaldo Carvalho de Melo 349d37f1586SArnaldo Carvalho de Melo rec->samples++; 350ded2b8feSJiri Olsa return record__write(rec, map, bf, size); 351d37f1586SArnaldo Carvalho de Melo } 352d37f1586SArnaldo Carvalho de Melo 3532dd6d8a1SAdrian Hunter static volatile int done; 3542dd6d8a1SAdrian Hunter static volatile int signr = -1; 3552dd6d8a1SAdrian Hunter static volatile int child_finished; 356c0bdc1c4SWang Nan 3572dd6d8a1SAdrian Hunter static void sig_handler(int sig) 3582dd6d8a1SAdrian Hunter { 3592dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 3602dd6d8a1SAdrian Hunter child_finished = 1; 3612dd6d8a1SAdrian Hunter else 3622dd6d8a1SAdrian Hunter signr = sig; 3632dd6d8a1SAdrian Hunter 3642dd6d8a1SAdrian Hunter done = 1; 3652dd6d8a1SAdrian Hunter } 3662dd6d8a1SAdrian Hunter 367a074865eSWang Nan static void sigsegv_handler(int sig) 368a074865eSWang Nan { 369a074865eSWang Nan perf_hooks__recover(); 370a074865eSWang Nan sighandler_dump_stack(sig); 371a074865eSWang Nan } 372a074865eSWang Nan 3732dd6d8a1SAdrian Hunter static void record__sig_exit(void) 3742dd6d8a1SAdrian Hunter { 3752dd6d8a1SAdrian Hunter if (signr == -1) 3762dd6d8a1SAdrian Hunter return; 3772dd6d8a1SAdrian Hunter 3782dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 3792dd6d8a1SAdrian Hunter raise(signr); 3802dd6d8a1SAdrian Hunter } 3812dd6d8a1SAdrian Hunter 382e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 383e31f0d01SAdrian Hunter 384ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 385ded2b8feSJiri Olsa struct perf_mmap *map, 386ef149c25SAdrian Hunter union perf_event *event, void *data1, 387ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 388ef149c25SAdrian Hunter { 389ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 3908ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 391ef149c25SAdrian Hunter size_t padding; 392ef149c25SAdrian Hunter u8 pad[8] = {0}; 393ef149c25SAdrian Hunter 3948ceb41d7SJiri Olsa if (!perf_data__is_pipe(data)) { 39599fa2984SAdrian Hunter off_t file_offset; 3968ceb41d7SJiri Olsa int fd = perf_data__fd(data); 39799fa2984SAdrian Hunter int err; 39899fa2984SAdrian Hunter 39999fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 40099fa2984SAdrian Hunter if (file_offset == -1) 40199fa2984SAdrian Hunter return -1; 40299fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 40399fa2984SAdrian Hunter event, file_offset); 40499fa2984SAdrian Hunter if (err) 40599fa2984SAdrian Hunter return err; 40699fa2984SAdrian Hunter } 40799fa2984SAdrian Hunter 408ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 409ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 410ef149c25SAdrian Hunter if (padding) 411ef149c25SAdrian Hunter padding = 8 - padding; 412ef149c25SAdrian Hunter 413ded2b8feSJiri Olsa record__write(rec, map, event, event->header.size); 414ded2b8feSJiri Olsa record__write(rec, map, data1, len1); 415ef149c25SAdrian Hunter if (len2) 416ded2b8feSJiri Olsa record__write(rec, map, data2, len2); 417ded2b8feSJiri Olsa record__write(rec, map, &pad, padding); 418ef149c25SAdrian Hunter 419ef149c25SAdrian Hunter return 0; 420ef149c25SAdrian Hunter } 421ef149c25SAdrian Hunter 422ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 423e035f4caSJiri Olsa struct perf_mmap *map) 424ef149c25SAdrian Hunter { 425ef149c25SAdrian Hunter int ret; 426ef149c25SAdrian Hunter 427e035f4caSJiri Olsa ret = auxtrace_mmap__read(map, rec->itr, &rec->tool, 428ef149c25SAdrian Hunter record__process_auxtrace); 429ef149c25SAdrian Hunter if (ret < 0) 430ef149c25SAdrian Hunter return ret; 431ef149c25SAdrian Hunter 432ef149c25SAdrian Hunter if (ret) 433ef149c25SAdrian Hunter rec->samples++; 434ef149c25SAdrian Hunter 435ef149c25SAdrian Hunter return 0; 436ef149c25SAdrian Hunter } 437ef149c25SAdrian Hunter 4382dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 439e035f4caSJiri Olsa struct perf_mmap *map) 4402dd6d8a1SAdrian Hunter { 4412dd6d8a1SAdrian Hunter int ret; 4422dd6d8a1SAdrian Hunter 443e035f4caSJiri Olsa ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool, 4442dd6d8a1SAdrian Hunter record__process_auxtrace, 4452dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 4462dd6d8a1SAdrian Hunter if (ret < 0) 4472dd6d8a1SAdrian Hunter return ret; 4482dd6d8a1SAdrian Hunter 4492dd6d8a1SAdrian Hunter if (ret) 4502dd6d8a1SAdrian Hunter rec->samples++; 4512dd6d8a1SAdrian Hunter 4522dd6d8a1SAdrian Hunter return 0; 4532dd6d8a1SAdrian Hunter } 4542dd6d8a1SAdrian Hunter 4552dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 4562dd6d8a1SAdrian Hunter { 4572dd6d8a1SAdrian Hunter int i; 4582dd6d8a1SAdrian Hunter int rc = 0; 4592dd6d8a1SAdrian Hunter 4602dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 461e035f4caSJiri Olsa struct perf_mmap *map = &rec->evlist->mmap[i]; 4622dd6d8a1SAdrian Hunter 463e035f4caSJiri Olsa if (!map->auxtrace_mmap.base) 4642dd6d8a1SAdrian Hunter continue; 4652dd6d8a1SAdrian Hunter 466e035f4caSJiri Olsa if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) { 4672dd6d8a1SAdrian Hunter rc = -1; 4682dd6d8a1SAdrian Hunter goto out; 4692dd6d8a1SAdrian Hunter } 4702dd6d8a1SAdrian Hunter } 4712dd6d8a1SAdrian Hunter out: 4722dd6d8a1SAdrian Hunter return rc; 4732dd6d8a1SAdrian Hunter } 4742dd6d8a1SAdrian Hunter 4752dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 4762dd6d8a1SAdrian Hunter { 4772dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 4782dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 4795f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 4802dd6d8a1SAdrian Hunter } else { 4815f9cf599SWang Nan if (auxtrace_record__snapshot_finish(rec->itr)) 4825f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 4835f9cf599SWang Nan else 4845f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 4852dd6d8a1SAdrian Hunter } 4862dd6d8a1SAdrian Hunter } 4872dd6d8a1SAdrian Hunter 4884b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec) 4894b5ea3bdSAdrian Hunter { 4904b5ea3bdSAdrian Hunter int err; 4914b5ea3bdSAdrian Hunter 4924b5ea3bdSAdrian Hunter if (!rec->itr) { 4934b5ea3bdSAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 4944b5ea3bdSAdrian Hunter if (err) 4954b5ea3bdSAdrian Hunter return err; 4964b5ea3bdSAdrian Hunter } 4974b5ea3bdSAdrian Hunter 4984b5ea3bdSAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 4994b5ea3bdSAdrian Hunter rec->opts.auxtrace_snapshot_opts); 5004b5ea3bdSAdrian Hunter if (err) 5014b5ea3bdSAdrian Hunter return err; 5024b5ea3bdSAdrian Hunter 5034b5ea3bdSAdrian Hunter return auxtrace_parse_filters(rec->evlist); 5044b5ea3bdSAdrian Hunter } 5054b5ea3bdSAdrian Hunter 506e31f0d01SAdrian Hunter #else 507e31f0d01SAdrian Hunter 508e31f0d01SAdrian Hunter static inline 509e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 510e035f4caSJiri Olsa struct perf_mmap *map __maybe_unused) 511e31f0d01SAdrian Hunter { 512e31f0d01SAdrian Hunter return 0; 513e31f0d01SAdrian Hunter } 514e31f0d01SAdrian Hunter 5152dd6d8a1SAdrian Hunter static inline 5162dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 5172dd6d8a1SAdrian Hunter { 5182dd6d8a1SAdrian Hunter } 5192dd6d8a1SAdrian Hunter 5202dd6d8a1SAdrian Hunter static inline 5212dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 5222dd6d8a1SAdrian Hunter { 5232dd6d8a1SAdrian Hunter return 0; 5242dd6d8a1SAdrian Hunter } 5252dd6d8a1SAdrian Hunter 5264b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused) 5274b5ea3bdSAdrian Hunter { 5284b5ea3bdSAdrian Hunter return 0; 5294b5ea3bdSAdrian Hunter } 5304b5ea3bdSAdrian Hunter 531e31f0d01SAdrian Hunter #endif 532e31f0d01SAdrian Hunter 533cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 534cda57a8cSWang Nan struct perf_evlist *evlist) 535cda57a8cSWang Nan { 536cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 537cda57a8cSWang Nan char msg[512]; 538cda57a8cSWang Nan 5397a276ff6SWang Nan if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, 540cda57a8cSWang Nan opts->auxtrace_mmap_pages, 541*9d2ed645SAlexey Budankov opts->auxtrace_snapshot_mode, 542*9d2ed645SAlexey Budankov opts->nr_cblocks, opts->affinity) < 0) { 543cda57a8cSWang Nan if (errno == EPERM) { 544cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 545cda57a8cSWang Nan "Consider increasing " 546cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 547cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 548cda57a8cSWang Nan "(current value: %u,%u)\n", 549cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 550cda57a8cSWang Nan return -errno; 551cda57a8cSWang Nan } else { 552cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 553c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 554cda57a8cSWang Nan if (errno) 555cda57a8cSWang Nan return -errno; 556cda57a8cSWang Nan else 557cda57a8cSWang Nan return -EINVAL; 558cda57a8cSWang Nan } 559cda57a8cSWang Nan } 560cda57a8cSWang Nan return 0; 561cda57a8cSWang Nan } 562cda57a8cSWang Nan 563cda57a8cSWang Nan static int record__mmap(struct record *rec) 564cda57a8cSWang Nan { 565cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 566cda57a8cSWang Nan } 567cda57a8cSWang Nan 5688c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 569dd7927f4SArnaldo Carvalho de Melo { 570d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 5716a4bb04cSJiri Olsa struct perf_evsel *pos; 572d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 573d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 574b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 5758d3eca20SDavid Ahern int rc = 0; 576dd7927f4SArnaldo Carvalho de Melo 577d3dbf43cSArnaldo Carvalho de Melo /* 578d3dbf43cSArnaldo Carvalho de Melo * For initial_delay we need to add a dummy event so that we can track 579d3dbf43cSArnaldo Carvalho de Melo * PERF_RECORD_MMAP while we wait for the initial delay to enable the 580d3dbf43cSArnaldo Carvalho de Melo * real events, the ones asked by the user. 581d3dbf43cSArnaldo Carvalho de Melo */ 582d3dbf43cSArnaldo Carvalho de Melo if (opts->initial_delay) { 583d3dbf43cSArnaldo Carvalho de Melo if (perf_evlist__add_dummy(evlist)) 584d3dbf43cSArnaldo Carvalho de Melo return -ENOMEM; 585d3dbf43cSArnaldo Carvalho de Melo 586d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__first(evlist); 587d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 0; 588d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__last(evlist); 589d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 1; 590d3dbf43cSArnaldo Carvalho de Melo pos->attr.enable_on_exec = 1; 591d3dbf43cSArnaldo Carvalho de Melo } 592d3dbf43cSArnaldo Carvalho de Melo 593e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 594cac21425SJiri Olsa 595e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 5963da297a6SIngo Molnar try_again: 597d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 59856e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 599bb963e16SNamhyung Kim if (verbose > 0) 600c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 6013da297a6SIngo Molnar goto try_again; 6023da297a6SIngo Molnar } 603cf99ad14SAndi Kleen if ((errno == EINVAL || errno == EBADF) && 604cf99ad14SAndi Kleen pos->leader != pos && 605cf99ad14SAndi Kleen pos->weak_group) { 606cf99ad14SAndi Kleen pos = perf_evlist__reset_weak_group(evlist, pos); 607cf99ad14SAndi Kleen goto try_again; 608cf99ad14SAndi Kleen } 60956e52e85SArnaldo Carvalho de Melo rc = -errno; 61056e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 61156e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 61256e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 6138d3eca20SDavid Ahern goto out; 6147c6a1c65SPeter Zijlstra } 615bfd8f72cSAndi Kleen 616bfd8f72cSAndi Kleen pos->supported = true; 6177c6a1c65SPeter Zijlstra } 6187c6a1c65SPeter Zijlstra 61923d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 62062d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 62123d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 622c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 6238d3eca20SDavid Ahern rc = -1; 6248d3eca20SDavid Ahern goto out; 6250a102479SFrederic Weisbecker } 6260a102479SFrederic Weisbecker 627cda57a8cSWang Nan rc = record__mmap(rec); 628cda57a8cSWang Nan if (rc) 6298d3eca20SDavid Ahern goto out; 6300a27d7f9SArnaldo Carvalho de Melo 631a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 6327b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 6338d3eca20SDavid Ahern out: 6348d3eca20SDavid Ahern return rc; 635a91e5431SArnaldo Carvalho de Melo } 636a91e5431SArnaldo Carvalho de Melo 637e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 638e3d59112SNamhyung Kim union perf_event *event, 639e3d59112SNamhyung Kim struct perf_sample *sample, 640e3d59112SNamhyung Kim struct perf_evsel *evsel, 641e3d59112SNamhyung Kim struct machine *machine) 642e3d59112SNamhyung Kim { 643e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 644e3d59112SNamhyung Kim 64568588bafSJin Yao if (rec->evlist->first_sample_time == 0) 64668588bafSJin Yao rec->evlist->first_sample_time = sample->time; 647e3d59112SNamhyung Kim 64868588bafSJin Yao rec->evlist->last_sample_time = sample->time; 64968588bafSJin Yao 65068588bafSJin Yao if (rec->buildid_all) 65168588bafSJin Yao return 0; 65268588bafSJin Yao 65368588bafSJin Yao rec->samples++; 654e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 655e3d59112SNamhyung Kim } 656e3d59112SNamhyung Kim 6578c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 6586122e4e4SArnaldo Carvalho de Melo { 6598ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 660f5fc1412SJiri Olsa struct perf_session *session = rec->session; 6616122e4e4SArnaldo Carvalho de Melo 6628ceb41d7SJiri Olsa if (data->size == 0) 6639f591fd7SArnaldo Carvalho de Melo return 0; 6649f591fd7SArnaldo Carvalho de Melo 66500dc8657SNamhyung Kim /* 66600dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 66700dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 66800dc8657SNamhyung Kim * we prefer the vmlinux path like 66900dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 67000dc8657SNamhyung Kim * 67100dc8657SNamhyung Kim * rather than build-id path (in debug directory). 67200dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 67300dc8657SNamhyung Kim */ 67400dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 67500dc8657SNamhyung Kim 6766156681bSNamhyung Kim /* 6776156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 67868588bafSJin Yao * so no need to process samples. But if timestamp_boundary is enabled, 67968588bafSJin Yao * it still needs to walk on all samples to get the timestamps of 68068588bafSJin Yao * first/last samples. 6816156681bSNamhyung Kim */ 68268588bafSJin Yao if (rec->buildid_all && !rec->timestamp_boundary) 6836156681bSNamhyung Kim rec->tool.sample = NULL; 6846156681bSNamhyung Kim 685b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 6866122e4e4SArnaldo Carvalho de Melo } 6876122e4e4SArnaldo Carvalho de Melo 6888115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 689a1645ce1SZhang, Yanmin { 690a1645ce1SZhang, Yanmin int err; 69145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 692a1645ce1SZhang, Yanmin /* 693a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 694a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 695a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 696a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 697a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 698a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 699a1645ce1SZhang, Yanmin */ 70045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 701743eb868SArnaldo Carvalho de Melo machine); 702a1645ce1SZhang, Yanmin if (err < 0) 703a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 70423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 705a1645ce1SZhang, Yanmin 706a1645ce1SZhang, Yanmin /* 707a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 708a1645ce1SZhang, Yanmin * have no _text sometimes. 709a1645ce1SZhang, Yanmin */ 71045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 7110ae617beSAdrian Hunter machine); 712a1645ce1SZhang, Yanmin if (err < 0) 713a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 71423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 715a1645ce1SZhang, Yanmin } 716a1645ce1SZhang, Yanmin 71798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 71898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 71998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 72098402807SFrederic Weisbecker }; 72198402807SFrederic Weisbecker 722a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, 7230b72d69aSWang Nan bool overwrite) 72498402807SFrederic Weisbecker { 725dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 7260e2e63ddSPeter Zijlstra int i; 7278d3eca20SDavid Ahern int rc = 0; 728a4ea0ec4SWang Nan struct perf_mmap *maps; 729d3d1af6fSAlexey Budankov int trace_fd = rec->data.file.fd; 730d3d1af6fSAlexey Budankov off_t off; 73198402807SFrederic Weisbecker 732cb21686bSWang Nan if (!evlist) 733cb21686bSWang Nan return 0; 734ef149c25SAdrian Hunter 7350b72d69aSWang Nan maps = overwrite ? evlist->overwrite_mmap : evlist->mmap; 736a4ea0ec4SWang Nan if (!maps) 737a4ea0ec4SWang Nan return 0; 738cb21686bSWang Nan 7390b72d69aSWang Nan if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 74054cc54deSWang Nan return 0; 74154cc54deSWang Nan 742d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 743d3d1af6fSAlexey Budankov off = record__aio_get_pos(trace_fd); 744d3d1af6fSAlexey Budankov 745a4ea0ec4SWang Nan for (i = 0; i < evlist->nr_mmaps; i++) { 746e035f4caSJiri Olsa struct perf_mmap *map = &maps[i]; 747a4ea0ec4SWang Nan 748e035f4caSJiri Olsa if (map->base) { 749d3d1af6fSAlexey Budankov if (!record__aio_enabled(rec)) { 750e035f4caSJiri Olsa if (perf_mmap__push(map, rec, record__pushfn) != 0) { 7518d3eca20SDavid Ahern rc = -1; 7528d3eca20SDavid Ahern goto out; 7538d3eca20SDavid Ahern } 754d3d1af6fSAlexey Budankov } else { 75593f20c0fSAlexey Budankov int idx; 756d3d1af6fSAlexey Budankov /* 757d3d1af6fSAlexey Budankov * Call record__aio_sync() to wait till map->data buffer 758d3d1af6fSAlexey Budankov * becomes available after previous aio write request. 759d3d1af6fSAlexey Budankov */ 76093f20c0fSAlexey Budankov idx = record__aio_sync(map, false); 76193f20c0fSAlexey Budankov if (perf_mmap__aio_push(map, rec, idx, record__aio_pushfn, &off) != 0) { 762d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 763d3d1af6fSAlexey Budankov rc = -1; 764d3d1af6fSAlexey Budankov goto out; 765d3d1af6fSAlexey Budankov } 766d3d1af6fSAlexey Budankov } 7678d3eca20SDavid Ahern } 768ef149c25SAdrian Hunter 769e035f4caSJiri Olsa if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode && 770e035f4caSJiri Olsa record__auxtrace_mmap_read(rec, map) != 0) { 771ef149c25SAdrian Hunter rc = -1; 772ef149c25SAdrian Hunter goto out; 773ef149c25SAdrian Hunter } 77498402807SFrederic Weisbecker } 77598402807SFrederic Weisbecker 776d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 777d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 778d3d1af6fSAlexey Budankov 779dcabb507SJiri Olsa /* 780dcabb507SJiri Olsa * Mark the round finished in case we wrote 781dcabb507SJiri Olsa * at least one event. 782dcabb507SJiri Olsa */ 783dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 784ded2b8feSJiri Olsa rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event)); 7858d3eca20SDavid Ahern 7860b72d69aSWang Nan if (overwrite) 78754cc54deSWang Nan perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 7888d3eca20SDavid Ahern out: 7898d3eca20SDavid Ahern return rc; 79098402807SFrederic Weisbecker } 79198402807SFrederic Weisbecker 792cb21686bSWang Nan static int record__mmap_read_all(struct record *rec) 793cb21686bSWang Nan { 794cb21686bSWang Nan int err; 795cb21686bSWang Nan 796a4ea0ec4SWang Nan err = record__mmap_read_evlist(rec, rec->evlist, false); 797cb21686bSWang Nan if (err) 798cb21686bSWang Nan return err; 799cb21686bSWang Nan 80005737464SWang Nan return record__mmap_read_evlist(rec, rec->evlist, true); 801cb21686bSWang Nan } 802cb21686bSWang Nan 8038c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 80457706abcSDavid Ahern { 80557706abcSDavid Ahern struct perf_session *session = rec->session; 80657706abcSDavid Ahern int feat; 80757706abcSDavid Ahern 80857706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 80957706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 81057706abcSDavid Ahern 81157706abcSDavid Ahern if (rec->no_buildid) 81257706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 81357706abcSDavid Ahern 8143e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 81557706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 81657706abcSDavid Ahern 81757706abcSDavid Ahern if (!rec->opts.branch_stack) 81857706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 819ef149c25SAdrian Hunter 820ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 821ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 822ffa517adSJiri Olsa 823cf790516SAlexey Budankov if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 824cf790516SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_CLOCKID); 825cf790516SAlexey Budankov 826ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 82757706abcSDavid Ahern } 82857706abcSDavid Ahern 829e1ab48baSWang Nan static void 830e1ab48baSWang Nan record__finish_output(struct record *rec) 831e1ab48baSWang Nan { 8328ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 8338ceb41d7SJiri Olsa int fd = perf_data__fd(data); 834e1ab48baSWang Nan 8358ceb41d7SJiri Olsa if (data->is_pipe) 836e1ab48baSWang Nan return; 837e1ab48baSWang Nan 838e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 8398ceb41d7SJiri Olsa data->size = lseek(perf_data__fd(data), 0, SEEK_CUR); 840e1ab48baSWang Nan 841e1ab48baSWang Nan if (!rec->no_buildid) { 842e1ab48baSWang Nan process_buildids(rec); 843e1ab48baSWang Nan 844e1ab48baSWang Nan if (rec->buildid_all) 845e1ab48baSWang Nan dsos__hit_all(rec->session); 846e1ab48baSWang Nan } 847e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 848e1ab48baSWang Nan 849e1ab48baSWang Nan return; 850e1ab48baSWang Nan } 851e1ab48baSWang Nan 8524ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 853be7b0c9eSWang Nan { 8549d6aae72SArnaldo Carvalho de Melo int err; 8559d6aae72SArnaldo Carvalho de Melo struct thread_map *thread_map; 856be7b0c9eSWang Nan 8574ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 8584ea648aeSWang Nan return 0; 8594ea648aeSWang Nan 8609d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 8619d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL) 8629d6aae72SArnaldo Carvalho de Melo return -1; 8639d6aae72SArnaldo Carvalho de Melo 8649d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 865be7b0c9eSWang Nan process_synthesized_event, 866be7b0c9eSWang Nan &rec->session->machines.host, 8673fcb10e4SMark Drayton rec->opts.sample_address); 8689d6aae72SArnaldo Carvalho de Melo thread_map__put(thread_map); 8699d6aae72SArnaldo Carvalho de Melo return err; 870be7b0c9eSWang Nan } 871be7b0c9eSWang Nan 8724ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 8733c1cb7e3SWang Nan 874ecfd7a9cSWang Nan static int 875ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 876ecfd7a9cSWang Nan { 8778ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 878ecfd7a9cSWang Nan int fd, err; 879ecfd7a9cSWang Nan 880ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 881ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 882ecfd7a9cSWang Nan 883d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 884d3d1af6fSAlexey Budankov 8854ea648aeSWang Nan record__synthesize(rec, true); 8864ea648aeSWang Nan if (target__none(&rec->opts.target)) 8874ea648aeSWang Nan record__synthesize_workload(rec, true); 8884ea648aeSWang Nan 889ecfd7a9cSWang Nan rec->samples = 0; 890ecfd7a9cSWang Nan record__finish_output(rec); 891ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 892ecfd7a9cSWang Nan if (err) { 893ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 894ecfd7a9cSWang Nan return -EINVAL; 895ecfd7a9cSWang Nan } 896ecfd7a9cSWang Nan 8978ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp, 898ecfd7a9cSWang Nan rec->session->header.data_offset, 899ecfd7a9cSWang Nan at_exit); 900ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 901ecfd7a9cSWang Nan rec->bytes_written = 0; 902ecfd7a9cSWang Nan rec->session->header.data_size = 0; 903ecfd7a9cSWang Nan } 904ecfd7a9cSWang Nan 905ecfd7a9cSWang Nan if (!quiet) 906ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 907eae8ad80SJiri Olsa data->file.path, timestamp); 9083c1cb7e3SWang Nan 9093c1cb7e3SWang Nan /* Output tracking events */ 910be7b0c9eSWang Nan if (!at_exit) { 9114ea648aeSWang Nan record__synthesize(rec, false); 9123c1cb7e3SWang Nan 913be7b0c9eSWang Nan /* 914be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 915be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 916be7b0c9eSWang Nan * generate tracking events because there's no thread_map 917be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 918be7b0c9eSWang Nan * contain map and comm information. 919be7b0c9eSWang Nan * Create a fake thread_map and directly call 920be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 921be7b0c9eSWang Nan */ 922be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 9234ea648aeSWang Nan record__synthesize_workload(rec, false); 924be7b0c9eSWang Nan } 925ecfd7a9cSWang Nan return fd; 926ecfd7a9cSWang Nan } 927ecfd7a9cSWang Nan 928f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 929f33cbe72SArnaldo Carvalho de Melo 930f33cbe72SArnaldo Carvalho de Melo /* 931f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 932f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 933f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 934f33cbe72SArnaldo Carvalho de Melo */ 93545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 93645604710SNamhyung Kim siginfo_t *info, 937f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 938f33cbe72SArnaldo Carvalho de Melo { 939f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 940f33cbe72SArnaldo Carvalho de Melo done = 1; 941f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 942f33cbe72SArnaldo Carvalho de Melo } 943f33cbe72SArnaldo Carvalho de Melo 9442dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 945bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig); 9462dd6d8a1SAdrian Hunter 94746bc29b9SAdrian Hunter int __weak 94846bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 94946bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 95046bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 95146bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 95246bc29b9SAdrian Hunter { 95346bc29b9SAdrian Hunter return 0; 95446bc29b9SAdrian Hunter } 95546bc29b9SAdrian Hunter 956ee667f94SWang Nan static const struct perf_event_mmap_page * 957ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist) 958ee667f94SWang Nan { 959b2cb615dSWang Nan if (evlist) { 960b2cb615dSWang Nan if (evlist->mmap && evlist->mmap[0].base) 961ee667f94SWang Nan return evlist->mmap[0].base; 9620b72d69aSWang Nan if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base) 9630b72d69aSWang Nan return evlist->overwrite_mmap[0].base; 964b2cb615dSWang Nan } 965ee667f94SWang Nan return NULL; 966ee667f94SWang Nan } 967ee667f94SWang Nan 968c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 969c45628b0SWang Nan { 970ee667f94SWang Nan const struct perf_event_mmap_page *pc; 971ee667f94SWang Nan 972ee667f94SWang Nan pc = perf_evlist__pick_pc(rec->evlist); 973ee667f94SWang Nan if (pc) 974ee667f94SWang Nan return pc; 975c45628b0SWang Nan return NULL; 976c45628b0SWang Nan } 977c45628b0SWang Nan 9784ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 979c45c86ebSWang Nan { 980c45c86ebSWang Nan struct perf_session *session = rec->session; 981c45c86ebSWang Nan struct machine *machine = &session->machines.host; 9828ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 983c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 984c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 9858ceb41d7SJiri Olsa int fd = perf_data__fd(data); 986c45c86ebSWang Nan int err = 0; 987c45c86ebSWang Nan 9884ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 9894ea648aeSWang Nan return 0; 9904ea648aeSWang Nan 9918ceb41d7SJiri Olsa if (data->is_pipe) { 992a2015516SJiri Olsa /* 993a2015516SJiri Olsa * We need to synthesize events first, because some 994a2015516SJiri Olsa * features works on top of them (on report side). 995a2015516SJiri Olsa */ 996318ec184SJiri Olsa err = perf_event__synthesize_attrs(tool, rec->evlist, 997c45c86ebSWang Nan process_synthesized_event); 998c45c86ebSWang Nan if (err < 0) { 999c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 1000c45c86ebSWang Nan goto out; 1001c45c86ebSWang Nan } 1002c45c86ebSWang Nan 1003a2015516SJiri Olsa err = perf_event__synthesize_features(tool, session, rec->evlist, 1004a2015516SJiri Olsa process_synthesized_event); 1005a2015516SJiri Olsa if (err < 0) { 1006a2015516SJiri Olsa pr_err("Couldn't synthesize features.\n"); 1007a2015516SJiri Olsa return err; 1008a2015516SJiri Olsa } 1009a2015516SJiri Olsa 1010c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 1011c45c86ebSWang Nan /* 1012c45c86ebSWang Nan * FIXME err <= 0 here actually means that 1013c45c86ebSWang Nan * there were no tracepoints so its not really 1014c45c86ebSWang Nan * an error, just that we don't need to 1015c45c86ebSWang Nan * synthesize anything. We really have to 1016c45c86ebSWang Nan * return this more properly and also 1017c45c86ebSWang Nan * propagate errors that now are calling die() 1018c45c86ebSWang Nan */ 1019c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 1020c45c86ebSWang Nan process_synthesized_event); 1021c45c86ebSWang Nan if (err <= 0) { 1022c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 1023c45c86ebSWang Nan goto out; 1024c45c86ebSWang Nan } 1025c45c86ebSWang Nan rec->bytes_written += err; 1026c45c86ebSWang Nan } 1027c45c86ebSWang Nan } 1028c45c86ebSWang Nan 1029c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 103046bc29b9SAdrian Hunter process_synthesized_event, machine); 103146bc29b9SAdrian Hunter if (err) 103246bc29b9SAdrian Hunter goto out; 103346bc29b9SAdrian Hunter 1034c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 1035c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 1036c45c86ebSWang Nan session, process_synthesized_event); 1037c45c86ebSWang Nan if (err) 1038c45c86ebSWang Nan goto out; 1039c45c86ebSWang Nan } 1040c45c86ebSWang Nan 10416c443954SArnaldo Carvalho de Melo if (!perf_evlist__exclude_kernel(rec->evlist)) { 1042c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 1043c45c86ebSWang Nan machine); 1044c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 1045c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1046c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 1047c45c86ebSWang Nan 1048c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 1049c45c86ebSWang Nan machine); 1050c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 1051c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1052c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 10536c443954SArnaldo Carvalho de Melo } 1054c45c86ebSWang Nan 1055c45c86ebSWang Nan if (perf_guest) { 1056c45c86ebSWang Nan machines__process_guests(&session->machines, 1057c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 1058c45c86ebSWang Nan } 1059c45c86ebSWang Nan 1060bfd8f72cSAndi Kleen err = perf_event__synthesize_extra_attr(&rec->tool, 1061bfd8f72cSAndi Kleen rec->evlist, 1062bfd8f72cSAndi Kleen process_synthesized_event, 1063bfd8f72cSAndi Kleen data->is_pipe); 1064bfd8f72cSAndi Kleen if (err) 1065bfd8f72cSAndi Kleen goto out; 1066bfd8f72cSAndi Kleen 1067373565d2SAndi Kleen err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads, 1068373565d2SAndi Kleen process_synthesized_event, 1069373565d2SAndi Kleen NULL); 1070373565d2SAndi Kleen if (err < 0) { 1071373565d2SAndi Kleen pr_err("Couldn't synthesize thread map.\n"); 1072373565d2SAndi Kleen return err; 1073373565d2SAndi Kleen } 1074373565d2SAndi Kleen 1075373565d2SAndi Kleen err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus, 1076373565d2SAndi Kleen process_synthesized_event, NULL); 1077373565d2SAndi Kleen if (err < 0) { 1078373565d2SAndi Kleen pr_err("Couldn't synthesize cpu map.\n"); 1079373565d2SAndi Kleen return err; 1080373565d2SAndi Kleen } 1081373565d2SAndi Kleen 10827b612e29SSong Liu err = perf_event__synthesize_bpf_events(tool, process_synthesized_event, 10837b612e29SSong Liu machine, opts); 10847b612e29SSong Liu if (err < 0) 10857b612e29SSong Liu pr_warning("Couldn't synthesize bpf events.\n"); 10867b612e29SSong Liu 1087c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 1088c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 10893fcb10e4SMark Drayton 1); 1090c45c86ebSWang Nan out: 1091c45c86ebSWang Nan return err; 1092c45c86ebSWang Nan } 1093c45c86ebSWang Nan 10948c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 109586470930SIngo Molnar { 109657706abcSDavid Ahern int err; 109745604710SNamhyung Kim int status = 0; 10988b412664SPeter Zijlstra unsigned long waking = 0; 109946be604bSZhang, Yanmin const bool forks = argc > 0; 110045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 1101b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 11028ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1103d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 11046dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 110542aa276fSNamhyung Kim int fd; 110686470930SIngo Molnar 110745604710SNamhyung Kim atexit(record__sig_exit); 1108f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 1109f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 1110804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 1111a074865eSWang Nan signal(SIGSEGV, sigsegv_handler); 1112c0bdc1c4SWang Nan 1113f3b3614aSHari Bathini if (rec->opts.record_namespaces) 1114f3b3614aSHari Bathini tool->namespace_events = true; 1115f3b3614aSHari Bathini 1116dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 11172dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 11183c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 11195f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 1120dc0c6127SJiri Olsa if (rec->switch_output.enabled) 11213c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 1122c0bdc1c4SWang Nan } else { 11232dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 1124c0bdc1c4SWang Nan } 1125f5970550SPeter Zijlstra 11268ceb41d7SJiri Olsa session = perf_session__new(data, false, tool); 112794c744b6SArnaldo Carvalho de Melo if (session == NULL) { 1128ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 1129a9a70bbcSArnaldo Carvalho de Melo return -1; 1130a9a70bbcSArnaldo Carvalho de Melo } 1131a9a70bbcSArnaldo Carvalho de Melo 11328ceb41d7SJiri Olsa fd = perf_data__fd(data); 1133d20deb64SArnaldo Carvalho de Melo rec->session = session; 1134d20deb64SArnaldo Carvalho de Melo 11358c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 1136330aa675SStephane Eranian 1137cf790516SAlexey Budankov if (rec->opts.use_clockid && rec->opts.clockid_res_ns) 1138cf790516SAlexey Budankov session->header.env.clockid_res_ns = rec->opts.clockid_res_ns; 1139cf790516SAlexey Budankov 1140d4db3f16SArnaldo Carvalho de Melo if (forks) { 11413e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 11428ceb41d7SJiri Olsa argv, data->is_pipe, 1143735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 114435b9d88eSArnaldo Carvalho de Melo if (err < 0) { 114535b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 114645604710SNamhyung Kim status = err; 114735b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 1148856e9660SPeter Zijlstra } 1149856e9660SPeter Zijlstra } 1150856e9660SPeter Zijlstra 1151ad46e48cSJiri Olsa /* 1152ad46e48cSJiri Olsa * If we have just single event and are sending data 1153ad46e48cSJiri Olsa * through pipe, we need to force the ids allocation, 1154ad46e48cSJiri Olsa * because we synthesize event name through the pipe 1155ad46e48cSJiri Olsa * and need the id for that. 1156ad46e48cSJiri Olsa */ 1157ad46e48cSJiri Olsa if (data->is_pipe && rec->evlist->nr_entries == 1) 1158ad46e48cSJiri Olsa rec->opts.sample_id = true; 1159ad46e48cSJiri Olsa 11608c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 11618d3eca20SDavid Ahern err = -1; 116245604710SNamhyung Kim goto out_child; 11638d3eca20SDavid Ahern } 116486470930SIngo Molnar 11658690a2a7SWang Nan err = bpf__apply_obj_config(); 11668690a2a7SWang Nan if (err) { 11678690a2a7SWang Nan char errbuf[BUFSIZ]; 11688690a2a7SWang Nan 11698690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 11708690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 11718690a2a7SWang Nan errbuf); 11728690a2a7SWang Nan goto out_child; 11738690a2a7SWang Nan } 11748690a2a7SWang Nan 1175cca8482cSAdrian Hunter /* 1176cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 1177cca8482cSAdrian Hunter * evlist. 1178cca8482cSAdrian Hunter */ 1179cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 1180cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 1181cca8482cSAdrian Hunter rec->tool.ordered_events = false; 1182cca8482cSAdrian Hunter } 1183cca8482cSAdrian Hunter 11843e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 1185a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 1186a8bb559bSNamhyung Kim 11878ceb41d7SJiri Olsa if (data->is_pipe) { 118842aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 1189529870e3STom Zanussi if (err < 0) 119045604710SNamhyung Kim goto out_child; 1191563aecb2SJiri Olsa } else { 119242aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 1193d5eed904SArnaldo Carvalho de Melo if (err < 0) 119445604710SNamhyung Kim goto out_child; 1195d5eed904SArnaldo Carvalho de Melo } 11967c6a1c65SPeter Zijlstra 1197d3665498SDavid Ahern if (!rec->no_buildid 1198e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 1199d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 1200e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 12018d3eca20SDavid Ahern err = -1; 120245604710SNamhyung Kim goto out_child; 1203e20960c0SRobert Richter } 1204e20960c0SRobert Richter 12054ea648aeSWang Nan err = record__synthesize(rec, false); 1206c45c86ebSWang Nan if (err < 0) 120745604710SNamhyung Kim goto out_child; 12088d3eca20SDavid Ahern 1209d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 121086470930SIngo Molnar struct sched_param param; 121186470930SIngo Molnar 1212d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 121386470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 12146beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 12158d3eca20SDavid Ahern err = -1; 121645604710SNamhyung Kim goto out_child; 121786470930SIngo Molnar } 121886470930SIngo Molnar } 121986470930SIngo Molnar 1220774cb499SJiri Olsa /* 1221774cb499SJiri Olsa * When perf is starting the traced process, all the events 1222774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 1223774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 1224774cb499SJiri Olsa */ 12256619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 12263e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 1227764e16a3SDavid Ahern 1228856e9660SPeter Zijlstra /* 1229856e9660SPeter Zijlstra * Let the child rip 1230856e9660SPeter Zijlstra */ 1231e803cf97SNamhyung Kim if (forks) { 123220a8a3cfSJiri Olsa struct machine *machine = &session->machines.host; 1233e5bed564SNamhyung Kim union perf_event *event; 1234e907caf3SHari Bathini pid_t tgid; 1235e5bed564SNamhyung Kim 1236e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 1237e5bed564SNamhyung Kim if (event == NULL) { 1238e5bed564SNamhyung Kim err = -ENOMEM; 1239e5bed564SNamhyung Kim goto out_child; 1240e5bed564SNamhyung Kim } 1241e5bed564SNamhyung Kim 1242e803cf97SNamhyung Kim /* 1243e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 1244e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 1245e803cf97SNamhyung Kim * cannot see a correct process name for those events. 1246e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 1247e803cf97SNamhyung Kim */ 1248e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event, 1249e803cf97SNamhyung Kim rec->evlist->workload.pid, 1250e803cf97SNamhyung Kim process_synthesized_event, 1251e803cf97SNamhyung Kim machine); 1252e5bed564SNamhyung Kim free(event); 1253e803cf97SNamhyung Kim 1254e907caf3SHari Bathini if (tgid == -1) 1255e907caf3SHari Bathini goto out_child; 1256e907caf3SHari Bathini 1257e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) + 1258e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 1259e907caf3SHari Bathini machine->id_hdr_size); 1260e907caf3SHari Bathini if (event == NULL) { 1261e907caf3SHari Bathini err = -ENOMEM; 1262e907caf3SHari Bathini goto out_child; 1263e907caf3SHari Bathini } 1264e907caf3SHari Bathini 1265e907caf3SHari Bathini /* 1266e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified. 1267e907caf3SHari Bathini */ 1268e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event, 1269e907caf3SHari Bathini rec->evlist->workload.pid, 1270e907caf3SHari Bathini tgid, process_synthesized_event, 1271e907caf3SHari Bathini machine); 1272e907caf3SHari Bathini free(event); 1273e907caf3SHari Bathini 12743e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 1275e803cf97SNamhyung Kim } 1276856e9660SPeter Zijlstra 12776619a53eSAndi Kleen if (opts->initial_delay) { 12780693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 12796619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 12806619a53eSAndi Kleen } 12816619a53eSAndi Kleen 12825f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 12833c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 1284a074865eSWang Nan perf_hooks__invoke_record_start(); 1285649c48a9SPeter Zijlstra for (;;) { 12869f065194SYang Shi unsigned long long hits = rec->samples; 128786470930SIngo Molnar 128805737464SWang Nan /* 128905737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 129005737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 129105737464SWang Nan * hits != rec->samples in previous round. 129205737464SWang Nan * 129305737464SWang Nan * perf_evlist__toggle_bkw_mmap ensure we never 129405737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 129505737464SWang Nan */ 129605737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 129705737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 129805737464SWang Nan 12998c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 13005f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 13013c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 13028d3eca20SDavid Ahern err = -1; 130345604710SNamhyung Kim goto out_child; 13048d3eca20SDavid Ahern } 130586470930SIngo Molnar 13062dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 13072dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 13085f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 13092dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 13105f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 13112dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 13122dd6d8a1SAdrian Hunter err = -1; 13132dd6d8a1SAdrian Hunter goto out_child; 13142dd6d8a1SAdrian Hunter } 13152dd6d8a1SAdrian Hunter } 13162dd6d8a1SAdrian Hunter 13173c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 131805737464SWang Nan /* 131905737464SWang Nan * If switch_output_trigger is hit, the data in 132005737464SWang Nan * overwritable ring buffer should have been collected, 132105737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 132205737464SWang Nan * 132305737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 132405737464SWang Nan * record__mmap_read_all() didn't collect data from 132505737464SWang Nan * overwritable ring buffer. Read again. 132605737464SWang Nan */ 132705737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 132805737464SWang Nan continue; 13293c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 13303c1cb7e3SWang Nan 133105737464SWang Nan /* 133205737464SWang Nan * Reenable events in overwrite ring buffer after 133305737464SWang Nan * record__mmap_read_all(): we should have collected 133405737464SWang Nan * data from it. 133505737464SWang Nan */ 133605737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 133705737464SWang Nan 13383c1cb7e3SWang Nan if (!quiet) 13393c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 13403c1cb7e3SWang Nan waking); 13413c1cb7e3SWang Nan waking = 0; 13423c1cb7e3SWang Nan fd = record__switch_output(rec, false); 13433c1cb7e3SWang Nan if (fd < 0) { 13443c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 13453c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 13463c1cb7e3SWang Nan err = fd; 13473c1cb7e3SWang Nan goto out_child; 13483c1cb7e3SWang Nan } 1349bfacbe3bSJiri Olsa 1350bfacbe3bSJiri Olsa /* re-arm the alarm */ 1351bfacbe3bSJiri Olsa if (rec->switch_output.time) 1352bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 13533c1cb7e3SWang Nan } 13543c1cb7e3SWang Nan 1355d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 13566dcf45efSArnaldo Carvalho de Melo if (done || draining) 1357649c48a9SPeter Zijlstra break; 1358f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 1359a515114fSJiri Olsa /* 1360a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1361a515114fSJiri Olsa * number of returned events and interrupt error. 1362a515114fSJiri Olsa */ 1363a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 136445604710SNamhyung Kim err = 0; 13658b412664SPeter Zijlstra waking++; 13666dcf45efSArnaldo Carvalho de Melo 13676dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 13686dcf45efSArnaldo Carvalho de Melo draining = true; 13698b412664SPeter Zijlstra } 13708b412664SPeter Zijlstra 1371774cb499SJiri Olsa /* 1372774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1373774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1374774cb499SJiri Olsa * disable events in this case. 1375774cb499SJiri Olsa */ 1376602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 13775f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 13783e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 13792711926aSJiri Olsa disabled = true; 13802711926aSJiri Olsa } 13818b412664SPeter Zijlstra } 13825f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 13833c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 13848b412664SPeter Zijlstra 1385f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 138635550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 1387c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 1388f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 1389f33cbe72SArnaldo Carvalho de Melo err = -1; 139045604710SNamhyung Kim goto out_child; 1391f33cbe72SArnaldo Carvalho de Melo } 1392f33cbe72SArnaldo Carvalho de Melo 1393e3d59112SNamhyung Kim if (!quiet) 13948b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 139586470930SIngo Molnar 13964ea648aeSWang Nan if (target__none(&rec->opts.target)) 13974ea648aeSWang Nan record__synthesize_workload(rec, true); 13984ea648aeSWang Nan 139945604710SNamhyung Kim out_child: 1400d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 1401d3d1af6fSAlexey Budankov 140245604710SNamhyung Kim if (forks) { 140345604710SNamhyung Kim int exit_status; 140445604710SNamhyung Kim 140545604710SNamhyung Kim if (!child_finished) 140645604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 140745604710SNamhyung Kim 140845604710SNamhyung Kim wait(&exit_status); 140945604710SNamhyung Kim 141045604710SNamhyung Kim if (err < 0) 141145604710SNamhyung Kim status = err; 141245604710SNamhyung Kim else if (WIFEXITED(exit_status)) 141345604710SNamhyung Kim status = WEXITSTATUS(exit_status); 141445604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 141545604710SNamhyung Kim signr = WTERMSIG(exit_status); 141645604710SNamhyung Kim } else 141745604710SNamhyung Kim status = err; 141845604710SNamhyung Kim 14194ea648aeSWang Nan record__synthesize(rec, true); 1420e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 1421e3d59112SNamhyung Kim rec->samples = 0; 1422e3d59112SNamhyung Kim 1423ecfd7a9cSWang Nan if (!err) { 1424ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 1425e1ab48baSWang Nan record__finish_output(rec); 1426ecfd7a9cSWang Nan } else { 1427ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1428ecfd7a9cSWang Nan if (fd < 0) { 1429ecfd7a9cSWang Nan status = fd; 1430ecfd7a9cSWang Nan goto out_delete_session; 1431ecfd7a9cSWang Nan } 1432ecfd7a9cSWang Nan } 1433ecfd7a9cSWang Nan } 143439d17dacSArnaldo Carvalho de Melo 1435a074865eSWang Nan perf_hooks__invoke_record_end(); 1436a074865eSWang Nan 1437e3d59112SNamhyung Kim if (!err && !quiet) { 1438e3d59112SNamhyung Kim char samples[128]; 1439ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1440ecfd7a9cSWang Nan ".<timestamp>" : ""; 1441e3d59112SNamhyung Kim 1442ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1443e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1444e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1445e3d59112SNamhyung Kim else 1446e3d59112SNamhyung Kim samples[0] = '\0'; 1447e3d59112SNamhyung Kim 1448ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 14498ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0, 1450eae8ad80SJiri Olsa data->file.path, postfix, samples); 1451e3d59112SNamhyung Kim } 1452e3d59112SNamhyung Kim 145339d17dacSArnaldo Carvalho de Melo out_delete_session: 145439d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 145545604710SNamhyung Kim return status; 145686470930SIngo Molnar } 145786470930SIngo Molnar 14580883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 145909b0fd45SJiri Olsa { 1460aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1461a601fdffSJiri Olsa 14620883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 146326d33022SJiri Olsa 14640883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 146509b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 14660883e820SArnaldo Carvalho de Melo callchain->dump_size); 14670883e820SArnaldo Carvalho de Melo } 14680883e820SArnaldo Carvalho de Melo 14690883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 14700883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 14710883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 14720883e820SArnaldo Carvalho de Melo { 14730883e820SArnaldo Carvalho de Melo int ret; 14740883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 14750883e820SArnaldo Carvalho de Melo 14760883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 14770883e820SArnaldo Carvalho de Melo if (unset) { 14780883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 14790883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 14800883e820SArnaldo Carvalho de Melo return 0; 14810883e820SArnaldo Carvalho de Melo } 14820883e820SArnaldo Carvalho de Melo 14830883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 14840883e820SArnaldo Carvalho de Melo if (!ret) { 14850883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 14860883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 14870883e820SArnaldo Carvalho de Melo record->sample_address = true; 14880883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 14890883e820SArnaldo Carvalho de Melo } 14900883e820SArnaldo Carvalho de Melo 14910883e820SArnaldo Carvalho de Melo return ret; 149209b0fd45SJiri Olsa } 149309b0fd45SJiri Olsa 1494c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 149509b0fd45SJiri Olsa const char *arg, 149609b0fd45SJiri Olsa int unset) 149709b0fd45SJiri Olsa { 14980883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 149926d33022SJiri Olsa } 150026d33022SJiri Olsa 1501c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 150209b0fd45SJiri Olsa const char *arg __maybe_unused, 150309b0fd45SJiri Olsa int unset __maybe_unused) 150409b0fd45SJiri Olsa { 15052ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1506c421e80bSKan Liang 15072ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 150809b0fd45SJiri Olsa 15092ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 15102ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1511eb853e80SJiri Olsa 15122ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 151309b0fd45SJiri Olsa return 0; 151409b0fd45SJiri Olsa } 151509b0fd45SJiri Olsa 1516eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1517eb853e80SJiri Olsa { 15187a29c087SNamhyung Kim struct record *rec = cb; 15197a29c087SNamhyung Kim 15207a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 15217a29c087SNamhyung Kim if (!strcmp(value, "cache")) 15227a29c087SNamhyung Kim rec->no_buildid_cache = false; 15237a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 15247a29c087SNamhyung Kim rec->no_buildid_cache = true; 15257a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 15267a29c087SNamhyung Kim rec->no_buildid = true; 15277a29c087SNamhyung Kim else 15287a29c087SNamhyung Kim return -1; 15297a29c087SNamhyung Kim return 0; 15307a29c087SNamhyung Kim } 1531cff17205SYisheng Xie if (!strcmp(var, "record.call-graph")) { 1532cff17205SYisheng Xie var = "call-graph.record-mode"; 1533eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1534eb853e80SJiri Olsa } 153593f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 153693f20c0fSAlexey Budankov if (!strcmp(var, "record.aio")) { 153793f20c0fSAlexey Budankov rec->opts.nr_cblocks = strtol(value, NULL, 0); 153893f20c0fSAlexey Budankov if (!rec->opts.nr_cblocks) 153993f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_default; 154093f20c0fSAlexey Budankov } 154193f20c0fSAlexey Budankov #endif 1542eb853e80SJiri Olsa 1543cff17205SYisheng Xie return 0; 1544cff17205SYisheng Xie } 1545cff17205SYisheng Xie 1546814c8c38SPeter Zijlstra struct clockid_map { 1547814c8c38SPeter Zijlstra const char *name; 1548814c8c38SPeter Zijlstra int clockid; 1549814c8c38SPeter Zijlstra }; 1550814c8c38SPeter Zijlstra 1551814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1552814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1553814c8c38SPeter Zijlstra 1554814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1555814c8c38SPeter Zijlstra 1556814c8c38SPeter Zijlstra 1557814c8c38SPeter Zijlstra /* 1558814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1559814c8c38SPeter Zijlstra */ 1560814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1561814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1562814c8c38SPeter Zijlstra #endif 1563814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1564814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1565814c8c38SPeter Zijlstra #endif 1566814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1567814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1568814c8c38SPeter Zijlstra #endif 1569814c8c38SPeter Zijlstra 1570814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1571814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1572814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1573814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1574814c8c38SPeter Zijlstra 1575814c8c38SPeter Zijlstra /* available for some events */ 1576814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1577814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1578814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1579814c8c38SPeter Zijlstra 1580814c8c38SPeter Zijlstra /* available for the lazy */ 1581814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1582814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1583814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1584814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1585814c8c38SPeter Zijlstra 1586814c8c38SPeter Zijlstra CLOCKID_END, 1587814c8c38SPeter Zijlstra }; 1588814c8c38SPeter Zijlstra 1589cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns) 1590cf790516SAlexey Budankov { 1591cf790516SAlexey Budankov struct timespec res; 1592cf790516SAlexey Budankov 1593cf790516SAlexey Budankov *res_ns = 0; 1594cf790516SAlexey Budankov if (!clock_getres(clk_id, &res)) 1595cf790516SAlexey Budankov *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC; 1596cf790516SAlexey Budankov else 1597cf790516SAlexey Budankov pr_warning("WARNING: Failed to determine specified clock resolution.\n"); 1598cf790516SAlexey Budankov 1599cf790516SAlexey Budankov return 0; 1600cf790516SAlexey Budankov } 1601cf790516SAlexey Budankov 1602814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1603814c8c38SPeter Zijlstra { 1604814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1605814c8c38SPeter Zijlstra const struct clockid_map *cm; 1606814c8c38SPeter Zijlstra const char *ostr = str; 1607814c8c38SPeter Zijlstra 1608814c8c38SPeter Zijlstra if (unset) { 1609814c8c38SPeter Zijlstra opts->use_clockid = 0; 1610814c8c38SPeter Zijlstra return 0; 1611814c8c38SPeter Zijlstra } 1612814c8c38SPeter Zijlstra 1613814c8c38SPeter Zijlstra /* no arg passed */ 1614814c8c38SPeter Zijlstra if (!str) 1615814c8c38SPeter Zijlstra return 0; 1616814c8c38SPeter Zijlstra 1617814c8c38SPeter Zijlstra /* no setting it twice */ 1618814c8c38SPeter Zijlstra if (opts->use_clockid) 1619814c8c38SPeter Zijlstra return -1; 1620814c8c38SPeter Zijlstra 1621814c8c38SPeter Zijlstra opts->use_clockid = true; 1622814c8c38SPeter Zijlstra 1623814c8c38SPeter Zijlstra /* if its a number, we're done */ 1624814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1625cf790516SAlexey Budankov return get_clockid_res(opts->clockid, &opts->clockid_res_ns); 1626814c8c38SPeter Zijlstra 1627814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1628814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1629814c8c38SPeter Zijlstra str += 6; 1630814c8c38SPeter Zijlstra 1631814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1632814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1633814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1634cf790516SAlexey Budankov return get_clockid_res(opts->clockid, 1635cf790516SAlexey Budankov &opts->clockid_res_ns); 1636814c8c38SPeter Zijlstra } 1637814c8c38SPeter Zijlstra } 1638814c8c38SPeter Zijlstra 1639814c8c38SPeter Zijlstra opts->use_clockid = false; 1640814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1641814c8c38SPeter Zijlstra return -1; 1642814c8c38SPeter Zijlstra } 1643814c8c38SPeter Zijlstra 1644e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1645e9db1310SAdrian Hunter const char *str, 1646e9db1310SAdrian Hunter int unset __maybe_unused) 1647e9db1310SAdrian Hunter { 1648e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1649e9db1310SAdrian Hunter char *s, *p; 1650e9db1310SAdrian Hunter unsigned int mmap_pages; 1651e9db1310SAdrian Hunter int ret; 1652e9db1310SAdrian Hunter 1653e9db1310SAdrian Hunter if (!str) 1654e9db1310SAdrian Hunter return -EINVAL; 1655e9db1310SAdrian Hunter 1656e9db1310SAdrian Hunter s = strdup(str); 1657e9db1310SAdrian Hunter if (!s) 1658e9db1310SAdrian Hunter return -ENOMEM; 1659e9db1310SAdrian Hunter 1660e9db1310SAdrian Hunter p = strchr(s, ','); 1661e9db1310SAdrian Hunter if (p) 1662e9db1310SAdrian Hunter *p = '\0'; 1663e9db1310SAdrian Hunter 1664e9db1310SAdrian Hunter if (*s) { 1665e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1666e9db1310SAdrian Hunter if (ret) 1667e9db1310SAdrian Hunter goto out_free; 1668e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1669e9db1310SAdrian Hunter } 1670e9db1310SAdrian Hunter 1671e9db1310SAdrian Hunter if (!p) { 1672e9db1310SAdrian Hunter ret = 0; 1673e9db1310SAdrian Hunter goto out_free; 1674e9db1310SAdrian Hunter } 1675e9db1310SAdrian Hunter 1676e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1677e9db1310SAdrian Hunter if (ret) 1678e9db1310SAdrian Hunter goto out_free; 1679e9db1310SAdrian Hunter 1680e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1681e9db1310SAdrian Hunter 1682e9db1310SAdrian Hunter out_free: 1683e9db1310SAdrian Hunter free(s); 1684e9db1310SAdrian Hunter return ret; 1685e9db1310SAdrian Hunter } 1686e9db1310SAdrian Hunter 16870c582449SJiri Olsa static void switch_output_size_warn(struct record *rec) 16880c582449SJiri Olsa { 16890c582449SJiri Olsa u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages); 16900c582449SJiri Olsa struct switch_output *s = &rec->switch_output; 16910c582449SJiri Olsa 16920c582449SJiri Olsa wakeup_size /= 2; 16930c582449SJiri Olsa 16940c582449SJiri Olsa if (s->size < wakeup_size) { 16950c582449SJiri Olsa char buf[100]; 16960c582449SJiri Olsa 16970c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 16980c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than " 16990c582449SJiri Olsa "wakeup kernel buffer size (%s) " 17000c582449SJiri Olsa "expect bigger perf.data sizes\n", buf); 17010c582449SJiri Olsa } 17020c582449SJiri Olsa } 17030c582449SJiri Olsa 1704cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec) 1705cb4e1ebbSJiri Olsa { 1706cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output; 1707dc0c6127SJiri Olsa static struct parse_tag tags_size[] = { 1708dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 }, 1709dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 1710dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 1711dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 1712dc0c6127SJiri Olsa { .tag = 0 }, 1713dc0c6127SJiri Olsa }; 1714bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = { 1715bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 }, 1716bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 }, 1717bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 }, 1718bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 }, 1719bfacbe3bSJiri Olsa { .tag = 0 }, 1720bfacbe3bSJiri Olsa }; 1721dc0c6127SJiri Olsa unsigned long val; 1722cb4e1ebbSJiri Olsa 1723cb4e1ebbSJiri Olsa if (!s->set) 1724cb4e1ebbSJiri Olsa return 0; 1725cb4e1ebbSJiri Olsa 1726cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) { 1727cb4e1ebbSJiri Olsa s->signal = true; 1728cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n"); 1729dc0c6127SJiri Olsa goto enabled; 1730dc0c6127SJiri Olsa } 1731dc0c6127SJiri Olsa 1732dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size); 1733dc0c6127SJiri Olsa if (val != (unsigned long) -1) { 1734dc0c6127SJiri Olsa s->size = val; 1735dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str); 1736dc0c6127SJiri Olsa goto enabled; 1737cb4e1ebbSJiri Olsa } 1738cb4e1ebbSJiri Olsa 1739bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time); 1740bfacbe3bSJiri Olsa if (val != (unsigned long) -1) { 1741bfacbe3bSJiri Olsa s->time = val; 1742bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n", 1743bfacbe3bSJiri Olsa s->str, s->time); 1744bfacbe3bSJiri Olsa goto enabled; 1745bfacbe3bSJiri Olsa } 1746bfacbe3bSJiri Olsa 1747cb4e1ebbSJiri Olsa return -1; 1748dc0c6127SJiri Olsa 1749dc0c6127SJiri Olsa enabled: 1750dc0c6127SJiri Olsa rec->timestamp_filename = true; 1751dc0c6127SJiri Olsa s->enabled = true; 17520c582449SJiri Olsa 17530c582449SJiri Olsa if (s->size && !rec->opts.no_buffering) 17540c582449SJiri Olsa switch_output_size_warn(rec); 17550c582449SJiri Olsa 1756dc0c6127SJiri Olsa return 0; 1757cb4e1ebbSJiri Olsa } 1758cb4e1ebbSJiri Olsa 1759e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 176086470930SIngo Molnar "perf record [<options>] [<command>]", 176186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 176286470930SIngo Molnar NULL 176386470930SIngo Molnar }; 1764e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 176586470930SIngo Molnar 1766d20deb64SArnaldo Carvalho de Melo /* 17678c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 17688c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1769d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1770d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1771d20deb64SArnaldo Carvalho de Melo * 1772d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1773d20deb64SArnaldo Carvalho de Melo * 1774d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1775d20deb64SArnaldo Carvalho de Melo */ 17768c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1777d20deb64SArnaldo Carvalho de Melo .opts = { 17788affc2b8SAndi Kleen .sample_time = true, 1779d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1780d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1781d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1782447a6013SArnaldo Carvalho de Melo .freq = 4000, 1783d1cb9fceSNamhyung Kim .target = { 1784d1cb9fceSNamhyung Kim .uses_mmap = true, 17853aa5939dSAdrian Hunter .default_per_cpu = true, 1786d1cb9fceSNamhyung Kim }, 1787d20deb64SArnaldo Carvalho de Melo }, 1788e3d59112SNamhyung Kim .tool = { 1789e3d59112SNamhyung Kim .sample = process_sample_event, 1790e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1791cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1792e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1793f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces, 1794e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1795e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1796cca8482cSAdrian Hunter .ordered_events = true, 1797e3d59112SNamhyung Kim }, 1798d20deb64SArnaldo Carvalho de Melo }; 17997865e817SFrederic Weisbecker 180076a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 180176a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 180261eaa3beSArnaldo Carvalho de Melo 18030aab2136SWang Nan static bool dry_run; 18040aab2136SWang Nan 1805d20deb64SArnaldo Carvalho de Melo /* 1806d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1807d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1808b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1809d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1810d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1811d20deb64SArnaldo Carvalho de Melo */ 1812efd21307SJiri Olsa static struct option __record_options[] = { 1813d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 181486470930SIngo Molnar "event selector. use 'perf list' to list available events", 1815f120f9d5SJiri Olsa parse_events_option), 1816d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1817c171b552SLi Zefan "event filter", parse_filter), 18184ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 18194ba1faa1SWang Nan NULL, "don't record events from perf itself", 18204ba1faa1SWang Nan exclude_perf), 1821bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1822d6d901c2SZhang, Yanmin "record events on existing process id"), 1823bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1824d6d901c2SZhang, Yanmin "record events on existing thread id"), 1825d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 182686470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1827509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1828acac03faSKirill Smelkov "collect data without buffering"), 1829d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1830daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1831bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 183286470930SIngo Molnar "system-wide collection from all CPUs"), 1833bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1834c45c6ea2SStephane Eranian "list of cpus to monitor"), 1835d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1836eae8ad80SJiri Olsa OPT_STRING('o', "output", &record.data.file.path, "file", 183786470930SIngo Molnar "output file name"), 183869e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 183969e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 18402e6cdf99SStephane Eranian "child tasks do not inherit counters"), 18414ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 18424ea648aeSWang Nan "synthesize non-sample events at the end of output"), 1843626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 184445178a92SSong Liu OPT_BOOLEAN(0, "bpf-event", &record.opts.bpf_event, "record bpf events"), 1845b09c2364SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 1846b09c2364SArnaldo Carvalho de Melo "Fail if the specified frequency can't be used"), 184767230479SArnaldo Carvalho de Melo OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 184867230479SArnaldo Carvalho de Melo "profile at this frequency", 184967230479SArnaldo Carvalho de Melo record__parse_freq), 1850e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1851e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1852e9db1310SAdrian Hunter record__parse_mmap_pages), 1853d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 185443bece79SLin Ming "put the counters into a counter group"), 18552ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 185609b0fd45SJiri Olsa NULL, "enables call-graph recording" , 185709b0fd45SJiri Olsa &record_callchain_opt), 185809b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 185976a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 186009b0fd45SJiri Olsa &record_parse_callchain_opt), 1861c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 18623da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1863b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1864d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1865649c48a9SPeter Zijlstra "per thread counts"), 186656100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 18673b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 18683b0a5daaSKan Liang "Record the sample physical addresses"), 1869b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 18703abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 18713abebc55SAdrian Hunter &record.opts.sample_time_set, 18723abebc55SAdrian Hunter "Record the sample timestamps"), 1873f290aa1fSJiri Olsa OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set, 1874f290aa1fSJiri Olsa "Record the sample period"), 1875d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1876649c48a9SPeter Zijlstra "don't sample"), 1877d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1878d2db9a98SWang Nan &record.no_buildid_cache_set, 1879a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1880d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1881d2db9a98SWang Nan &record.no_buildid_set, 1882baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1883d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1884023695d9SStephane Eranian "monitor event in cgroup name only", 1885023695d9SStephane Eranian parse_cgroups), 1886a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 18876619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1888bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1889bea03405SNamhyung Kim "user to profile"), 1890a5aabdacSStephane Eranian 1891a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1892a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1893a5aabdacSStephane Eranian parse_branch_stack), 1894a5aabdacSStephane Eranian 1895a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1896a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1897bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 189805484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 189905484298SAndi Kleen "sample by weight (on special events only)"), 1900475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1901475eeab9SAndi Kleen "sample transaction flags (special events only)"), 19023aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 19033aa5939dSAdrian Hunter "use per-thread mmaps"), 1904bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1905bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1906bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 190784c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 190884c41742SAndi Kleen "sample selected machine registers on interrupt," 190984c41742SAndi Kleen " use -I ? to list register names", parse_regs), 191085c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 191185c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1912814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1913814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1914814c8c38SPeter Zijlstra parse_clockid), 19152dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 19162dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 19173fcb10e4SMark Drayton OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout, 19189d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1919f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 1920f3b3614aSHari Bathini "Record namespaces events"), 1921b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1922b757bb09SAdrian Hunter "Record context switch events"), 192385723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 192485723885SJiri Olsa "Configure all used events to run in kernel space.", 192585723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 192685723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 192785723885SJiri Olsa "Configure all used events to run in user space.", 192885723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 192971dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 193071dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 193171dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 193271dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 19337efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 19347efe0e03SHe Kuang "file", "vmlinux pathname"), 19356156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 19366156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 1937ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1938ecfd7a9cSWang Nan "append timestamp to output filename"), 193968588bafSJin Yao OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 194068588bafSJin Yao "Record timestamp boundary (time of first/last samples)"), 1941cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 1942bfacbe3bSJiri Olsa &record.switch_output.set, "signal,size,time", 1943bfacbe3bSJiri Olsa "Switch output when receive SIGUSR2 or cross size,time threshold", 1944dc0c6127SJiri Olsa "signal"), 19450aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 19460aab2136SWang Nan "Parse options then exit"), 1947d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 194893f20c0fSAlexey Budankov OPT_CALLBACK_OPTARG(0, "aio", &record.opts, 194993f20c0fSAlexey Budankov &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)", 1950d3d1af6fSAlexey Budankov record__aio_parse), 1951d3d1af6fSAlexey Budankov #endif 195286470930SIngo Molnar OPT_END() 195386470930SIngo Molnar }; 195486470930SIngo Molnar 1955e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1956e5b2c207SNamhyung Kim 1957b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv) 195886470930SIngo Molnar { 1959ef149c25SAdrian Hunter int err; 19608c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 196116ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 196286470930SIngo Molnar 196367230479SArnaldo Carvalho de Melo setlocale(LC_ALL, ""); 196467230479SArnaldo Carvalho de Melo 196548e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 196648e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 196748e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 196848e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 196948e1cab1SWang Nan # undef set_nobuild 197048e1cab1SWang Nan #endif 197148e1cab1SWang Nan 19727efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 19737efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 19747efe0e03SHe Kuang # define REASON "NO_DWARF=1" 19757efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 19767efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 19777efe0e03SHe Kuang # else 19787efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 19797efe0e03SHe Kuang # endif 19807efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 19817efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 19827efe0e03SHe Kuang # undef set_nobuild 19837efe0e03SHe Kuang # undef REASON 19847efe0e03SHe Kuang #endif 19857efe0e03SHe Kuang 1986*9d2ed645SAlexey Budankov CPU_ZERO(&rec->affinity_mask); 1987*9d2ed645SAlexey Budankov rec->opts.affinity = PERF_AFFINITY_SYS; 1988*9d2ed645SAlexey Budankov 19893e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 19903e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1991361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1992361c99a6SArnaldo Carvalho de Melo 1993ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec); 1994ecc4c561SArnaldo Carvalho de Melo if (err) 1995ecc4c561SArnaldo Carvalho de Melo return err; 1996eb853e80SJiri Olsa 1997bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1998a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 199968ba3235SNamhyung Kim if (quiet) 200068ba3235SNamhyung Kim perf_quiet_option(); 2001483635a9SJiri Olsa 2002483635a9SJiri Olsa /* Make system wide (-a) the default target. */ 2003602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 2004483635a9SJiri Olsa rec->opts.target.system_wide = true; 200586470930SIngo Molnar 2006bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 2007c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 2008c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 2009c7118369SNamhyung Kim 2010023695d9SStephane Eranian } 2011b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 2012b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 2013c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 2014c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 2015c7118369SNamhyung Kim return -EINVAL; 2016b757bb09SAdrian Hunter } 2017023695d9SStephane Eranian 2018cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) { 2019cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0); 2020cb4e1ebbSJiri Olsa return -EINVAL; 2021cb4e1ebbSJiri Olsa } 2022cb4e1ebbSJiri Olsa 2023bfacbe3bSJiri Olsa if (rec->switch_output.time) { 2024bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler); 2025bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 2026bfacbe3bSJiri Olsa } 2027bfacbe3bSJiri Olsa 20281b36c03eSAdrian Hunter /* 20291b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address 20301b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters(). 20311b36c03eSAdrian Hunter */ 20321b36c03eSAdrian Hunter symbol_conf.allow_aliases = true; 20331b36c03eSAdrian Hunter 20341b36c03eSAdrian Hunter symbol__init(NULL); 20351b36c03eSAdrian Hunter 20364b5ea3bdSAdrian Hunter err = record__auxtrace_init(rec); 20371b36c03eSAdrian Hunter if (err) 20381b36c03eSAdrian Hunter goto out; 20391b36c03eSAdrian Hunter 20400aab2136SWang Nan if (dry_run) 20415c01ad60SAdrian Hunter goto out; 20420aab2136SWang Nan 2043d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 2044d7888573SWang Nan if (err) { 2045d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 2046d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 2047d7888573SWang Nan errbuf); 20485c01ad60SAdrian Hunter goto out; 2049d7888573SWang Nan } 2050d7888573SWang Nan 2051ef149c25SAdrian Hunter err = -ENOMEM; 2052ef149c25SAdrian Hunter 20536c443954SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(rec->evlist)) 2054646aaea6SArnaldo Carvalho de Melo pr_warning( 2055646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 2056ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 2057646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 2058646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 2059646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 2060646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 2061646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 2062ec80fde7SArnaldo Carvalho de Melo 20630c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 2064a1ac1d3cSStephane Eranian disable_buildid_cache(); 2065dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) { 20660c1d46a8SWang Nan /* 20670c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 20680c1d46a8SWang Nan * generation by default to reduce data file switching 20690c1d46a8SWang Nan * overhead. Still generate buildid if they are required 20700c1d46a8SWang Nan * explicitly using 20710c1d46a8SWang Nan * 207260437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \ 20730c1d46a8SWang Nan * --no-no-buildid-cache 20740c1d46a8SWang Nan * 20750c1d46a8SWang Nan * Following code equals to: 20760c1d46a8SWang Nan * 20770c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 20780c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 20790c1d46a8SWang Nan * disable_buildid_cache(); 20800c1d46a8SWang Nan */ 20810c1d46a8SWang Nan bool disable = true; 20820c1d46a8SWang Nan 20830c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 20840c1d46a8SWang Nan disable = false; 20850c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 20860c1d46a8SWang Nan disable = false; 20870c1d46a8SWang Nan if (disable) { 20880c1d46a8SWang Nan rec->no_buildid = true; 20890c1d46a8SWang Nan rec->no_buildid_cache = true; 20900c1d46a8SWang Nan disable_buildid_cache(); 20910c1d46a8SWang Nan } 20920c1d46a8SWang Nan } 2093655000e7SArnaldo Carvalho de Melo 20944ea648aeSWang Nan if (record.opts.overwrite) 20954ea648aeSWang Nan record.opts.tail_synthesize = true; 20964ea648aeSWang Nan 20973e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 20984b4cd503SArnaldo Carvalho de Melo __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { 209969aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 2100394c01edSAdrian Hunter goto out; 2101bbd36e5eSPeter Zijlstra } 210286470930SIngo Molnar 210369e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 210469e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 210569e7e5b0SAdrian Hunter 2106602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 210716ad2ffbSNamhyung Kim if (err) { 2108602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 2109c3dec27bSJiri Olsa ui__warning("%s\n", errbuf); 211016ad2ffbSNamhyung Kim } 21114bd0f2d2SNamhyung Kim 2112602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 211316ad2ffbSNamhyung Kim if (err) { 211416ad2ffbSNamhyung Kim int saved_errno = errno; 211516ad2ffbSNamhyung Kim 2116602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 21173780f488SNamhyung Kim ui__error("%s", errbuf); 211816ad2ffbSNamhyung Kim 211916ad2ffbSNamhyung Kim err = -saved_errno; 2120394c01edSAdrian Hunter goto out; 212116ad2ffbSNamhyung Kim } 21220d37aa34SArnaldo Carvalho de Melo 2123ca800068SMengting Zhang /* Enable ignoring missing threads when -u/-p option is defined. */ 2124ca800068SMengting Zhang rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; 212523dc4f15SJiri Olsa 212616ad2ffbSNamhyung Kim err = -ENOMEM; 21273e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 2128dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 212969aad6f1SArnaldo Carvalho de Melo 2130ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 2131ef149c25SAdrian Hunter if (err) 2132394c01edSAdrian Hunter goto out; 2133ef149c25SAdrian Hunter 21346156681bSNamhyung Kim /* 21356156681bSNamhyung Kim * We take all buildids when the file contains 21366156681bSNamhyung Kim * AUX area tracing data because we do not decode the 21376156681bSNamhyung Kim * trace because it would take too long. 21386156681bSNamhyung Kim */ 21396156681bSNamhyung Kim if (rec->opts.full_auxtrace) 21406156681bSNamhyung Kim rec->buildid_all = true; 21416156681bSNamhyung Kim 2142b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 214339d17dacSArnaldo Carvalho de Melo err = -EINVAL; 2144394c01edSAdrian Hunter goto out; 21457e4ff9e3SMike Galbraith } 21467e4ff9e3SMike Galbraith 214793f20c0fSAlexey Budankov if (rec->opts.nr_cblocks > nr_cblocks_max) 214893f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_max; 2149d3d1af6fSAlexey Budankov if (verbose > 0) 2150d3d1af6fSAlexey Budankov pr_info("nr_cblocks: %d\n", rec->opts.nr_cblocks); 2151d3d1af6fSAlexey Budankov 2152*9d2ed645SAlexey Budankov pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); 2153*9d2ed645SAlexey Budankov 2154d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 2155394c01edSAdrian Hunter out: 215645604710SNamhyung Kim perf_evlist__delete(rec->evlist); 2157d65a458bSArnaldo Carvalho de Melo symbol__exit(); 2158ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 215939d17dacSArnaldo Carvalho de Melo return err; 216086470930SIngo Molnar } 21612dd6d8a1SAdrian Hunter 21622dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 21632dd6d8a1SAdrian Hunter { 2164dc0c6127SJiri Olsa struct record *rec = &record; 2165dc0c6127SJiri Olsa 21665f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 21675f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 21682dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 21695f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 21705f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 21715f9cf599SWang Nan } 21723c1cb7e3SWang Nan 2173dc0c6127SJiri Olsa if (switch_output_signal(rec)) 21743c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 21752dd6d8a1SAdrian Hunter } 2176bfacbe3bSJiri Olsa 2177bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused) 2178bfacbe3bSJiri Olsa { 2179bfacbe3bSJiri Olsa struct record *rec = &record; 2180bfacbe3bSJiri Olsa 2181bfacbe3bSJiri Olsa if (switch_output_time(rec)) 2182bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger); 2183bfacbe3bSJiri Olsa } 2184