1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 286470930SIngo Molnar /* 386470930SIngo Molnar * builtin-record.c 486470930SIngo Molnar * 586470930SIngo Molnar * Builtin record command: Record the profile of a workload 686470930SIngo Molnar * (or a CPU, or a PID) into the perf.data output file - for 786470930SIngo Molnar * later analysis via perf report. 886470930SIngo Molnar */ 986470930SIngo Molnar #include "builtin.h" 1086470930SIngo Molnar 1186470930SIngo Molnar #include "perf.h" 1286470930SIngo Molnar 136122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 1486470930SIngo Molnar #include "util/util.h" 154b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1686470930SIngo Molnar #include "util/parse-events.h" 1741840d21STaeung Song #include "util/config.h" 1886470930SIngo Molnar 198f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 20f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 217c6a1c65SPeter Zijlstra #include "util/header.h" 2266e274f3SFrederic Weisbecker #include "util/event.h" 23361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2469aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 258f28827aSFrederic Weisbecker #include "util/debug.h" 2694c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2745694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 288d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 29a12b51c4SPaul Mackerras #include "util/cpumap.h" 30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 31f5fc1412SJiri Olsa #include "util/data.h" 32bcc84ec6SStephane Eranian #include "util/perf_regs.h" 33ef149c25SAdrian Hunter #include "util/auxtrace.h" 3446bc29b9SAdrian Hunter #include "util/tsc.h" 35f00898f4SAndi Kleen #include "util/parse-branch-options.h" 36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3771dc2326SWang Nan #include "util/llvm-utils.h" 388690a2a7SWang Nan #include "util/bpf-loader.h" 395f9cf599SWang Nan #include "util/trigger.h" 40a074865eSWang Nan #include "util/perf-hooks.h" 41f13de660SAlexey Budankov #include "util/cpu-set-sched.h" 42c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h" 4358db1d6eSArnaldo Carvalho de Melo #include "util/units.h" 447b612e29SSong Liu #include "util/bpf-event.h" 45d8871ea7SWang Nan #include "asm/bug.h" 467c6a1c65SPeter Zijlstra 47a43783aeSArnaldo Carvalho de Melo #include <errno.h> 48fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 4967230479SArnaldo Carvalho de Melo #include <locale.h> 504208735dSArnaldo Carvalho de Melo #include <poll.h> 5186470930SIngo Molnar #include <unistd.h> 5286470930SIngo Molnar #include <sched.h> 539607ad3aSArnaldo Carvalho de Melo #include <signal.h> 54a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 554208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 560693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 5778da39faSBernhard Rosenkraenzer 581b43b704SJiri Olsa struct switch_output { 59dc0c6127SJiri Olsa bool enabled; 601b43b704SJiri Olsa bool signal; 61dc0c6127SJiri Olsa unsigned long size; 62bfacbe3bSJiri Olsa unsigned long time; 63cb4e1ebbSJiri Olsa const char *str; 64cb4e1ebbSJiri Olsa bool set; 6503724b2eSAndi Kleen char **filenames; 6603724b2eSAndi Kleen int num_files; 6703724b2eSAndi Kleen int cur_file; 681b43b704SJiri Olsa }; 691b43b704SJiri Olsa 708c6f45a7SArnaldo Carvalho de Melo struct record { 7145694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 72b4006796SArnaldo Carvalho de Melo struct record_opts opts; 73d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 748ceb41d7SJiri Olsa struct perf_data data; 75ef149c25SAdrian Hunter struct auxtrace_record *itr; 76d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 77d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 78d20deb64SArnaldo Carvalho de Melo int realtime_prio; 79d20deb64SArnaldo Carvalho de Melo bool no_buildid; 80d2db9a98SWang Nan bool no_buildid_set; 81d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 82d2db9a98SWang Nan bool no_buildid_cache_set; 836156681bSNamhyung Kim bool buildid_all; 84ecfd7a9cSWang Nan bool timestamp_filename; 8568588bafSJin Yao bool timestamp_boundary; 861b43b704SJiri Olsa struct switch_output switch_output; 879f065194SYang Shi unsigned long long samples; 889d2ed645SAlexey Budankov cpu_set_t affinity_mask; 890f82ebc4SArnaldo Carvalho de Melo }; 9086470930SIngo Molnar 91dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started; 92dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 93dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger); 94dc0c6127SJiri Olsa 959d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = { 969d2ed645SAlexey Budankov "SYS", "NODE", "CPU" 979d2ed645SAlexey Budankov }; 989d2ed645SAlexey Budankov 99dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec) 100dc0c6127SJiri Olsa { 101dc0c6127SJiri Olsa return rec->switch_output.signal && 102dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger); 103dc0c6127SJiri Olsa } 104dc0c6127SJiri Olsa 105dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec) 106dc0c6127SJiri Olsa { 107dc0c6127SJiri Olsa return rec->switch_output.size && 108dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) && 109dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size); 110dc0c6127SJiri Olsa } 111dc0c6127SJiri Olsa 112bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec) 113bfacbe3bSJiri Olsa { 114bfacbe3bSJiri Olsa return rec->switch_output.time && 115bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger); 116bfacbe3bSJiri Olsa } 117bfacbe3bSJiri Olsa 118ded2b8feSJiri Olsa static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused, 119ded2b8feSJiri Olsa void *bf, size_t size) 120f5970550SPeter Zijlstra { 121ded2b8feSJiri Olsa struct perf_data_file *file = &rec->session->data->file; 122ded2b8feSJiri Olsa 123ded2b8feSJiri Olsa if (perf_data_file__write(file, bf, size) < 0) { 1244f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 1258d3eca20SDavid Ahern return -1; 1268d3eca20SDavid Ahern } 127f5970550SPeter Zijlstra 128cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 129dc0c6127SJiri Olsa 130dc0c6127SJiri Olsa if (switch_output_size(rec)) 131dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger); 132dc0c6127SJiri Olsa 1338d3eca20SDavid Ahern return 0; 134f5970550SPeter Zijlstra } 135f5970550SPeter Zijlstra 136d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 137d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd, 138d3d1af6fSAlexey Budankov void *buf, size_t size, off_t off) 139d3d1af6fSAlexey Budankov { 140d3d1af6fSAlexey Budankov int rc; 141d3d1af6fSAlexey Budankov 142d3d1af6fSAlexey Budankov cblock->aio_fildes = trace_fd; 143d3d1af6fSAlexey Budankov cblock->aio_buf = buf; 144d3d1af6fSAlexey Budankov cblock->aio_nbytes = size; 145d3d1af6fSAlexey Budankov cblock->aio_offset = off; 146d3d1af6fSAlexey Budankov cblock->aio_sigevent.sigev_notify = SIGEV_NONE; 147d3d1af6fSAlexey Budankov 148d3d1af6fSAlexey Budankov do { 149d3d1af6fSAlexey Budankov rc = aio_write(cblock); 150d3d1af6fSAlexey Budankov if (rc == 0) { 151d3d1af6fSAlexey Budankov break; 152d3d1af6fSAlexey Budankov } else if (errno != EAGAIN) { 153d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 154d3d1af6fSAlexey Budankov pr_err("failed to queue perf data, error: %m\n"); 155d3d1af6fSAlexey Budankov break; 156d3d1af6fSAlexey Budankov } 157d3d1af6fSAlexey Budankov } while (1); 158d3d1af6fSAlexey Budankov 159d3d1af6fSAlexey Budankov return rc; 160d3d1af6fSAlexey Budankov } 161d3d1af6fSAlexey Budankov 162d3d1af6fSAlexey Budankov static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock) 163d3d1af6fSAlexey Budankov { 164d3d1af6fSAlexey Budankov void *rem_buf; 165d3d1af6fSAlexey Budankov off_t rem_off; 166d3d1af6fSAlexey Budankov size_t rem_size; 167d3d1af6fSAlexey Budankov int rc, aio_errno; 168d3d1af6fSAlexey Budankov ssize_t aio_ret, written; 169d3d1af6fSAlexey Budankov 170d3d1af6fSAlexey Budankov aio_errno = aio_error(cblock); 171d3d1af6fSAlexey Budankov if (aio_errno == EINPROGRESS) 172d3d1af6fSAlexey Budankov return 0; 173d3d1af6fSAlexey Budankov 174d3d1af6fSAlexey Budankov written = aio_ret = aio_return(cblock); 175d3d1af6fSAlexey Budankov if (aio_ret < 0) { 176d3d1af6fSAlexey Budankov if (aio_errno != EINTR) 177d3d1af6fSAlexey Budankov pr_err("failed to write perf data, error: %m\n"); 178d3d1af6fSAlexey Budankov written = 0; 179d3d1af6fSAlexey Budankov } 180d3d1af6fSAlexey Budankov 181d3d1af6fSAlexey Budankov rem_size = cblock->aio_nbytes - written; 182d3d1af6fSAlexey Budankov 183d3d1af6fSAlexey Budankov if (rem_size == 0) { 184d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 185d3d1af6fSAlexey Budankov /* 186d3d1af6fSAlexey Budankov * md->refcount is incremented in perf_mmap__push() for 187d3d1af6fSAlexey Budankov * every enqueued aio write request so decrement it because 188d3d1af6fSAlexey Budankov * the request is now complete. 189d3d1af6fSAlexey Budankov */ 190d3d1af6fSAlexey Budankov perf_mmap__put(md); 191d3d1af6fSAlexey Budankov rc = 1; 192d3d1af6fSAlexey Budankov } else { 193d3d1af6fSAlexey Budankov /* 194d3d1af6fSAlexey Budankov * aio write request may require restart with the 195d3d1af6fSAlexey Budankov * reminder if the kernel didn't write whole 196d3d1af6fSAlexey Budankov * chunk at once. 197d3d1af6fSAlexey Budankov */ 198d3d1af6fSAlexey Budankov rem_off = cblock->aio_offset + written; 199d3d1af6fSAlexey Budankov rem_buf = (void *)(cblock->aio_buf + written); 200d3d1af6fSAlexey Budankov record__aio_write(cblock, cblock->aio_fildes, 201d3d1af6fSAlexey Budankov rem_buf, rem_size, rem_off); 202d3d1af6fSAlexey Budankov rc = 0; 203d3d1af6fSAlexey Budankov } 204d3d1af6fSAlexey Budankov 205d3d1af6fSAlexey Budankov return rc; 206d3d1af6fSAlexey Budankov } 207d3d1af6fSAlexey Budankov 20893f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md, bool sync_all) 209d3d1af6fSAlexey Budankov { 21093f20c0fSAlexey Budankov struct aiocb **aiocb = md->aio.aiocb; 21193f20c0fSAlexey Budankov struct aiocb *cblocks = md->aio.cblocks; 212d3d1af6fSAlexey Budankov struct timespec timeout = { 0, 1000 * 1000 * 1 }; /* 1ms */ 21393f20c0fSAlexey Budankov int i, do_suspend; 214d3d1af6fSAlexey Budankov 215d3d1af6fSAlexey Budankov do { 21693f20c0fSAlexey Budankov do_suspend = 0; 21793f20c0fSAlexey Budankov for (i = 0; i < md->aio.nr_cblocks; ++i) { 21893f20c0fSAlexey Budankov if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) { 21993f20c0fSAlexey Budankov if (sync_all) 22093f20c0fSAlexey Budankov aiocb[i] = NULL; 22193f20c0fSAlexey Budankov else 22293f20c0fSAlexey Budankov return i; 22393f20c0fSAlexey Budankov } else { 22493f20c0fSAlexey Budankov /* 22593f20c0fSAlexey Budankov * Started aio write is not complete yet 22693f20c0fSAlexey Budankov * so it has to be waited before the 22793f20c0fSAlexey Budankov * next allocation. 22893f20c0fSAlexey Budankov */ 22993f20c0fSAlexey Budankov aiocb[i] = &cblocks[i]; 23093f20c0fSAlexey Budankov do_suspend = 1; 23193f20c0fSAlexey Budankov } 23293f20c0fSAlexey Budankov } 23393f20c0fSAlexey Budankov if (!do_suspend) 23493f20c0fSAlexey Budankov return -1; 235d3d1af6fSAlexey Budankov 23693f20c0fSAlexey Budankov while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) { 237d3d1af6fSAlexey Budankov if (!(errno == EAGAIN || errno == EINTR)) 238d3d1af6fSAlexey Budankov pr_err("failed to sync perf data, error: %m\n"); 239d3d1af6fSAlexey Budankov } 240d3d1af6fSAlexey Budankov } while (1); 241d3d1af6fSAlexey Budankov } 242d3d1af6fSAlexey Budankov 243d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t size, off_t off) 244d3d1af6fSAlexey Budankov { 245d3d1af6fSAlexey Budankov struct record *rec = to; 246d3d1af6fSAlexey Budankov int ret, trace_fd = rec->session->data->file.fd; 247d3d1af6fSAlexey Budankov 248d3d1af6fSAlexey Budankov rec->samples++; 249d3d1af6fSAlexey Budankov 250d3d1af6fSAlexey Budankov ret = record__aio_write(cblock, trace_fd, bf, size, off); 251d3d1af6fSAlexey Budankov if (!ret) { 252d3d1af6fSAlexey Budankov rec->bytes_written += size; 253d3d1af6fSAlexey Budankov if (switch_output_size(rec)) 254d3d1af6fSAlexey Budankov trigger_hit(&switch_output_trigger); 255d3d1af6fSAlexey Budankov } 256d3d1af6fSAlexey Budankov 257d3d1af6fSAlexey Budankov return ret; 258d3d1af6fSAlexey Budankov } 259d3d1af6fSAlexey Budankov 260d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd) 261d3d1af6fSAlexey Budankov { 262d3d1af6fSAlexey Budankov return lseek(trace_fd, 0, SEEK_CUR); 263d3d1af6fSAlexey Budankov } 264d3d1af6fSAlexey Budankov 265d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos) 266d3d1af6fSAlexey Budankov { 267d3d1af6fSAlexey Budankov lseek(trace_fd, pos, SEEK_SET); 268d3d1af6fSAlexey Budankov } 269d3d1af6fSAlexey Budankov 270d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec) 271d3d1af6fSAlexey Budankov { 272d3d1af6fSAlexey Budankov int i; 273d3d1af6fSAlexey Budankov struct perf_evlist *evlist = rec->evlist; 274d3d1af6fSAlexey Budankov struct perf_mmap *maps = evlist->mmap; 275d3d1af6fSAlexey Budankov 276d3d1af6fSAlexey Budankov if (!rec->opts.nr_cblocks) 277d3d1af6fSAlexey Budankov return; 278d3d1af6fSAlexey Budankov 279d3d1af6fSAlexey Budankov for (i = 0; i < evlist->nr_mmaps; i++) { 280d3d1af6fSAlexey Budankov struct perf_mmap *map = &maps[i]; 281d3d1af6fSAlexey Budankov 282d3d1af6fSAlexey Budankov if (map->base) 28393f20c0fSAlexey Budankov record__aio_sync(map, true); 284d3d1af6fSAlexey Budankov } 285d3d1af6fSAlexey Budankov } 286d3d1af6fSAlexey Budankov 287d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1; 28893f20c0fSAlexey Budankov static int nr_cblocks_max = 4; 289d3d1af6fSAlexey Budankov 290d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt, 29193f20c0fSAlexey Budankov const char *str, 292d3d1af6fSAlexey Budankov int unset) 293d3d1af6fSAlexey Budankov { 294d3d1af6fSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 295d3d1af6fSAlexey Budankov 29693f20c0fSAlexey Budankov if (unset) { 297d3d1af6fSAlexey Budankov opts->nr_cblocks = 0; 29893f20c0fSAlexey Budankov } else { 29993f20c0fSAlexey Budankov if (str) 30093f20c0fSAlexey Budankov opts->nr_cblocks = strtol(str, NULL, 0); 30193f20c0fSAlexey Budankov if (!opts->nr_cblocks) 302d3d1af6fSAlexey Budankov opts->nr_cblocks = nr_cblocks_default; 30393f20c0fSAlexey Budankov } 304d3d1af6fSAlexey Budankov 305d3d1af6fSAlexey Budankov return 0; 306d3d1af6fSAlexey Budankov } 307d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */ 30893f20c0fSAlexey Budankov static int nr_cblocks_max = 0; 30993f20c0fSAlexey Budankov 31093f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md __maybe_unused, bool sync_all __maybe_unused) 311d3d1af6fSAlexey Budankov { 31293f20c0fSAlexey Budankov return -1; 313d3d1af6fSAlexey Budankov } 314d3d1af6fSAlexey Budankov 315d3d1af6fSAlexey Budankov static int record__aio_pushfn(void *to __maybe_unused, struct aiocb *cblock __maybe_unused, 316d3d1af6fSAlexey Budankov void *bf __maybe_unused, size_t size __maybe_unused, off_t off __maybe_unused) 317d3d1af6fSAlexey Budankov { 318d3d1af6fSAlexey Budankov return -1; 319d3d1af6fSAlexey Budankov } 320d3d1af6fSAlexey Budankov 321d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused) 322d3d1af6fSAlexey Budankov { 323d3d1af6fSAlexey Budankov return -1; 324d3d1af6fSAlexey Budankov } 325d3d1af6fSAlexey Budankov 326d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused) 327d3d1af6fSAlexey Budankov { 328d3d1af6fSAlexey Budankov } 329d3d1af6fSAlexey Budankov 330d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused) 331d3d1af6fSAlexey Budankov { 332d3d1af6fSAlexey Budankov } 333d3d1af6fSAlexey Budankov #endif 334d3d1af6fSAlexey Budankov 335d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec) 336d3d1af6fSAlexey Budankov { 337d3d1af6fSAlexey Budankov return rec->opts.nr_cblocks > 0; 338d3d1af6fSAlexey Budankov } 339d3d1af6fSAlexey Budankov 340470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1 341470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt, 342470530bbSAlexey Budankov const char *str, 343470530bbSAlexey Budankov int unset) 344470530bbSAlexey Budankov { 345470530bbSAlexey Budankov int flush_max; 346470530bbSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 347470530bbSAlexey Budankov static struct parse_tag tags[] = { 348470530bbSAlexey Budankov { .tag = 'B', .mult = 1 }, 349470530bbSAlexey Budankov { .tag = 'K', .mult = 1 << 10 }, 350470530bbSAlexey Budankov { .tag = 'M', .mult = 1 << 20 }, 351470530bbSAlexey Budankov { .tag = 'G', .mult = 1 << 30 }, 352470530bbSAlexey Budankov { .tag = 0 }, 353470530bbSAlexey Budankov }; 354470530bbSAlexey Budankov 355470530bbSAlexey Budankov if (unset) 356470530bbSAlexey Budankov return 0; 357470530bbSAlexey Budankov 358470530bbSAlexey Budankov if (str) { 359470530bbSAlexey Budankov opts->mmap_flush = parse_tag_value(str, tags); 360470530bbSAlexey Budankov if (opts->mmap_flush == (int)-1) 361470530bbSAlexey Budankov opts->mmap_flush = strtol(str, NULL, 0); 362470530bbSAlexey Budankov } 363470530bbSAlexey Budankov 364470530bbSAlexey Budankov if (!opts->mmap_flush) 365470530bbSAlexey Budankov opts->mmap_flush = MMAP_FLUSH_DEFAULT; 366470530bbSAlexey Budankov 367470530bbSAlexey Budankov flush_max = perf_evlist__mmap_size(opts->mmap_pages); 368470530bbSAlexey Budankov flush_max /= 4; 369470530bbSAlexey Budankov if (opts->mmap_flush > flush_max) 370470530bbSAlexey Budankov opts->mmap_flush = flush_max; 371470530bbSAlexey Budankov 372470530bbSAlexey Budankov return 0; 373470530bbSAlexey Budankov } 374470530bbSAlexey Budankov 37545694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 376d20deb64SArnaldo Carvalho de Melo union perf_event *event, 3771d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 3781d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 379234fbbf5SArnaldo Carvalho de Melo { 3808c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 381ded2b8feSJiri Olsa return record__write(rec, NULL, event, event->header.size); 382234fbbf5SArnaldo Carvalho de Melo } 383234fbbf5SArnaldo Carvalho de Melo 384ded2b8feSJiri Olsa static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size) 385d37f1586SArnaldo Carvalho de Melo { 386d37f1586SArnaldo Carvalho de Melo struct record *rec = to; 387d37f1586SArnaldo Carvalho de Melo 388d37f1586SArnaldo Carvalho de Melo rec->samples++; 389ded2b8feSJiri Olsa return record__write(rec, map, bf, size); 390d37f1586SArnaldo Carvalho de Melo } 391d37f1586SArnaldo Carvalho de Melo 3922dd6d8a1SAdrian Hunter static volatile int done; 3932dd6d8a1SAdrian Hunter static volatile int signr = -1; 3942dd6d8a1SAdrian Hunter static volatile int child_finished; 395c0bdc1c4SWang Nan 3962dd6d8a1SAdrian Hunter static void sig_handler(int sig) 3972dd6d8a1SAdrian Hunter { 3982dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 3992dd6d8a1SAdrian Hunter child_finished = 1; 4002dd6d8a1SAdrian Hunter else 4012dd6d8a1SAdrian Hunter signr = sig; 4022dd6d8a1SAdrian Hunter 4032dd6d8a1SAdrian Hunter done = 1; 4042dd6d8a1SAdrian Hunter } 4052dd6d8a1SAdrian Hunter 406a074865eSWang Nan static void sigsegv_handler(int sig) 407a074865eSWang Nan { 408a074865eSWang Nan perf_hooks__recover(); 409a074865eSWang Nan sighandler_dump_stack(sig); 410a074865eSWang Nan } 411a074865eSWang Nan 4122dd6d8a1SAdrian Hunter static void record__sig_exit(void) 4132dd6d8a1SAdrian Hunter { 4142dd6d8a1SAdrian Hunter if (signr == -1) 4152dd6d8a1SAdrian Hunter return; 4162dd6d8a1SAdrian Hunter 4172dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 4182dd6d8a1SAdrian Hunter raise(signr); 4192dd6d8a1SAdrian Hunter } 4202dd6d8a1SAdrian Hunter 421e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 422e31f0d01SAdrian Hunter 423ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 424ded2b8feSJiri Olsa struct perf_mmap *map, 425ef149c25SAdrian Hunter union perf_event *event, void *data1, 426ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 427ef149c25SAdrian Hunter { 428ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 4298ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 430ef149c25SAdrian Hunter size_t padding; 431ef149c25SAdrian Hunter u8 pad[8] = {0}; 432ef149c25SAdrian Hunter 433cd3dd8ddSJiri Olsa if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) { 43499fa2984SAdrian Hunter off_t file_offset; 4358ceb41d7SJiri Olsa int fd = perf_data__fd(data); 43699fa2984SAdrian Hunter int err; 43799fa2984SAdrian Hunter 43899fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 43999fa2984SAdrian Hunter if (file_offset == -1) 44099fa2984SAdrian Hunter return -1; 44199fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 44299fa2984SAdrian Hunter event, file_offset); 44399fa2984SAdrian Hunter if (err) 44499fa2984SAdrian Hunter return err; 44599fa2984SAdrian Hunter } 44699fa2984SAdrian Hunter 447ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 448ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 449ef149c25SAdrian Hunter if (padding) 450ef149c25SAdrian Hunter padding = 8 - padding; 451ef149c25SAdrian Hunter 452ded2b8feSJiri Olsa record__write(rec, map, event, event->header.size); 453ded2b8feSJiri Olsa record__write(rec, map, data1, len1); 454ef149c25SAdrian Hunter if (len2) 455ded2b8feSJiri Olsa record__write(rec, map, data2, len2); 456ded2b8feSJiri Olsa record__write(rec, map, &pad, padding); 457ef149c25SAdrian Hunter 458ef149c25SAdrian Hunter return 0; 459ef149c25SAdrian Hunter } 460ef149c25SAdrian Hunter 461ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 462e035f4caSJiri Olsa struct perf_mmap *map) 463ef149c25SAdrian Hunter { 464ef149c25SAdrian Hunter int ret; 465ef149c25SAdrian Hunter 466e035f4caSJiri Olsa ret = auxtrace_mmap__read(map, rec->itr, &rec->tool, 467ef149c25SAdrian Hunter record__process_auxtrace); 468ef149c25SAdrian Hunter if (ret < 0) 469ef149c25SAdrian Hunter return ret; 470ef149c25SAdrian Hunter 471ef149c25SAdrian Hunter if (ret) 472ef149c25SAdrian Hunter rec->samples++; 473ef149c25SAdrian Hunter 474ef149c25SAdrian Hunter return 0; 475ef149c25SAdrian Hunter } 476ef149c25SAdrian Hunter 4772dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 478e035f4caSJiri Olsa struct perf_mmap *map) 4792dd6d8a1SAdrian Hunter { 4802dd6d8a1SAdrian Hunter int ret; 4812dd6d8a1SAdrian Hunter 482e035f4caSJiri Olsa ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool, 4832dd6d8a1SAdrian Hunter record__process_auxtrace, 4842dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 4852dd6d8a1SAdrian Hunter if (ret < 0) 4862dd6d8a1SAdrian Hunter return ret; 4872dd6d8a1SAdrian Hunter 4882dd6d8a1SAdrian Hunter if (ret) 4892dd6d8a1SAdrian Hunter rec->samples++; 4902dd6d8a1SAdrian Hunter 4912dd6d8a1SAdrian Hunter return 0; 4922dd6d8a1SAdrian Hunter } 4932dd6d8a1SAdrian Hunter 4942dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 4952dd6d8a1SAdrian Hunter { 4962dd6d8a1SAdrian Hunter int i; 4972dd6d8a1SAdrian Hunter int rc = 0; 4982dd6d8a1SAdrian Hunter 4992dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 500e035f4caSJiri Olsa struct perf_mmap *map = &rec->evlist->mmap[i]; 5012dd6d8a1SAdrian Hunter 502e035f4caSJiri Olsa if (!map->auxtrace_mmap.base) 5032dd6d8a1SAdrian Hunter continue; 5042dd6d8a1SAdrian Hunter 505e035f4caSJiri Olsa if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) { 5062dd6d8a1SAdrian Hunter rc = -1; 5072dd6d8a1SAdrian Hunter goto out; 5082dd6d8a1SAdrian Hunter } 5092dd6d8a1SAdrian Hunter } 5102dd6d8a1SAdrian Hunter out: 5112dd6d8a1SAdrian Hunter return rc; 5122dd6d8a1SAdrian Hunter } 5132dd6d8a1SAdrian Hunter 5142dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 5152dd6d8a1SAdrian Hunter { 5162dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 5172dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 5185f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 5192dd6d8a1SAdrian Hunter } else { 5205f9cf599SWang Nan if (auxtrace_record__snapshot_finish(rec->itr)) 5215f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 5225f9cf599SWang Nan else 5235f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 5242dd6d8a1SAdrian Hunter } 5252dd6d8a1SAdrian Hunter } 5262dd6d8a1SAdrian Hunter 5274b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec) 5284b5ea3bdSAdrian Hunter { 5294b5ea3bdSAdrian Hunter int err; 5304b5ea3bdSAdrian Hunter 5314b5ea3bdSAdrian Hunter if (!rec->itr) { 5324b5ea3bdSAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 5334b5ea3bdSAdrian Hunter if (err) 5344b5ea3bdSAdrian Hunter return err; 5354b5ea3bdSAdrian Hunter } 5364b5ea3bdSAdrian Hunter 5374b5ea3bdSAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 5384b5ea3bdSAdrian Hunter rec->opts.auxtrace_snapshot_opts); 5394b5ea3bdSAdrian Hunter if (err) 5404b5ea3bdSAdrian Hunter return err; 5414b5ea3bdSAdrian Hunter 5424b5ea3bdSAdrian Hunter return auxtrace_parse_filters(rec->evlist); 5434b5ea3bdSAdrian Hunter } 5444b5ea3bdSAdrian Hunter 545e31f0d01SAdrian Hunter #else 546e31f0d01SAdrian Hunter 547e31f0d01SAdrian Hunter static inline 548e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 549e035f4caSJiri Olsa struct perf_mmap *map __maybe_unused) 550e31f0d01SAdrian Hunter { 551e31f0d01SAdrian Hunter return 0; 552e31f0d01SAdrian Hunter } 553e31f0d01SAdrian Hunter 5542dd6d8a1SAdrian Hunter static inline 5552dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 5562dd6d8a1SAdrian Hunter { 5572dd6d8a1SAdrian Hunter } 5582dd6d8a1SAdrian Hunter 5592dd6d8a1SAdrian Hunter static inline 5602dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 5612dd6d8a1SAdrian Hunter { 5622dd6d8a1SAdrian Hunter return 0; 5632dd6d8a1SAdrian Hunter } 5642dd6d8a1SAdrian Hunter 5654b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused) 5664b5ea3bdSAdrian Hunter { 5674b5ea3bdSAdrian Hunter return 0; 5684b5ea3bdSAdrian Hunter } 5694b5ea3bdSAdrian Hunter 570e31f0d01SAdrian Hunter #endif 571e31f0d01SAdrian Hunter 572cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 573cda57a8cSWang Nan struct perf_evlist *evlist) 574cda57a8cSWang Nan { 575cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 576cda57a8cSWang Nan char msg[512]; 577cda57a8cSWang Nan 578f13de660SAlexey Budankov if (opts->affinity != PERF_AFFINITY_SYS) 579f13de660SAlexey Budankov cpu__setup_cpunode_map(); 580f13de660SAlexey Budankov 5817a276ff6SWang Nan if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, 582cda57a8cSWang Nan opts->auxtrace_mmap_pages, 5839d2ed645SAlexey Budankov opts->auxtrace_snapshot_mode, 584470530bbSAlexey Budankov opts->nr_cblocks, opts->affinity, 585470530bbSAlexey Budankov opts->mmap_flush) < 0) { 586cda57a8cSWang Nan if (errno == EPERM) { 587cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 588cda57a8cSWang Nan "Consider increasing " 589cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 590cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 591cda57a8cSWang Nan "(current value: %u,%u)\n", 592cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 593cda57a8cSWang Nan return -errno; 594cda57a8cSWang Nan } else { 595cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 596c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 597cda57a8cSWang Nan if (errno) 598cda57a8cSWang Nan return -errno; 599cda57a8cSWang Nan else 600cda57a8cSWang Nan return -EINVAL; 601cda57a8cSWang Nan } 602cda57a8cSWang Nan } 603cda57a8cSWang Nan return 0; 604cda57a8cSWang Nan } 605cda57a8cSWang Nan 606cda57a8cSWang Nan static int record__mmap(struct record *rec) 607cda57a8cSWang Nan { 608cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 609cda57a8cSWang Nan } 610cda57a8cSWang Nan 6118c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 612dd7927f4SArnaldo Carvalho de Melo { 613d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 6146a4bb04cSJiri Olsa struct perf_evsel *pos; 615d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 616d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 617b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 6188d3eca20SDavid Ahern int rc = 0; 619dd7927f4SArnaldo Carvalho de Melo 620d3dbf43cSArnaldo Carvalho de Melo /* 621d3dbf43cSArnaldo Carvalho de Melo * For initial_delay we need to add a dummy event so that we can track 622d3dbf43cSArnaldo Carvalho de Melo * PERF_RECORD_MMAP while we wait for the initial delay to enable the 623d3dbf43cSArnaldo Carvalho de Melo * real events, the ones asked by the user. 624d3dbf43cSArnaldo Carvalho de Melo */ 625d3dbf43cSArnaldo Carvalho de Melo if (opts->initial_delay) { 626d3dbf43cSArnaldo Carvalho de Melo if (perf_evlist__add_dummy(evlist)) 627d3dbf43cSArnaldo Carvalho de Melo return -ENOMEM; 628d3dbf43cSArnaldo Carvalho de Melo 629d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__first(evlist); 630d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 0; 631d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__last(evlist); 632d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 1; 633d3dbf43cSArnaldo Carvalho de Melo pos->attr.enable_on_exec = 1; 634d3dbf43cSArnaldo Carvalho de Melo } 635d3dbf43cSArnaldo Carvalho de Melo 636e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 637cac21425SJiri Olsa 638e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 6393da297a6SIngo Molnar try_again: 640d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 64156e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 642bb963e16SNamhyung Kim if (verbose > 0) 643c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 6443da297a6SIngo Molnar goto try_again; 6453da297a6SIngo Molnar } 646cf99ad14SAndi Kleen if ((errno == EINVAL || errno == EBADF) && 647cf99ad14SAndi Kleen pos->leader != pos && 648cf99ad14SAndi Kleen pos->weak_group) { 649cf99ad14SAndi Kleen pos = perf_evlist__reset_weak_group(evlist, pos); 650cf99ad14SAndi Kleen goto try_again; 651cf99ad14SAndi Kleen } 65256e52e85SArnaldo Carvalho de Melo rc = -errno; 65356e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 65456e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 65556e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 6568d3eca20SDavid Ahern goto out; 6577c6a1c65SPeter Zijlstra } 658bfd8f72cSAndi Kleen 659bfd8f72cSAndi Kleen pos->supported = true; 6607c6a1c65SPeter Zijlstra } 6617c6a1c65SPeter Zijlstra 66223d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 66362d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 66423d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 665c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 6668d3eca20SDavid Ahern rc = -1; 6678d3eca20SDavid Ahern goto out; 6680a102479SFrederic Weisbecker } 6690a102479SFrederic Weisbecker 670cda57a8cSWang Nan rc = record__mmap(rec); 671cda57a8cSWang Nan if (rc) 6728d3eca20SDavid Ahern goto out; 6730a27d7f9SArnaldo Carvalho de Melo 674a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 6757b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 6768d3eca20SDavid Ahern out: 6778d3eca20SDavid Ahern return rc; 678a91e5431SArnaldo Carvalho de Melo } 679a91e5431SArnaldo Carvalho de Melo 680e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 681e3d59112SNamhyung Kim union perf_event *event, 682e3d59112SNamhyung Kim struct perf_sample *sample, 683e3d59112SNamhyung Kim struct perf_evsel *evsel, 684e3d59112SNamhyung Kim struct machine *machine) 685e3d59112SNamhyung Kim { 686e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 687e3d59112SNamhyung Kim 68868588bafSJin Yao if (rec->evlist->first_sample_time == 0) 68968588bafSJin Yao rec->evlist->first_sample_time = sample->time; 690e3d59112SNamhyung Kim 69168588bafSJin Yao rec->evlist->last_sample_time = sample->time; 69268588bafSJin Yao 69368588bafSJin Yao if (rec->buildid_all) 69468588bafSJin Yao return 0; 69568588bafSJin Yao 69668588bafSJin Yao rec->samples++; 697e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 698e3d59112SNamhyung Kim } 699e3d59112SNamhyung Kim 7008c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 7016122e4e4SArnaldo Carvalho de Melo { 702f5fc1412SJiri Olsa struct perf_session *session = rec->session; 7036122e4e4SArnaldo Carvalho de Melo 70445112e89SJiri Olsa if (perf_data__size(&rec->data) == 0) 7059f591fd7SArnaldo Carvalho de Melo return 0; 7069f591fd7SArnaldo Carvalho de Melo 70700dc8657SNamhyung Kim /* 70800dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 70900dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 71000dc8657SNamhyung Kim * we prefer the vmlinux path like 71100dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 71200dc8657SNamhyung Kim * 71300dc8657SNamhyung Kim * rather than build-id path (in debug directory). 71400dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 71500dc8657SNamhyung Kim */ 71600dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 71700dc8657SNamhyung Kim 7186156681bSNamhyung Kim /* 7196156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 72068588bafSJin Yao * so no need to process samples. But if timestamp_boundary is enabled, 72168588bafSJin Yao * it still needs to walk on all samples to get the timestamps of 72268588bafSJin Yao * first/last samples. 7236156681bSNamhyung Kim */ 72468588bafSJin Yao if (rec->buildid_all && !rec->timestamp_boundary) 7256156681bSNamhyung Kim rec->tool.sample = NULL; 7266156681bSNamhyung Kim 727b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 7286122e4e4SArnaldo Carvalho de Melo } 7296122e4e4SArnaldo Carvalho de Melo 7308115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 731a1645ce1SZhang, Yanmin { 732a1645ce1SZhang, Yanmin int err; 73345694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 734a1645ce1SZhang, Yanmin /* 735a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 736a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 737a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 738a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 739a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 740a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 741a1645ce1SZhang, Yanmin */ 74245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 743743eb868SArnaldo Carvalho de Melo machine); 744a1645ce1SZhang, Yanmin if (err < 0) 745a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 74623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 747a1645ce1SZhang, Yanmin 748a1645ce1SZhang, Yanmin /* 749a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 750a1645ce1SZhang, Yanmin * have no _text sometimes. 751a1645ce1SZhang, Yanmin */ 75245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 7530ae617beSAdrian Hunter machine); 754a1645ce1SZhang, Yanmin if (err < 0) 755a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 75623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 757a1645ce1SZhang, Yanmin } 758a1645ce1SZhang, Yanmin 75998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 76098402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 76198402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 76298402807SFrederic Weisbecker }; 76398402807SFrederic Weisbecker 764f13de660SAlexey Budankov static void record__adjust_affinity(struct record *rec, struct perf_mmap *map) 765f13de660SAlexey Budankov { 766f13de660SAlexey Budankov if (rec->opts.affinity != PERF_AFFINITY_SYS && 767f13de660SAlexey Budankov !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) { 768f13de660SAlexey Budankov CPU_ZERO(&rec->affinity_mask); 769f13de660SAlexey Budankov CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask); 770f13de660SAlexey Budankov sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask); 771f13de660SAlexey Budankov } 772f13de660SAlexey Budankov } 773f13de660SAlexey Budankov 774a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, 775470530bbSAlexey Budankov bool overwrite, bool synch) 77698402807SFrederic Weisbecker { 777dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 7780e2e63ddSPeter Zijlstra int i; 7798d3eca20SDavid Ahern int rc = 0; 780a4ea0ec4SWang Nan struct perf_mmap *maps; 781d3d1af6fSAlexey Budankov int trace_fd = rec->data.file.fd; 782d3d1af6fSAlexey Budankov off_t off; 78398402807SFrederic Weisbecker 784cb21686bSWang Nan if (!evlist) 785cb21686bSWang Nan return 0; 786ef149c25SAdrian Hunter 7870b72d69aSWang Nan maps = overwrite ? evlist->overwrite_mmap : evlist->mmap; 788a4ea0ec4SWang Nan if (!maps) 789a4ea0ec4SWang Nan return 0; 790cb21686bSWang Nan 7910b72d69aSWang Nan if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 79254cc54deSWang Nan return 0; 79354cc54deSWang Nan 794d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 795d3d1af6fSAlexey Budankov off = record__aio_get_pos(trace_fd); 796d3d1af6fSAlexey Budankov 797a4ea0ec4SWang Nan for (i = 0; i < evlist->nr_mmaps; i++) { 798470530bbSAlexey Budankov u64 flush = 0; 799e035f4caSJiri Olsa struct perf_mmap *map = &maps[i]; 800a4ea0ec4SWang Nan 801e035f4caSJiri Olsa if (map->base) { 802f13de660SAlexey Budankov record__adjust_affinity(rec, map); 803470530bbSAlexey Budankov if (synch) { 804470530bbSAlexey Budankov flush = map->flush; 805470530bbSAlexey Budankov map->flush = 1; 806470530bbSAlexey Budankov } 807d3d1af6fSAlexey Budankov if (!record__aio_enabled(rec)) { 808e035f4caSJiri Olsa if (perf_mmap__push(map, rec, record__pushfn) != 0) { 809470530bbSAlexey Budankov if (synch) 810470530bbSAlexey Budankov map->flush = flush; 8118d3eca20SDavid Ahern rc = -1; 8128d3eca20SDavid Ahern goto out; 8138d3eca20SDavid Ahern } 814d3d1af6fSAlexey Budankov } else { 81593f20c0fSAlexey Budankov int idx; 816d3d1af6fSAlexey Budankov /* 817d3d1af6fSAlexey Budankov * Call record__aio_sync() to wait till map->data buffer 818d3d1af6fSAlexey Budankov * becomes available after previous aio write request. 819d3d1af6fSAlexey Budankov */ 82093f20c0fSAlexey Budankov idx = record__aio_sync(map, false); 82193f20c0fSAlexey Budankov if (perf_mmap__aio_push(map, rec, idx, record__aio_pushfn, &off) != 0) { 822d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 823470530bbSAlexey Budankov if (synch) 824470530bbSAlexey Budankov map->flush = flush; 825d3d1af6fSAlexey Budankov rc = -1; 826d3d1af6fSAlexey Budankov goto out; 827d3d1af6fSAlexey Budankov } 828d3d1af6fSAlexey Budankov } 829470530bbSAlexey Budankov if (synch) 830470530bbSAlexey Budankov map->flush = flush; 8318d3eca20SDavid Ahern } 832ef149c25SAdrian Hunter 833e035f4caSJiri Olsa if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode && 834e035f4caSJiri Olsa record__auxtrace_mmap_read(rec, map) != 0) { 835ef149c25SAdrian Hunter rc = -1; 836ef149c25SAdrian Hunter goto out; 837ef149c25SAdrian Hunter } 83898402807SFrederic Weisbecker } 83998402807SFrederic Weisbecker 840d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 841d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 842d3d1af6fSAlexey Budankov 843dcabb507SJiri Olsa /* 844dcabb507SJiri Olsa * Mark the round finished in case we wrote 845dcabb507SJiri Olsa * at least one event. 846dcabb507SJiri Olsa */ 847dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 848ded2b8feSJiri Olsa rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event)); 8498d3eca20SDavid Ahern 8500b72d69aSWang Nan if (overwrite) 85154cc54deSWang Nan perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 8528d3eca20SDavid Ahern out: 8538d3eca20SDavid Ahern return rc; 85498402807SFrederic Weisbecker } 85598402807SFrederic Weisbecker 856470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch) 857cb21686bSWang Nan { 858cb21686bSWang Nan int err; 859cb21686bSWang Nan 860470530bbSAlexey Budankov err = record__mmap_read_evlist(rec, rec->evlist, false, synch); 861cb21686bSWang Nan if (err) 862cb21686bSWang Nan return err; 863cb21686bSWang Nan 864470530bbSAlexey Budankov return record__mmap_read_evlist(rec, rec->evlist, true, synch); 865cb21686bSWang Nan } 866cb21686bSWang Nan 8678c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 86857706abcSDavid Ahern { 86957706abcSDavid Ahern struct perf_session *session = rec->session; 87057706abcSDavid Ahern int feat; 87157706abcSDavid Ahern 87257706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 87357706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 87457706abcSDavid Ahern 87557706abcSDavid Ahern if (rec->no_buildid) 87657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 87757706abcSDavid Ahern 8783e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 87957706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 88057706abcSDavid Ahern 88157706abcSDavid Ahern if (!rec->opts.branch_stack) 88257706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 883ef149c25SAdrian Hunter 884ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 885ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 886ffa517adSJiri Olsa 887cf790516SAlexey Budankov if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 888cf790516SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_CLOCKID); 889cf790516SAlexey Budankov 890258031c0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); 891258031c0SJiri Olsa 892ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 89357706abcSDavid Ahern } 89457706abcSDavid Ahern 895e1ab48baSWang Nan static void 896e1ab48baSWang Nan record__finish_output(struct record *rec) 897e1ab48baSWang Nan { 8988ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 8998ceb41d7SJiri Olsa int fd = perf_data__fd(data); 900e1ab48baSWang Nan 9018ceb41d7SJiri Olsa if (data->is_pipe) 902e1ab48baSWang Nan return; 903e1ab48baSWang Nan 904e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 90545112e89SJiri Olsa data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR); 906e1ab48baSWang Nan 907e1ab48baSWang Nan if (!rec->no_buildid) { 908e1ab48baSWang Nan process_buildids(rec); 909e1ab48baSWang Nan 910e1ab48baSWang Nan if (rec->buildid_all) 911e1ab48baSWang Nan dsos__hit_all(rec->session); 912e1ab48baSWang Nan } 913e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 914e1ab48baSWang Nan 915e1ab48baSWang Nan return; 916e1ab48baSWang Nan } 917e1ab48baSWang Nan 9184ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 919be7b0c9eSWang Nan { 9209d6aae72SArnaldo Carvalho de Melo int err; 9219d6aae72SArnaldo Carvalho de Melo struct thread_map *thread_map; 922be7b0c9eSWang Nan 9234ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 9244ea648aeSWang Nan return 0; 9254ea648aeSWang Nan 9269d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 9279d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL) 9289d6aae72SArnaldo Carvalho de Melo return -1; 9299d6aae72SArnaldo Carvalho de Melo 9309d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 931be7b0c9eSWang Nan process_synthesized_event, 932be7b0c9eSWang Nan &rec->session->machines.host, 9333fcb10e4SMark Drayton rec->opts.sample_address); 9349d6aae72SArnaldo Carvalho de Melo thread_map__put(thread_map); 9359d6aae72SArnaldo Carvalho de Melo return err; 936be7b0c9eSWang Nan } 937be7b0c9eSWang Nan 9384ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 9393c1cb7e3SWang Nan 940ecfd7a9cSWang Nan static int 941ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 942ecfd7a9cSWang Nan { 9438ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 944ecfd7a9cSWang Nan int fd, err; 94503724b2eSAndi Kleen char *new_filename; 946ecfd7a9cSWang Nan 947ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 948ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 949ecfd7a9cSWang Nan 950d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 951d3d1af6fSAlexey Budankov 9524ea648aeSWang Nan record__synthesize(rec, true); 9534ea648aeSWang Nan if (target__none(&rec->opts.target)) 9544ea648aeSWang Nan record__synthesize_workload(rec, true); 9554ea648aeSWang Nan 956ecfd7a9cSWang Nan rec->samples = 0; 957ecfd7a9cSWang Nan record__finish_output(rec); 958ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 959ecfd7a9cSWang Nan if (err) { 960ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 961ecfd7a9cSWang Nan return -EINVAL; 962ecfd7a9cSWang Nan } 963ecfd7a9cSWang Nan 9648ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp, 965ecfd7a9cSWang Nan rec->session->header.data_offset, 96603724b2eSAndi Kleen at_exit, &new_filename); 967ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 968ecfd7a9cSWang Nan rec->bytes_written = 0; 969ecfd7a9cSWang Nan rec->session->header.data_size = 0; 970ecfd7a9cSWang Nan } 971ecfd7a9cSWang Nan 972ecfd7a9cSWang Nan if (!quiet) 973ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 9742d4f2799SJiri Olsa data->path, timestamp); 9753c1cb7e3SWang Nan 97603724b2eSAndi Kleen if (rec->switch_output.num_files) { 97703724b2eSAndi Kleen int n = rec->switch_output.cur_file + 1; 97803724b2eSAndi Kleen 97903724b2eSAndi Kleen if (n >= rec->switch_output.num_files) 98003724b2eSAndi Kleen n = 0; 98103724b2eSAndi Kleen rec->switch_output.cur_file = n; 98203724b2eSAndi Kleen if (rec->switch_output.filenames[n]) { 98303724b2eSAndi Kleen remove(rec->switch_output.filenames[n]); 98403724b2eSAndi Kleen free(rec->switch_output.filenames[n]); 98503724b2eSAndi Kleen } 98603724b2eSAndi Kleen rec->switch_output.filenames[n] = new_filename; 98703724b2eSAndi Kleen } else { 98803724b2eSAndi Kleen free(new_filename); 98903724b2eSAndi Kleen } 99003724b2eSAndi Kleen 9913c1cb7e3SWang Nan /* Output tracking events */ 992be7b0c9eSWang Nan if (!at_exit) { 9934ea648aeSWang Nan record__synthesize(rec, false); 9943c1cb7e3SWang Nan 995be7b0c9eSWang Nan /* 996be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 997be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 998be7b0c9eSWang Nan * generate tracking events because there's no thread_map 999be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 1000be7b0c9eSWang Nan * contain map and comm information. 1001be7b0c9eSWang Nan * Create a fake thread_map and directly call 1002be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 1003be7b0c9eSWang Nan */ 1004be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 10054ea648aeSWang Nan record__synthesize_workload(rec, false); 1006be7b0c9eSWang Nan } 1007ecfd7a9cSWang Nan return fd; 1008ecfd7a9cSWang Nan } 1009ecfd7a9cSWang Nan 1010f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 1011f33cbe72SArnaldo Carvalho de Melo 1012f33cbe72SArnaldo Carvalho de Melo /* 1013f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 1014f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 1015f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 1016f33cbe72SArnaldo Carvalho de Melo */ 101745604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 101845604710SNamhyung Kim siginfo_t *info, 1019f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 1020f33cbe72SArnaldo Carvalho de Melo { 1021f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 1022f33cbe72SArnaldo Carvalho de Melo done = 1; 1023f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 1024f33cbe72SArnaldo Carvalho de Melo } 1025f33cbe72SArnaldo Carvalho de Melo 10262dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 1027bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig); 10282dd6d8a1SAdrian Hunter 102946bc29b9SAdrian Hunter int __weak 103046bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 103146bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 103246bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 103346bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 103446bc29b9SAdrian Hunter { 103546bc29b9SAdrian Hunter return 0; 103646bc29b9SAdrian Hunter } 103746bc29b9SAdrian Hunter 1038ee667f94SWang Nan static const struct perf_event_mmap_page * 1039ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist) 1040ee667f94SWang Nan { 1041b2cb615dSWang Nan if (evlist) { 1042b2cb615dSWang Nan if (evlist->mmap && evlist->mmap[0].base) 1043ee667f94SWang Nan return evlist->mmap[0].base; 10440b72d69aSWang Nan if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base) 10450b72d69aSWang Nan return evlist->overwrite_mmap[0].base; 1046b2cb615dSWang Nan } 1047ee667f94SWang Nan return NULL; 1048ee667f94SWang Nan } 1049ee667f94SWang Nan 1050c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 1051c45628b0SWang Nan { 1052ee667f94SWang Nan const struct perf_event_mmap_page *pc; 1053ee667f94SWang Nan 1054ee667f94SWang Nan pc = perf_evlist__pick_pc(rec->evlist); 1055ee667f94SWang Nan if (pc) 1056ee667f94SWang Nan return pc; 1057c45628b0SWang Nan return NULL; 1058c45628b0SWang Nan } 1059c45628b0SWang Nan 10604ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 1061c45c86ebSWang Nan { 1062c45c86ebSWang Nan struct perf_session *session = rec->session; 1063c45c86ebSWang Nan struct machine *machine = &session->machines.host; 10648ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1065c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 1066c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 10678ceb41d7SJiri Olsa int fd = perf_data__fd(data); 1068c45c86ebSWang Nan int err = 0; 1069c45c86ebSWang Nan 10704ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 10714ea648aeSWang Nan return 0; 10724ea648aeSWang Nan 10738ceb41d7SJiri Olsa if (data->is_pipe) { 1074a2015516SJiri Olsa /* 1075a2015516SJiri Olsa * We need to synthesize events first, because some 1076a2015516SJiri Olsa * features works on top of them (on report side). 1077a2015516SJiri Olsa */ 1078318ec184SJiri Olsa err = perf_event__synthesize_attrs(tool, rec->evlist, 1079c45c86ebSWang Nan process_synthesized_event); 1080c45c86ebSWang Nan if (err < 0) { 1081c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 1082c45c86ebSWang Nan goto out; 1083c45c86ebSWang Nan } 1084c45c86ebSWang Nan 1085a2015516SJiri Olsa err = perf_event__synthesize_features(tool, session, rec->evlist, 1086a2015516SJiri Olsa process_synthesized_event); 1087a2015516SJiri Olsa if (err < 0) { 1088a2015516SJiri Olsa pr_err("Couldn't synthesize features.\n"); 1089a2015516SJiri Olsa return err; 1090a2015516SJiri Olsa } 1091a2015516SJiri Olsa 1092c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 1093c45c86ebSWang Nan /* 1094c45c86ebSWang Nan * FIXME err <= 0 here actually means that 1095c45c86ebSWang Nan * there were no tracepoints so its not really 1096c45c86ebSWang Nan * an error, just that we don't need to 1097c45c86ebSWang Nan * synthesize anything. We really have to 1098c45c86ebSWang Nan * return this more properly and also 1099c45c86ebSWang Nan * propagate errors that now are calling die() 1100c45c86ebSWang Nan */ 1101c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 1102c45c86ebSWang Nan process_synthesized_event); 1103c45c86ebSWang Nan if (err <= 0) { 1104c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 1105c45c86ebSWang Nan goto out; 1106c45c86ebSWang Nan } 1107c45c86ebSWang Nan rec->bytes_written += err; 1108c45c86ebSWang Nan } 1109c45c86ebSWang Nan } 1110c45c86ebSWang Nan 1111c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 111246bc29b9SAdrian Hunter process_synthesized_event, machine); 111346bc29b9SAdrian Hunter if (err) 111446bc29b9SAdrian Hunter goto out; 111546bc29b9SAdrian Hunter 1116c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 1117c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 1118c45c86ebSWang Nan session, process_synthesized_event); 1119c45c86ebSWang Nan if (err) 1120c45c86ebSWang Nan goto out; 1121c45c86ebSWang Nan } 1122c45c86ebSWang Nan 11236c443954SArnaldo Carvalho de Melo if (!perf_evlist__exclude_kernel(rec->evlist)) { 1124c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 1125c45c86ebSWang Nan machine); 1126c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 1127c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1128c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 1129c45c86ebSWang Nan 1130c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 1131c45c86ebSWang Nan machine); 1132c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 1133c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1134c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 11356c443954SArnaldo Carvalho de Melo } 1136c45c86ebSWang Nan 1137c45c86ebSWang Nan if (perf_guest) { 1138c45c86ebSWang Nan machines__process_guests(&session->machines, 1139c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 1140c45c86ebSWang Nan } 1141c45c86ebSWang Nan 1142bfd8f72cSAndi Kleen err = perf_event__synthesize_extra_attr(&rec->tool, 1143bfd8f72cSAndi Kleen rec->evlist, 1144bfd8f72cSAndi Kleen process_synthesized_event, 1145bfd8f72cSAndi Kleen data->is_pipe); 1146bfd8f72cSAndi Kleen if (err) 1147bfd8f72cSAndi Kleen goto out; 1148bfd8f72cSAndi Kleen 1149373565d2SAndi Kleen err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->threads, 1150373565d2SAndi Kleen process_synthesized_event, 1151373565d2SAndi Kleen NULL); 1152373565d2SAndi Kleen if (err < 0) { 1153373565d2SAndi Kleen pr_err("Couldn't synthesize thread map.\n"); 1154373565d2SAndi Kleen return err; 1155373565d2SAndi Kleen } 1156373565d2SAndi Kleen 1157373565d2SAndi Kleen err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->cpus, 1158373565d2SAndi Kleen process_synthesized_event, NULL); 1159373565d2SAndi Kleen if (err < 0) { 1160373565d2SAndi Kleen pr_err("Couldn't synthesize cpu map.\n"); 1161373565d2SAndi Kleen return err; 1162373565d2SAndi Kleen } 1163373565d2SAndi Kleen 1164e5416950SSong Liu err = perf_event__synthesize_bpf_events(session, process_synthesized_event, 11657b612e29SSong Liu machine, opts); 11667b612e29SSong Liu if (err < 0) 11677b612e29SSong Liu pr_warning("Couldn't synthesize bpf events.\n"); 11687b612e29SSong Liu 1169c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 1170c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 11713fcb10e4SMark Drayton 1); 1172c45c86ebSWang Nan out: 1173c45c86ebSWang Nan return err; 1174c45c86ebSWang Nan } 1175c45c86ebSWang Nan 11768c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 117786470930SIngo Molnar { 117857706abcSDavid Ahern int err; 117945604710SNamhyung Kim int status = 0; 11808b412664SPeter Zijlstra unsigned long waking = 0; 118146be604bSZhang, Yanmin const bool forks = argc > 0; 118245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 1183b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 11848ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1185d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 11866dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 1187657ee553SSong Liu struct perf_evlist *sb_evlist = NULL; 118842aa276fSNamhyung Kim int fd; 118986470930SIngo Molnar 119045604710SNamhyung Kim atexit(record__sig_exit); 1191f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 1192f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 1193804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 1194a074865eSWang Nan signal(SIGSEGV, sigsegv_handler); 1195c0bdc1c4SWang Nan 1196f3b3614aSHari Bathini if (rec->opts.record_namespaces) 1197f3b3614aSHari Bathini tool->namespace_events = true; 1198f3b3614aSHari Bathini 1199dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 12002dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 12013c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 12025f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 1203dc0c6127SJiri Olsa if (rec->switch_output.enabled) 12043c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 1205c0bdc1c4SWang Nan } else { 12062dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 1207c0bdc1c4SWang Nan } 1208f5970550SPeter Zijlstra 12098ceb41d7SJiri Olsa session = perf_session__new(data, false, tool); 121094c744b6SArnaldo Carvalho de Melo if (session == NULL) { 1211ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 1212a9a70bbcSArnaldo Carvalho de Melo return -1; 1213a9a70bbcSArnaldo Carvalho de Melo } 1214a9a70bbcSArnaldo Carvalho de Melo 12158ceb41d7SJiri Olsa fd = perf_data__fd(data); 1216d20deb64SArnaldo Carvalho de Melo rec->session = session; 1217d20deb64SArnaldo Carvalho de Melo 12188c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 1219330aa675SStephane Eranian 1220cf790516SAlexey Budankov if (rec->opts.use_clockid && rec->opts.clockid_res_ns) 1221cf790516SAlexey Budankov session->header.env.clockid_res_ns = rec->opts.clockid_res_ns; 1222cf790516SAlexey Budankov 1223d4db3f16SArnaldo Carvalho de Melo if (forks) { 12243e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 12258ceb41d7SJiri Olsa argv, data->is_pipe, 1226735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 122735b9d88eSArnaldo Carvalho de Melo if (err < 0) { 122835b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 122945604710SNamhyung Kim status = err; 123035b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 1231856e9660SPeter Zijlstra } 1232856e9660SPeter Zijlstra } 1233856e9660SPeter Zijlstra 1234ad46e48cSJiri Olsa /* 1235ad46e48cSJiri Olsa * If we have just single event and are sending data 1236ad46e48cSJiri Olsa * through pipe, we need to force the ids allocation, 1237ad46e48cSJiri Olsa * because we synthesize event name through the pipe 1238ad46e48cSJiri Olsa * and need the id for that. 1239ad46e48cSJiri Olsa */ 1240ad46e48cSJiri Olsa if (data->is_pipe && rec->evlist->nr_entries == 1) 1241ad46e48cSJiri Olsa rec->opts.sample_id = true; 1242ad46e48cSJiri Olsa 12438c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 12448d3eca20SDavid Ahern err = -1; 124545604710SNamhyung Kim goto out_child; 12468d3eca20SDavid Ahern } 124786470930SIngo Molnar 12488690a2a7SWang Nan err = bpf__apply_obj_config(); 12498690a2a7SWang Nan if (err) { 12508690a2a7SWang Nan char errbuf[BUFSIZ]; 12518690a2a7SWang Nan 12528690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 12538690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 12548690a2a7SWang Nan errbuf); 12558690a2a7SWang Nan goto out_child; 12568690a2a7SWang Nan } 12578690a2a7SWang Nan 1258cca8482cSAdrian Hunter /* 1259cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 1260cca8482cSAdrian Hunter * evlist. 1261cca8482cSAdrian Hunter */ 1262cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 1263cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 1264cca8482cSAdrian Hunter rec->tool.ordered_events = false; 1265cca8482cSAdrian Hunter } 1266cca8482cSAdrian Hunter 12673e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 1268a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 1269a8bb559bSNamhyung Kim 12708ceb41d7SJiri Olsa if (data->is_pipe) { 127142aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 1272529870e3STom Zanussi if (err < 0) 127345604710SNamhyung Kim goto out_child; 1274563aecb2SJiri Olsa } else { 127542aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 1276d5eed904SArnaldo Carvalho de Melo if (err < 0) 127745604710SNamhyung Kim goto out_child; 1278d5eed904SArnaldo Carvalho de Melo } 12797c6a1c65SPeter Zijlstra 1280d3665498SDavid Ahern if (!rec->no_buildid 1281e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 1282d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 1283e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 12848d3eca20SDavid Ahern err = -1; 128545604710SNamhyung Kim goto out_child; 1286e20960c0SRobert Richter } 1287e20960c0SRobert Richter 1288d56354dcSSong Liu if (!opts->no_bpf_event) 1289d56354dcSSong Liu bpf_event__add_sb_event(&sb_evlist, &session->header.env); 1290d56354dcSSong Liu 1291657ee553SSong Liu if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) { 1292657ee553SSong Liu pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); 1293657ee553SSong Liu opts->no_bpf_event = true; 1294657ee553SSong Liu } 1295657ee553SSong Liu 12964ea648aeSWang Nan err = record__synthesize(rec, false); 1297c45c86ebSWang Nan if (err < 0) 129845604710SNamhyung Kim goto out_child; 12998d3eca20SDavid Ahern 1300d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 130186470930SIngo Molnar struct sched_param param; 130286470930SIngo Molnar 1303d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 130486470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 13056beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 13068d3eca20SDavid Ahern err = -1; 130745604710SNamhyung Kim goto out_child; 130886470930SIngo Molnar } 130986470930SIngo Molnar } 131086470930SIngo Molnar 1311774cb499SJiri Olsa /* 1312774cb499SJiri Olsa * When perf is starting the traced process, all the events 1313774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 1314774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 1315774cb499SJiri Olsa */ 13166619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 13173e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 1318764e16a3SDavid Ahern 1319856e9660SPeter Zijlstra /* 1320856e9660SPeter Zijlstra * Let the child rip 1321856e9660SPeter Zijlstra */ 1322e803cf97SNamhyung Kim if (forks) { 132320a8a3cfSJiri Olsa struct machine *machine = &session->machines.host; 1324e5bed564SNamhyung Kim union perf_event *event; 1325e907caf3SHari Bathini pid_t tgid; 1326e5bed564SNamhyung Kim 1327e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 1328e5bed564SNamhyung Kim if (event == NULL) { 1329e5bed564SNamhyung Kim err = -ENOMEM; 1330e5bed564SNamhyung Kim goto out_child; 1331e5bed564SNamhyung Kim } 1332e5bed564SNamhyung Kim 1333e803cf97SNamhyung Kim /* 1334e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 1335e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 1336e803cf97SNamhyung Kim * cannot see a correct process name for those events. 1337e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 1338e803cf97SNamhyung Kim */ 1339e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event, 1340e803cf97SNamhyung Kim rec->evlist->workload.pid, 1341e803cf97SNamhyung Kim process_synthesized_event, 1342e803cf97SNamhyung Kim machine); 1343e5bed564SNamhyung Kim free(event); 1344e803cf97SNamhyung Kim 1345e907caf3SHari Bathini if (tgid == -1) 1346e907caf3SHari Bathini goto out_child; 1347e907caf3SHari Bathini 1348e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) + 1349e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 1350e907caf3SHari Bathini machine->id_hdr_size); 1351e907caf3SHari Bathini if (event == NULL) { 1352e907caf3SHari Bathini err = -ENOMEM; 1353e907caf3SHari Bathini goto out_child; 1354e907caf3SHari Bathini } 1355e907caf3SHari Bathini 1356e907caf3SHari Bathini /* 1357e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified. 1358e907caf3SHari Bathini */ 1359e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event, 1360e907caf3SHari Bathini rec->evlist->workload.pid, 1361e907caf3SHari Bathini tgid, process_synthesized_event, 1362e907caf3SHari Bathini machine); 1363e907caf3SHari Bathini free(event); 1364e907caf3SHari Bathini 13653e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 1366e803cf97SNamhyung Kim } 1367856e9660SPeter Zijlstra 13686619a53eSAndi Kleen if (opts->initial_delay) { 13690693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 13706619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 13716619a53eSAndi Kleen } 13726619a53eSAndi Kleen 13735f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 13743c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 1375a074865eSWang Nan perf_hooks__invoke_record_start(); 1376649c48a9SPeter Zijlstra for (;;) { 13779f065194SYang Shi unsigned long long hits = rec->samples; 137886470930SIngo Molnar 137905737464SWang Nan /* 138005737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 138105737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 138205737464SWang Nan * hits != rec->samples in previous round. 138305737464SWang Nan * 138405737464SWang Nan * perf_evlist__toggle_bkw_mmap ensure we never 138505737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 138605737464SWang Nan */ 138705737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 138805737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 138905737464SWang Nan 1390470530bbSAlexey Budankov if (record__mmap_read_all(rec, false) < 0) { 13915f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 13923c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 13938d3eca20SDavid Ahern err = -1; 139445604710SNamhyung Kim goto out_child; 13958d3eca20SDavid Ahern } 139686470930SIngo Molnar 13972dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 13982dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 13995f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 14002dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 14015f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 14022dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 14032dd6d8a1SAdrian Hunter err = -1; 14042dd6d8a1SAdrian Hunter goto out_child; 14052dd6d8a1SAdrian Hunter } 14062dd6d8a1SAdrian Hunter } 14072dd6d8a1SAdrian Hunter 14083c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 140905737464SWang Nan /* 141005737464SWang Nan * If switch_output_trigger is hit, the data in 141105737464SWang Nan * overwritable ring buffer should have been collected, 141205737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 141305737464SWang Nan * 141405737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 141505737464SWang Nan * record__mmap_read_all() didn't collect data from 141605737464SWang Nan * overwritable ring buffer. Read again. 141705737464SWang Nan */ 141805737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 141905737464SWang Nan continue; 14203c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 14213c1cb7e3SWang Nan 142205737464SWang Nan /* 142305737464SWang Nan * Reenable events in overwrite ring buffer after 142405737464SWang Nan * record__mmap_read_all(): we should have collected 142505737464SWang Nan * data from it. 142605737464SWang Nan */ 142705737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 142805737464SWang Nan 14293c1cb7e3SWang Nan if (!quiet) 14303c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 14313c1cb7e3SWang Nan waking); 14323c1cb7e3SWang Nan waking = 0; 14333c1cb7e3SWang Nan fd = record__switch_output(rec, false); 14343c1cb7e3SWang Nan if (fd < 0) { 14353c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 14363c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 14373c1cb7e3SWang Nan err = fd; 14383c1cb7e3SWang Nan goto out_child; 14393c1cb7e3SWang Nan } 1440bfacbe3bSJiri Olsa 1441bfacbe3bSJiri Olsa /* re-arm the alarm */ 1442bfacbe3bSJiri Olsa if (rec->switch_output.time) 1443bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 14443c1cb7e3SWang Nan } 14453c1cb7e3SWang Nan 1446d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 14476dcf45efSArnaldo Carvalho de Melo if (done || draining) 1448649c48a9SPeter Zijlstra break; 1449f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 1450a515114fSJiri Olsa /* 1451a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1452a515114fSJiri Olsa * number of returned events and interrupt error. 1453a515114fSJiri Olsa */ 1454a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 145545604710SNamhyung Kim err = 0; 14568b412664SPeter Zijlstra waking++; 14576dcf45efSArnaldo Carvalho de Melo 14586dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 14596dcf45efSArnaldo Carvalho de Melo draining = true; 14608b412664SPeter Zijlstra } 14618b412664SPeter Zijlstra 1462774cb499SJiri Olsa /* 1463774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1464774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1465774cb499SJiri Olsa * disable events in this case. 1466774cb499SJiri Olsa */ 1467602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 14685f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 14693e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 14702711926aSJiri Olsa disabled = true; 14712711926aSJiri Olsa } 14728b412664SPeter Zijlstra } 14735f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 14743c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 14758b412664SPeter Zijlstra 1476f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 147735550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 1478c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 1479f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 1480f33cbe72SArnaldo Carvalho de Melo err = -1; 148145604710SNamhyung Kim goto out_child; 1482f33cbe72SArnaldo Carvalho de Melo } 1483f33cbe72SArnaldo Carvalho de Melo 1484e3d59112SNamhyung Kim if (!quiet) 14858b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 148686470930SIngo Molnar 14874ea648aeSWang Nan if (target__none(&rec->opts.target)) 14884ea648aeSWang Nan record__synthesize_workload(rec, true); 14894ea648aeSWang Nan 149045604710SNamhyung Kim out_child: 1491470530bbSAlexey Budankov record__mmap_read_all(rec, true); 1492d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 1493d3d1af6fSAlexey Budankov 149445604710SNamhyung Kim if (forks) { 149545604710SNamhyung Kim int exit_status; 149645604710SNamhyung Kim 149745604710SNamhyung Kim if (!child_finished) 149845604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 149945604710SNamhyung Kim 150045604710SNamhyung Kim wait(&exit_status); 150145604710SNamhyung Kim 150245604710SNamhyung Kim if (err < 0) 150345604710SNamhyung Kim status = err; 150445604710SNamhyung Kim else if (WIFEXITED(exit_status)) 150545604710SNamhyung Kim status = WEXITSTATUS(exit_status); 150645604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 150745604710SNamhyung Kim signr = WTERMSIG(exit_status); 150845604710SNamhyung Kim } else 150945604710SNamhyung Kim status = err; 151045604710SNamhyung Kim 15114ea648aeSWang Nan record__synthesize(rec, true); 1512e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 1513e3d59112SNamhyung Kim rec->samples = 0; 1514e3d59112SNamhyung Kim 1515ecfd7a9cSWang Nan if (!err) { 1516ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 1517e1ab48baSWang Nan record__finish_output(rec); 1518ecfd7a9cSWang Nan } else { 1519ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1520ecfd7a9cSWang Nan if (fd < 0) { 1521ecfd7a9cSWang Nan status = fd; 1522ecfd7a9cSWang Nan goto out_delete_session; 1523ecfd7a9cSWang Nan } 1524ecfd7a9cSWang Nan } 1525ecfd7a9cSWang Nan } 152639d17dacSArnaldo Carvalho de Melo 1527a074865eSWang Nan perf_hooks__invoke_record_end(); 1528a074865eSWang Nan 1529e3d59112SNamhyung Kim if (!err && !quiet) { 1530e3d59112SNamhyung Kim char samples[128]; 1531ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1532ecfd7a9cSWang Nan ".<timestamp>" : ""; 1533e3d59112SNamhyung Kim 1534ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1535e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1536e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1537e3d59112SNamhyung Kim else 1538e3d59112SNamhyung Kim samples[0] = '\0'; 1539e3d59112SNamhyung Kim 1540ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 15418ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0, 15422d4f2799SJiri Olsa data->path, postfix, samples); 1543e3d59112SNamhyung Kim } 1544e3d59112SNamhyung Kim 154539d17dacSArnaldo Carvalho de Melo out_delete_session: 154639d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 1547657ee553SSong Liu 1548657ee553SSong Liu if (!opts->no_bpf_event) 1549657ee553SSong Liu perf_evlist__stop_sb_thread(sb_evlist); 155045604710SNamhyung Kim return status; 155186470930SIngo Molnar } 155286470930SIngo Molnar 15530883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 155409b0fd45SJiri Olsa { 1555aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1556a601fdffSJiri Olsa 15570883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 155826d33022SJiri Olsa 15590883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 156009b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 15610883e820SArnaldo Carvalho de Melo callchain->dump_size); 15620883e820SArnaldo Carvalho de Melo } 15630883e820SArnaldo Carvalho de Melo 15640883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 15650883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 15660883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 15670883e820SArnaldo Carvalho de Melo { 15680883e820SArnaldo Carvalho de Melo int ret; 15690883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 15700883e820SArnaldo Carvalho de Melo 15710883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 15720883e820SArnaldo Carvalho de Melo if (unset) { 15730883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 15740883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 15750883e820SArnaldo Carvalho de Melo return 0; 15760883e820SArnaldo Carvalho de Melo } 15770883e820SArnaldo Carvalho de Melo 15780883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 15790883e820SArnaldo Carvalho de Melo if (!ret) { 15800883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 15810883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 15820883e820SArnaldo Carvalho de Melo record->sample_address = true; 15830883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 15840883e820SArnaldo Carvalho de Melo } 15850883e820SArnaldo Carvalho de Melo 15860883e820SArnaldo Carvalho de Melo return ret; 158709b0fd45SJiri Olsa } 158809b0fd45SJiri Olsa 1589c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 159009b0fd45SJiri Olsa const char *arg, 159109b0fd45SJiri Olsa int unset) 159209b0fd45SJiri Olsa { 15930883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 159426d33022SJiri Olsa } 159526d33022SJiri Olsa 1596c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 159709b0fd45SJiri Olsa const char *arg __maybe_unused, 159809b0fd45SJiri Olsa int unset __maybe_unused) 159909b0fd45SJiri Olsa { 16002ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1601c421e80bSKan Liang 16022ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 160309b0fd45SJiri Olsa 16042ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 16052ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1606eb853e80SJiri Olsa 16072ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 160809b0fd45SJiri Olsa return 0; 160909b0fd45SJiri Olsa } 161009b0fd45SJiri Olsa 1611eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1612eb853e80SJiri Olsa { 16137a29c087SNamhyung Kim struct record *rec = cb; 16147a29c087SNamhyung Kim 16157a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 16167a29c087SNamhyung Kim if (!strcmp(value, "cache")) 16177a29c087SNamhyung Kim rec->no_buildid_cache = false; 16187a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 16197a29c087SNamhyung Kim rec->no_buildid_cache = true; 16207a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 16217a29c087SNamhyung Kim rec->no_buildid = true; 16227a29c087SNamhyung Kim else 16237a29c087SNamhyung Kim return -1; 16247a29c087SNamhyung Kim return 0; 16257a29c087SNamhyung Kim } 1626cff17205SYisheng Xie if (!strcmp(var, "record.call-graph")) { 1627cff17205SYisheng Xie var = "call-graph.record-mode"; 1628eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1629eb853e80SJiri Olsa } 163093f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 163193f20c0fSAlexey Budankov if (!strcmp(var, "record.aio")) { 163293f20c0fSAlexey Budankov rec->opts.nr_cblocks = strtol(value, NULL, 0); 163393f20c0fSAlexey Budankov if (!rec->opts.nr_cblocks) 163493f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_default; 163593f20c0fSAlexey Budankov } 163693f20c0fSAlexey Budankov #endif 1637eb853e80SJiri Olsa 1638cff17205SYisheng Xie return 0; 1639cff17205SYisheng Xie } 1640cff17205SYisheng Xie 1641814c8c38SPeter Zijlstra struct clockid_map { 1642814c8c38SPeter Zijlstra const char *name; 1643814c8c38SPeter Zijlstra int clockid; 1644814c8c38SPeter Zijlstra }; 1645814c8c38SPeter Zijlstra 1646814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1647814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1648814c8c38SPeter Zijlstra 1649814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1650814c8c38SPeter Zijlstra 1651814c8c38SPeter Zijlstra 1652814c8c38SPeter Zijlstra /* 1653814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1654814c8c38SPeter Zijlstra */ 1655814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1656814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1657814c8c38SPeter Zijlstra #endif 1658814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1659814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1660814c8c38SPeter Zijlstra #endif 1661814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1662814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1663814c8c38SPeter Zijlstra #endif 1664814c8c38SPeter Zijlstra 1665814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1666814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1667814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1668814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1669814c8c38SPeter Zijlstra 1670814c8c38SPeter Zijlstra /* available for some events */ 1671814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1672814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1673814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1674814c8c38SPeter Zijlstra 1675814c8c38SPeter Zijlstra /* available for the lazy */ 1676814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1677814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1678814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1679814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1680814c8c38SPeter Zijlstra 1681814c8c38SPeter Zijlstra CLOCKID_END, 1682814c8c38SPeter Zijlstra }; 1683814c8c38SPeter Zijlstra 1684cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns) 1685cf790516SAlexey Budankov { 1686cf790516SAlexey Budankov struct timespec res; 1687cf790516SAlexey Budankov 1688cf790516SAlexey Budankov *res_ns = 0; 1689cf790516SAlexey Budankov if (!clock_getres(clk_id, &res)) 1690cf790516SAlexey Budankov *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC; 1691cf790516SAlexey Budankov else 1692cf790516SAlexey Budankov pr_warning("WARNING: Failed to determine specified clock resolution.\n"); 1693cf790516SAlexey Budankov 1694cf790516SAlexey Budankov return 0; 1695cf790516SAlexey Budankov } 1696cf790516SAlexey Budankov 1697814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1698814c8c38SPeter Zijlstra { 1699814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1700814c8c38SPeter Zijlstra const struct clockid_map *cm; 1701814c8c38SPeter Zijlstra const char *ostr = str; 1702814c8c38SPeter Zijlstra 1703814c8c38SPeter Zijlstra if (unset) { 1704814c8c38SPeter Zijlstra opts->use_clockid = 0; 1705814c8c38SPeter Zijlstra return 0; 1706814c8c38SPeter Zijlstra } 1707814c8c38SPeter Zijlstra 1708814c8c38SPeter Zijlstra /* no arg passed */ 1709814c8c38SPeter Zijlstra if (!str) 1710814c8c38SPeter Zijlstra return 0; 1711814c8c38SPeter Zijlstra 1712814c8c38SPeter Zijlstra /* no setting it twice */ 1713814c8c38SPeter Zijlstra if (opts->use_clockid) 1714814c8c38SPeter Zijlstra return -1; 1715814c8c38SPeter Zijlstra 1716814c8c38SPeter Zijlstra opts->use_clockid = true; 1717814c8c38SPeter Zijlstra 1718814c8c38SPeter Zijlstra /* if its a number, we're done */ 1719814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1720cf790516SAlexey Budankov return get_clockid_res(opts->clockid, &opts->clockid_res_ns); 1721814c8c38SPeter Zijlstra 1722814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1723814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1724814c8c38SPeter Zijlstra str += 6; 1725814c8c38SPeter Zijlstra 1726814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1727814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1728814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1729cf790516SAlexey Budankov return get_clockid_res(opts->clockid, 1730cf790516SAlexey Budankov &opts->clockid_res_ns); 1731814c8c38SPeter Zijlstra } 1732814c8c38SPeter Zijlstra } 1733814c8c38SPeter Zijlstra 1734814c8c38SPeter Zijlstra opts->use_clockid = false; 1735814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1736814c8c38SPeter Zijlstra return -1; 1737814c8c38SPeter Zijlstra } 1738814c8c38SPeter Zijlstra 1739f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset) 1740f4fe11b7SAlexey Budankov { 1741f4fe11b7SAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 1742f4fe11b7SAlexey Budankov 1743f4fe11b7SAlexey Budankov if (unset || !str) 1744f4fe11b7SAlexey Budankov return 0; 1745f4fe11b7SAlexey Budankov 1746f4fe11b7SAlexey Budankov if (!strcasecmp(str, "node")) 1747f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_NODE; 1748f4fe11b7SAlexey Budankov else if (!strcasecmp(str, "cpu")) 1749f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_CPU; 1750f4fe11b7SAlexey Budankov 1751f4fe11b7SAlexey Budankov return 0; 1752f4fe11b7SAlexey Budankov } 1753f4fe11b7SAlexey Budankov 1754e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1755e9db1310SAdrian Hunter const char *str, 1756e9db1310SAdrian Hunter int unset __maybe_unused) 1757e9db1310SAdrian Hunter { 1758e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1759e9db1310SAdrian Hunter char *s, *p; 1760e9db1310SAdrian Hunter unsigned int mmap_pages; 1761e9db1310SAdrian Hunter int ret; 1762e9db1310SAdrian Hunter 1763e9db1310SAdrian Hunter if (!str) 1764e9db1310SAdrian Hunter return -EINVAL; 1765e9db1310SAdrian Hunter 1766e9db1310SAdrian Hunter s = strdup(str); 1767e9db1310SAdrian Hunter if (!s) 1768e9db1310SAdrian Hunter return -ENOMEM; 1769e9db1310SAdrian Hunter 1770e9db1310SAdrian Hunter p = strchr(s, ','); 1771e9db1310SAdrian Hunter if (p) 1772e9db1310SAdrian Hunter *p = '\0'; 1773e9db1310SAdrian Hunter 1774e9db1310SAdrian Hunter if (*s) { 1775e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1776e9db1310SAdrian Hunter if (ret) 1777e9db1310SAdrian Hunter goto out_free; 1778e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1779e9db1310SAdrian Hunter } 1780e9db1310SAdrian Hunter 1781e9db1310SAdrian Hunter if (!p) { 1782e9db1310SAdrian Hunter ret = 0; 1783e9db1310SAdrian Hunter goto out_free; 1784e9db1310SAdrian Hunter } 1785e9db1310SAdrian Hunter 1786e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1787e9db1310SAdrian Hunter if (ret) 1788e9db1310SAdrian Hunter goto out_free; 1789e9db1310SAdrian Hunter 1790e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1791e9db1310SAdrian Hunter 1792e9db1310SAdrian Hunter out_free: 1793e9db1310SAdrian Hunter free(s); 1794e9db1310SAdrian Hunter return ret; 1795e9db1310SAdrian Hunter } 1796e9db1310SAdrian Hunter 17970c582449SJiri Olsa static void switch_output_size_warn(struct record *rec) 17980c582449SJiri Olsa { 17990c582449SJiri Olsa u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages); 18000c582449SJiri Olsa struct switch_output *s = &rec->switch_output; 18010c582449SJiri Olsa 18020c582449SJiri Olsa wakeup_size /= 2; 18030c582449SJiri Olsa 18040c582449SJiri Olsa if (s->size < wakeup_size) { 18050c582449SJiri Olsa char buf[100]; 18060c582449SJiri Olsa 18070c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 18080c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than " 18090c582449SJiri Olsa "wakeup kernel buffer size (%s) " 18100c582449SJiri Olsa "expect bigger perf.data sizes\n", buf); 18110c582449SJiri Olsa } 18120c582449SJiri Olsa } 18130c582449SJiri Olsa 1814cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec) 1815cb4e1ebbSJiri Olsa { 1816cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output; 1817dc0c6127SJiri Olsa static struct parse_tag tags_size[] = { 1818dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 }, 1819dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 1820dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 1821dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 1822dc0c6127SJiri Olsa { .tag = 0 }, 1823dc0c6127SJiri Olsa }; 1824bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = { 1825bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 }, 1826bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 }, 1827bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 }, 1828bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 }, 1829bfacbe3bSJiri Olsa { .tag = 0 }, 1830bfacbe3bSJiri Olsa }; 1831dc0c6127SJiri Olsa unsigned long val; 1832cb4e1ebbSJiri Olsa 1833cb4e1ebbSJiri Olsa if (!s->set) 1834cb4e1ebbSJiri Olsa return 0; 1835cb4e1ebbSJiri Olsa 1836cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) { 1837cb4e1ebbSJiri Olsa s->signal = true; 1838cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n"); 1839dc0c6127SJiri Olsa goto enabled; 1840dc0c6127SJiri Olsa } 1841dc0c6127SJiri Olsa 1842dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size); 1843dc0c6127SJiri Olsa if (val != (unsigned long) -1) { 1844dc0c6127SJiri Olsa s->size = val; 1845dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str); 1846dc0c6127SJiri Olsa goto enabled; 1847cb4e1ebbSJiri Olsa } 1848cb4e1ebbSJiri Olsa 1849bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time); 1850bfacbe3bSJiri Olsa if (val != (unsigned long) -1) { 1851bfacbe3bSJiri Olsa s->time = val; 1852bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n", 1853bfacbe3bSJiri Olsa s->str, s->time); 1854bfacbe3bSJiri Olsa goto enabled; 1855bfacbe3bSJiri Olsa } 1856bfacbe3bSJiri Olsa 1857cb4e1ebbSJiri Olsa return -1; 1858dc0c6127SJiri Olsa 1859dc0c6127SJiri Olsa enabled: 1860dc0c6127SJiri Olsa rec->timestamp_filename = true; 1861dc0c6127SJiri Olsa s->enabled = true; 18620c582449SJiri Olsa 18630c582449SJiri Olsa if (s->size && !rec->opts.no_buffering) 18640c582449SJiri Olsa switch_output_size_warn(rec); 18650c582449SJiri Olsa 1866dc0c6127SJiri Olsa return 0; 1867cb4e1ebbSJiri Olsa } 1868cb4e1ebbSJiri Olsa 1869e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 187086470930SIngo Molnar "perf record [<options>] [<command>]", 187186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 187286470930SIngo Molnar NULL 187386470930SIngo Molnar }; 1874e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 187586470930SIngo Molnar 1876d20deb64SArnaldo Carvalho de Melo /* 18778c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 18788c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1879d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1880d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1881d20deb64SArnaldo Carvalho de Melo * 1882d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1883d20deb64SArnaldo Carvalho de Melo * 1884d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1885d20deb64SArnaldo Carvalho de Melo */ 18868c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1887d20deb64SArnaldo Carvalho de Melo .opts = { 18888affc2b8SAndi Kleen .sample_time = true, 1889d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1890d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1891d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1892447a6013SArnaldo Carvalho de Melo .freq = 4000, 1893d1cb9fceSNamhyung Kim .target = { 1894d1cb9fceSNamhyung Kim .uses_mmap = true, 18953aa5939dSAdrian Hunter .default_per_cpu = true, 1896d1cb9fceSNamhyung Kim }, 1897470530bbSAlexey Budankov .mmap_flush = MMAP_FLUSH_DEFAULT, 1898d20deb64SArnaldo Carvalho de Melo }, 1899e3d59112SNamhyung Kim .tool = { 1900e3d59112SNamhyung Kim .sample = process_sample_event, 1901e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1902cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1903e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1904f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces, 1905e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1906e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1907cca8482cSAdrian Hunter .ordered_events = true, 1908e3d59112SNamhyung Kim }, 1909d20deb64SArnaldo Carvalho de Melo }; 19107865e817SFrederic Weisbecker 191176a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 191276a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 191361eaa3beSArnaldo Carvalho de Melo 19140aab2136SWang Nan static bool dry_run; 19150aab2136SWang Nan 1916d20deb64SArnaldo Carvalho de Melo /* 1917d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1918d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1919b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1920d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1921d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1922d20deb64SArnaldo Carvalho de Melo */ 1923efd21307SJiri Olsa static struct option __record_options[] = { 1924d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 192586470930SIngo Molnar "event selector. use 'perf list' to list available events", 1926f120f9d5SJiri Olsa parse_events_option), 1927d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1928c171b552SLi Zefan "event filter", parse_filter), 19294ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 19304ba1faa1SWang Nan NULL, "don't record events from perf itself", 19314ba1faa1SWang Nan exclude_perf), 1932bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1933d6d901c2SZhang, Yanmin "record events on existing process id"), 1934bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1935d6d901c2SZhang, Yanmin "record events on existing thread id"), 1936d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 193786470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1938509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1939acac03faSKirill Smelkov "collect data without buffering"), 1940d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1941daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1942bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 194386470930SIngo Molnar "system-wide collection from all CPUs"), 1944bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1945c45c6ea2SStephane Eranian "list of cpus to monitor"), 1946d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 19472d4f2799SJiri Olsa OPT_STRING('o', "output", &record.data.path, "file", 194886470930SIngo Molnar "output file name"), 194969e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 195069e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 19512e6cdf99SStephane Eranian "child tasks do not inherit counters"), 19524ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 19534ea648aeSWang Nan "synthesize non-sample events at the end of output"), 1954626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 195571184c6aSSong Liu OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"), 1956b09c2364SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 1957b09c2364SArnaldo Carvalho de Melo "Fail if the specified frequency can't be used"), 195867230479SArnaldo Carvalho de Melo OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 195967230479SArnaldo Carvalho de Melo "profile at this frequency", 196067230479SArnaldo Carvalho de Melo record__parse_freq), 1961e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1962e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1963e9db1310SAdrian Hunter record__parse_mmap_pages), 1964470530bbSAlexey Budankov OPT_CALLBACK(0, "mmap-flush", &record.opts, "number", 1965470530bbSAlexey Budankov "Minimal number of bytes that is extracted from mmap data pages (default: 1)", 1966470530bbSAlexey Budankov record__mmap_flush_parse), 1967d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 196843bece79SLin Ming "put the counters into a counter group"), 19692ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 197009b0fd45SJiri Olsa NULL, "enables call-graph recording" , 197109b0fd45SJiri Olsa &record_callchain_opt), 197209b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 197376a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 197409b0fd45SJiri Olsa &record_parse_callchain_opt), 1975c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 19763da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1977b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1978d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1979649c48a9SPeter Zijlstra "per thread counts"), 198056100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 19813b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 19823b0a5daaSKan Liang "Record the sample physical addresses"), 1983b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 19843abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 19853abebc55SAdrian Hunter &record.opts.sample_time_set, 19863abebc55SAdrian Hunter "Record the sample timestamps"), 1987f290aa1fSJiri Olsa OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set, 1988f290aa1fSJiri Olsa "Record the sample period"), 1989d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1990649c48a9SPeter Zijlstra "don't sample"), 1991d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1992d2db9a98SWang Nan &record.no_buildid_cache_set, 1993a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1994d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1995d2db9a98SWang Nan &record.no_buildid_set, 1996baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1997d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1998023695d9SStephane Eranian "monitor event in cgroup name only", 1999023695d9SStephane Eranian parse_cgroups), 2000a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 20016619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 2002bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 2003bea03405SNamhyung Kim "user to profile"), 2004a5aabdacSStephane Eranian 2005a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 2006a5aabdacSStephane Eranian "branch any", "sample any taken branches", 2007a5aabdacSStephane Eranian parse_branch_stack), 2008a5aabdacSStephane Eranian 2009a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 2010a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 2011bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 201205484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 201305484298SAndi Kleen "sample by weight (on special events only)"), 2014475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 2015475eeab9SAndi Kleen "sample transaction flags (special events only)"), 20163aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 20173aa5939dSAdrian Hunter "use per-thread mmaps"), 2018bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 2019bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 2020*8e5bc76fSArnaldo Carvalho de Melo " use '-I?' to list register names", parse_regs), 202184c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 202284c41742SAndi Kleen "sample selected machine registers on interrupt," 2023*8e5bc76fSArnaldo Carvalho de Melo " use '-I?' to list register names", parse_regs), 202485c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 202585c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 2026814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 2027814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 2028814c8c38SPeter Zijlstra parse_clockid), 20292dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 20302dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 20313fcb10e4SMark Drayton OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout, 20329d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 2033f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 2034f3b3614aSHari Bathini "Record namespaces events"), 2035b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 2036b757bb09SAdrian Hunter "Record context switch events"), 203785723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 203885723885SJiri Olsa "Configure all used events to run in kernel space.", 203985723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 204085723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 204185723885SJiri Olsa "Configure all used events to run in user space.", 204285723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 204371dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 204471dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 204571dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 204671dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 20477efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 20487efe0e03SHe Kuang "file", "vmlinux pathname"), 20496156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 20506156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 2051ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 2052ecfd7a9cSWang Nan "append timestamp to output filename"), 205368588bafSJin Yao OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 205468588bafSJin Yao "Record timestamp boundary (time of first/last samples)"), 2055cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 2056c38dab7dSAndi Kleen &record.switch_output.set, "signal or size[BKMG] or time[smhd]", 2057c38dab7dSAndi Kleen "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold", 2058dc0c6127SJiri Olsa "signal"), 205903724b2eSAndi Kleen OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, 206003724b2eSAndi Kleen "Limit number of switch output generated files"), 20610aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 20620aab2136SWang Nan "Parse options then exit"), 2063d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 206493f20c0fSAlexey Budankov OPT_CALLBACK_OPTARG(0, "aio", &record.opts, 206593f20c0fSAlexey Budankov &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)", 2066d3d1af6fSAlexey Budankov record__aio_parse), 2067d3d1af6fSAlexey Budankov #endif 2068f4fe11b7SAlexey Budankov OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", 2069f4fe11b7SAlexey Budankov "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", 2070f4fe11b7SAlexey Budankov record__parse_affinity), 207186470930SIngo Molnar OPT_END() 207286470930SIngo Molnar }; 207386470930SIngo Molnar 2074e5b2c207SNamhyung Kim struct option *record_options = __record_options; 2075e5b2c207SNamhyung Kim 2076b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv) 207786470930SIngo Molnar { 2078ef149c25SAdrian Hunter int err; 20798c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 208016ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 208186470930SIngo Molnar 208267230479SArnaldo Carvalho de Melo setlocale(LC_ALL, ""); 208367230479SArnaldo Carvalho de Melo 208448e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 208548e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 208648e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 208748e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 208848e1cab1SWang Nan # undef set_nobuild 208948e1cab1SWang Nan #endif 209048e1cab1SWang Nan 20917efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 20927efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 20937efe0e03SHe Kuang # define REASON "NO_DWARF=1" 20947efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 20957efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 20967efe0e03SHe Kuang # else 20977efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 20987efe0e03SHe Kuang # endif 20997efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 21007efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 21017efe0e03SHe Kuang # undef set_nobuild 21027efe0e03SHe Kuang # undef REASON 21037efe0e03SHe Kuang #endif 21047efe0e03SHe Kuang 21059d2ed645SAlexey Budankov CPU_ZERO(&rec->affinity_mask); 21069d2ed645SAlexey Budankov rec->opts.affinity = PERF_AFFINITY_SYS; 21079d2ed645SAlexey Budankov 21083e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 21093e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 2110361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 2111361c99a6SArnaldo Carvalho de Melo 2112ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec); 2113ecc4c561SArnaldo Carvalho de Melo if (err) 2114ecc4c561SArnaldo Carvalho de Melo return err; 2115eb853e80SJiri Olsa 2116bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 2117a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 211868ba3235SNamhyung Kim if (quiet) 211968ba3235SNamhyung Kim perf_quiet_option(); 2120483635a9SJiri Olsa 2121483635a9SJiri Olsa /* Make system wide (-a) the default target. */ 2122602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 2123483635a9SJiri Olsa rec->opts.target.system_wide = true; 212486470930SIngo Molnar 2125bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 2126c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 2127c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 2128c7118369SNamhyung Kim 2129023695d9SStephane Eranian } 2130b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 2131b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 2132c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 2133c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 2134c7118369SNamhyung Kim return -EINVAL; 2135b757bb09SAdrian Hunter } 2136023695d9SStephane Eranian 2137cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) { 2138cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0); 2139cb4e1ebbSJiri Olsa return -EINVAL; 2140cb4e1ebbSJiri Olsa } 2141cb4e1ebbSJiri Olsa 2142bfacbe3bSJiri Olsa if (rec->switch_output.time) { 2143bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler); 2144bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 2145bfacbe3bSJiri Olsa } 2146bfacbe3bSJiri Olsa 214703724b2eSAndi Kleen if (rec->switch_output.num_files) { 214803724b2eSAndi Kleen rec->switch_output.filenames = calloc(sizeof(char *), 214903724b2eSAndi Kleen rec->switch_output.num_files); 215003724b2eSAndi Kleen if (!rec->switch_output.filenames) 215103724b2eSAndi Kleen return -EINVAL; 215203724b2eSAndi Kleen } 215303724b2eSAndi Kleen 21541b36c03eSAdrian Hunter /* 21551b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address 21561b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters(). 21571b36c03eSAdrian Hunter */ 21581b36c03eSAdrian Hunter symbol_conf.allow_aliases = true; 21591b36c03eSAdrian Hunter 21601b36c03eSAdrian Hunter symbol__init(NULL); 21611b36c03eSAdrian Hunter 21624b5ea3bdSAdrian Hunter err = record__auxtrace_init(rec); 21631b36c03eSAdrian Hunter if (err) 21641b36c03eSAdrian Hunter goto out; 21651b36c03eSAdrian Hunter 21660aab2136SWang Nan if (dry_run) 21675c01ad60SAdrian Hunter goto out; 21680aab2136SWang Nan 2169d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 2170d7888573SWang Nan if (err) { 2171d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 2172d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 2173d7888573SWang Nan errbuf); 21745c01ad60SAdrian Hunter goto out; 2175d7888573SWang Nan } 2176d7888573SWang Nan 2177ef149c25SAdrian Hunter err = -ENOMEM; 2178ef149c25SAdrian Hunter 21796c443954SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(rec->evlist)) 2180646aaea6SArnaldo Carvalho de Melo pr_warning( 2181646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 2182ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 2183646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 2184646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 2185646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 2186646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 2187646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 2188ec80fde7SArnaldo Carvalho de Melo 21890c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 2190a1ac1d3cSStephane Eranian disable_buildid_cache(); 2191dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) { 21920c1d46a8SWang Nan /* 21930c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 21940c1d46a8SWang Nan * generation by default to reduce data file switching 21950c1d46a8SWang Nan * overhead. Still generate buildid if they are required 21960c1d46a8SWang Nan * explicitly using 21970c1d46a8SWang Nan * 219860437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \ 21990c1d46a8SWang Nan * --no-no-buildid-cache 22000c1d46a8SWang Nan * 22010c1d46a8SWang Nan * Following code equals to: 22020c1d46a8SWang Nan * 22030c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 22040c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 22050c1d46a8SWang Nan * disable_buildid_cache(); 22060c1d46a8SWang Nan */ 22070c1d46a8SWang Nan bool disable = true; 22080c1d46a8SWang Nan 22090c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 22100c1d46a8SWang Nan disable = false; 22110c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 22120c1d46a8SWang Nan disable = false; 22130c1d46a8SWang Nan if (disable) { 22140c1d46a8SWang Nan rec->no_buildid = true; 22150c1d46a8SWang Nan rec->no_buildid_cache = true; 22160c1d46a8SWang Nan disable_buildid_cache(); 22170c1d46a8SWang Nan } 22180c1d46a8SWang Nan } 2219655000e7SArnaldo Carvalho de Melo 22204ea648aeSWang Nan if (record.opts.overwrite) 22214ea648aeSWang Nan record.opts.tail_synthesize = true; 22224ea648aeSWang Nan 22233e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 22244b4cd503SArnaldo Carvalho de Melo __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { 222569aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 2226394c01edSAdrian Hunter goto out; 2227bbd36e5eSPeter Zijlstra } 222886470930SIngo Molnar 222969e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 223069e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 223169e7e5b0SAdrian Hunter 2232602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 223316ad2ffbSNamhyung Kim if (err) { 2234602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 2235c3dec27bSJiri Olsa ui__warning("%s\n", errbuf); 223616ad2ffbSNamhyung Kim } 22374bd0f2d2SNamhyung Kim 2238602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 223916ad2ffbSNamhyung Kim if (err) { 224016ad2ffbSNamhyung Kim int saved_errno = errno; 224116ad2ffbSNamhyung Kim 2242602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 22433780f488SNamhyung Kim ui__error("%s", errbuf); 224416ad2ffbSNamhyung Kim 224516ad2ffbSNamhyung Kim err = -saved_errno; 2246394c01edSAdrian Hunter goto out; 224716ad2ffbSNamhyung Kim } 22480d37aa34SArnaldo Carvalho de Melo 2249ca800068SMengting Zhang /* Enable ignoring missing threads when -u/-p option is defined. */ 2250ca800068SMengting Zhang rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; 225123dc4f15SJiri Olsa 225216ad2ffbSNamhyung Kim err = -ENOMEM; 22533e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 2254dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 225569aad6f1SArnaldo Carvalho de Melo 2256ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 2257ef149c25SAdrian Hunter if (err) 2258394c01edSAdrian Hunter goto out; 2259ef149c25SAdrian Hunter 22606156681bSNamhyung Kim /* 22616156681bSNamhyung Kim * We take all buildids when the file contains 22626156681bSNamhyung Kim * AUX area tracing data because we do not decode the 22636156681bSNamhyung Kim * trace because it would take too long. 22646156681bSNamhyung Kim */ 22656156681bSNamhyung Kim if (rec->opts.full_auxtrace) 22666156681bSNamhyung Kim rec->buildid_all = true; 22676156681bSNamhyung Kim 2268b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 226939d17dacSArnaldo Carvalho de Melo err = -EINVAL; 2270394c01edSAdrian Hunter goto out; 22717e4ff9e3SMike Galbraith } 22727e4ff9e3SMike Galbraith 227393f20c0fSAlexey Budankov if (rec->opts.nr_cblocks > nr_cblocks_max) 227493f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_max; 2275d3d1af6fSAlexey Budankov if (verbose > 0) 2276d3d1af6fSAlexey Budankov pr_info("nr_cblocks: %d\n", rec->opts.nr_cblocks); 2277d3d1af6fSAlexey Budankov 22789d2ed645SAlexey Budankov pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); 2279470530bbSAlexey Budankov pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); 22809d2ed645SAlexey Budankov 2281d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 2282394c01edSAdrian Hunter out: 228345604710SNamhyung Kim perf_evlist__delete(rec->evlist); 2284d65a458bSArnaldo Carvalho de Melo symbol__exit(); 2285ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 228639d17dacSArnaldo Carvalho de Melo return err; 228786470930SIngo Molnar } 22882dd6d8a1SAdrian Hunter 22892dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 22902dd6d8a1SAdrian Hunter { 2291dc0c6127SJiri Olsa struct record *rec = &record; 2292dc0c6127SJiri Olsa 22935f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 22945f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 22952dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 22965f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 22975f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 22985f9cf599SWang Nan } 22993c1cb7e3SWang Nan 2300dc0c6127SJiri Olsa if (switch_output_signal(rec)) 23013c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 23022dd6d8a1SAdrian Hunter } 2303bfacbe3bSJiri Olsa 2304bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused) 2305bfacbe3bSJiri Olsa { 2306bfacbe3bSJiri Olsa struct record *rec = &record; 2307bfacbe3bSJiri Olsa 2308bfacbe3bSJiri Olsa if (switch_output_time(rec)) 2309bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger); 2310bfacbe3bSJiri Olsa } 2311