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 116122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 124b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1386470930SIngo Molnar #include "util/parse-events.h" 1441840d21STaeung Song #include "util/config.h" 1586470930SIngo Molnar 168f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 17f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 187c6a1c65SPeter Zijlstra #include "util/header.h" 1966e274f3SFrederic Weisbecker #include "util/event.h" 20361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2169aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 228f28827aSFrederic Weisbecker #include "util/debug.h" 23e0fcfb08SArnaldo Carvalho de Melo #include "util/mmap.h" 24aeb00b1aSArnaldo Carvalho de Melo #include "util/target.h" 2594c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2645694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 278d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 28aeb00b1aSArnaldo Carvalho de Melo #include "util/record.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" 3740c7d246SArnaldo Carvalho de Melo #include "util/perf_api_probe.h" 3871dc2326SWang Nan #include "util/llvm-utils.h" 398690a2a7SWang Nan #include "util/bpf-loader.h" 405f9cf599SWang Nan #include "util/trigger.h" 41a074865eSWang Nan #include "util/perf-hooks.h" 42f13de660SAlexey Budankov #include "util/cpu-set-sched.h" 43ea49e01cSArnaldo Carvalho de Melo #include "util/synthetic-events.h" 44c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h" 4558db1d6eSArnaldo Carvalho de Melo #include "util/units.h" 467b612e29SSong Liu #include "util/bpf-event.h" 47d99c22eaSStephane Eranian #include "util/util.h" 4870943490SStephane Eranian #include "util/pfm.h" 496953beb4SJiri Olsa #include "util/clockid.h" 50b53a0755SJin Yao #include "util/pmu-hybrid.h" 51b53a0755SJin Yao #include "util/evlist-hybrid.h" 52d8871ea7SWang Nan #include "asm/bug.h" 53c1a604dfSArnaldo Carvalho de Melo #include "perf.h" 547c6a1c65SPeter Zijlstra 55a43783aeSArnaldo Carvalho de Melo #include <errno.h> 56fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 5767230479SArnaldo Carvalho de Melo #include <locale.h> 584208735dSArnaldo Carvalho de Melo #include <poll.h> 59d99c22eaSStephane Eranian #include <pthread.h> 6086470930SIngo Molnar #include <unistd.h> 6186470930SIngo Molnar #include <sched.h> 629607ad3aSArnaldo Carvalho de Melo #include <signal.h> 63da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 64da231338SAnand K Mistry #include <sys/eventfd.h> 65da231338SAnand K Mistry #endif 66a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 674208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 68eeb399b5SAdrian Hunter #include <sys/types.h> 69eeb399b5SAdrian Hunter #include <sys/stat.h> 70eeb399b5SAdrian Hunter #include <fcntl.h> 716ef81c55SMamatha Inamdar #include <linux/err.h> 728520a98dSArnaldo Carvalho de Melo #include <linux/string.h> 730693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 74d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h> 758384a260SAlexey Budankov #include <linux/bitmap.h> 76d1e325cfSJiri Olsa #include <sys/time.h> 7778da39faSBernhard Rosenkraenzer 781b43b704SJiri Olsa struct switch_output { 79dc0c6127SJiri Olsa bool enabled; 801b43b704SJiri Olsa bool signal; 81dc0c6127SJiri Olsa unsigned long size; 82bfacbe3bSJiri Olsa unsigned long time; 83cb4e1ebbSJiri Olsa const char *str; 84cb4e1ebbSJiri Olsa bool set; 8503724b2eSAndi Kleen char **filenames; 8603724b2eSAndi Kleen int num_files; 8703724b2eSAndi Kleen int cur_file; 881b43b704SJiri Olsa }; 891b43b704SJiri Olsa 90*7954f716SAlexey Bayduraev struct thread_mask { 91*7954f716SAlexey Bayduraev struct mmap_cpu_mask maps; 92*7954f716SAlexey Bayduraev struct mmap_cpu_mask affinity; 93*7954f716SAlexey Bayduraev }; 94*7954f716SAlexey Bayduraev 958c6f45a7SArnaldo Carvalho de Melo struct record { 9645694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 97b4006796SArnaldo Carvalho de Melo struct record_opts opts; 98d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 998ceb41d7SJiri Olsa struct perf_data data; 100ef149c25SAdrian Hunter struct auxtrace_record *itr; 10163503dbaSJiri Olsa struct evlist *evlist; 102d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 103bc477d79SArnaldo Carvalho de Melo struct evlist *sb_evlist; 104899e5ffbSArnaldo Carvalho de Melo pthread_t thread_id; 105d20deb64SArnaldo Carvalho de Melo int realtime_prio; 106899e5ffbSArnaldo Carvalho de Melo bool switch_output_event_set; 107d20deb64SArnaldo Carvalho de Melo bool no_buildid; 108d2db9a98SWang Nan bool no_buildid_set; 109d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 110d2db9a98SWang Nan bool no_buildid_cache_set; 1116156681bSNamhyung Kim bool buildid_all; 112e29386c8SJiri Olsa bool buildid_mmap; 113ecfd7a9cSWang Nan bool timestamp_filename; 11468588bafSJin Yao bool timestamp_boundary; 1151b43b704SJiri Olsa struct switch_output switch_output; 1169f065194SYang Shi unsigned long long samples; 1178384a260SAlexey Budankov struct mmap_cpu_mask affinity_mask; 1186d575816SJiwei Sun unsigned long output_max_size; /* = 0: unlimited */ 1199bce13eaSJiri Olsa struct perf_debuginfod debuginfod; 120*7954f716SAlexey Bayduraev int nr_threads; 121*7954f716SAlexey Bayduraev struct thread_mask *thread_masks; 1220f82ebc4SArnaldo Carvalho de Melo }; 12386470930SIngo Molnar 1246d575816SJiwei Sun static volatile int done; 1256d575816SJiwei Sun 126dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started; 127dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 128dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger); 129dc0c6127SJiri Olsa 1309d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = { 1319d2ed645SAlexey Budankov "SYS", "NODE", "CPU" 1329d2ed645SAlexey Budankov }; 1339d2ed645SAlexey Budankov 134dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec) 135dc0c6127SJiri Olsa { 136dc0c6127SJiri Olsa return rec->switch_output.signal && 137dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger); 138dc0c6127SJiri Olsa } 139dc0c6127SJiri Olsa 140dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec) 141dc0c6127SJiri Olsa { 142dc0c6127SJiri Olsa return rec->switch_output.size && 143dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) && 144dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size); 145dc0c6127SJiri Olsa } 146dc0c6127SJiri Olsa 147bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec) 148bfacbe3bSJiri Olsa { 149bfacbe3bSJiri Olsa return rec->switch_output.time && 150bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger); 151bfacbe3bSJiri Olsa } 152bfacbe3bSJiri Olsa 1536d575816SJiwei Sun static bool record__output_max_size_exceeded(struct record *rec) 1546d575816SJiwei Sun { 1556d575816SJiwei Sun return rec->output_max_size && 1566d575816SJiwei Sun (rec->bytes_written >= rec->output_max_size); 1576d575816SJiwei Sun } 1586d575816SJiwei Sun 159a5830532SJiri Olsa static int record__write(struct record *rec, struct mmap *map __maybe_unused, 160ded2b8feSJiri Olsa void *bf, size_t size) 161f5970550SPeter Zijlstra { 162ded2b8feSJiri Olsa struct perf_data_file *file = &rec->session->data->file; 163ded2b8feSJiri Olsa 164ded2b8feSJiri Olsa if (perf_data_file__write(file, bf, size) < 0) { 1654f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 1668d3eca20SDavid Ahern return -1; 1678d3eca20SDavid Ahern } 168f5970550SPeter Zijlstra 169cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 170dc0c6127SJiri Olsa 1716d575816SJiwei Sun if (record__output_max_size_exceeded(rec) && !done) { 1726d575816SJiwei Sun fprintf(stderr, "[ perf record: perf size limit reached (%" PRIu64 " KB)," 1736d575816SJiwei Sun " stopping session ]\n", 1746d575816SJiwei Sun rec->bytes_written >> 10); 1756d575816SJiwei Sun done = 1; 1766d575816SJiwei Sun } 1776d575816SJiwei Sun 178dc0c6127SJiri Olsa if (switch_output_size(rec)) 179dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger); 180dc0c6127SJiri Olsa 1818d3eca20SDavid Ahern return 0; 182f5970550SPeter Zijlstra } 183f5970550SPeter Zijlstra 184ef781128SAlexey Budankov static int record__aio_enabled(struct record *rec); 185ef781128SAlexey Budankov static int record__comp_enabled(struct record *rec); 1865d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 1875d7f4116SAlexey Budankov void *src, size_t src_size); 1885d7f4116SAlexey Budankov 189d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 190d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd, 191d3d1af6fSAlexey Budankov void *buf, size_t size, off_t off) 192d3d1af6fSAlexey Budankov { 193d3d1af6fSAlexey Budankov int rc; 194d3d1af6fSAlexey Budankov 195d3d1af6fSAlexey Budankov cblock->aio_fildes = trace_fd; 196d3d1af6fSAlexey Budankov cblock->aio_buf = buf; 197d3d1af6fSAlexey Budankov cblock->aio_nbytes = size; 198d3d1af6fSAlexey Budankov cblock->aio_offset = off; 199d3d1af6fSAlexey Budankov cblock->aio_sigevent.sigev_notify = SIGEV_NONE; 200d3d1af6fSAlexey Budankov 201d3d1af6fSAlexey Budankov do { 202d3d1af6fSAlexey Budankov rc = aio_write(cblock); 203d3d1af6fSAlexey Budankov if (rc == 0) { 204d3d1af6fSAlexey Budankov break; 205d3d1af6fSAlexey Budankov } else if (errno != EAGAIN) { 206d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 207d3d1af6fSAlexey Budankov pr_err("failed to queue perf data, error: %m\n"); 208d3d1af6fSAlexey Budankov break; 209d3d1af6fSAlexey Budankov } 210d3d1af6fSAlexey Budankov } while (1); 211d3d1af6fSAlexey Budankov 212d3d1af6fSAlexey Budankov return rc; 213d3d1af6fSAlexey Budankov } 214d3d1af6fSAlexey Budankov 215a5830532SJiri Olsa static int record__aio_complete(struct mmap *md, struct aiocb *cblock) 216d3d1af6fSAlexey Budankov { 217d3d1af6fSAlexey Budankov void *rem_buf; 218d3d1af6fSAlexey Budankov off_t rem_off; 219d3d1af6fSAlexey Budankov size_t rem_size; 220d3d1af6fSAlexey Budankov int rc, aio_errno; 221d3d1af6fSAlexey Budankov ssize_t aio_ret, written; 222d3d1af6fSAlexey Budankov 223d3d1af6fSAlexey Budankov aio_errno = aio_error(cblock); 224d3d1af6fSAlexey Budankov if (aio_errno == EINPROGRESS) 225d3d1af6fSAlexey Budankov return 0; 226d3d1af6fSAlexey Budankov 227d3d1af6fSAlexey Budankov written = aio_ret = aio_return(cblock); 228d3d1af6fSAlexey Budankov if (aio_ret < 0) { 229d3d1af6fSAlexey Budankov if (aio_errno != EINTR) 230d3d1af6fSAlexey Budankov pr_err("failed to write perf data, error: %m\n"); 231d3d1af6fSAlexey Budankov written = 0; 232d3d1af6fSAlexey Budankov } 233d3d1af6fSAlexey Budankov 234d3d1af6fSAlexey Budankov rem_size = cblock->aio_nbytes - written; 235d3d1af6fSAlexey Budankov 236d3d1af6fSAlexey Budankov if (rem_size == 0) { 237d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 238d3d1af6fSAlexey Budankov /* 239ef781128SAlexey Budankov * md->refcount is incremented in record__aio_pushfn() for 240ef781128SAlexey Budankov * every aio write request started in record__aio_push() so 241ef781128SAlexey Budankov * decrement it because the request is now complete. 242d3d1af6fSAlexey Budankov */ 24380e53d11SJiri Olsa perf_mmap__put(&md->core); 244d3d1af6fSAlexey Budankov rc = 1; 245d3d1af6fSAlexey Budankov } else { 246d3d1af6fSAlexey Budankov /* 247d3d1af6fSAlexey Budankov * aio write request may require restart with the 248d3d1af6fSAlexey Budankov * reminder if the kernel didn't write whole 249d3d1af6fSAlexey Budankov * chunk at once. 250d3d1af6fSAlexey Budankov */ 251d3d1af6fSAlexey Budankov rem_off = cblock->aio_offset + written; 252d3d1af6fSAlexey Budankov rem_buf = (void *)(cblock->aio_buf + written); 253d3d1af6fSAlexey Budankov record__aio_write(cblock, cblock->aio_fildes, 254d3d1af6fSAlexey Budankov rem_buf, rem_size, rem_off); 255d3d1af6fSAlexey Budankov rc = 0; 256d3d1af6fSAlexey Budankov } 257d3d1af6fSAlexey Budankov 258d3d1af6fSAlexey Budankov return rc; 259d3d1af6fSAlexey Budankov } 260d3d1af6fSAlexey Budankov 261a5830532SJiri Olsa static int record__aio_sync(struct mmap *md, bool sync_all) 262d3d1af6fSAlexey Budankov { 26393f20c0fSAlexey Budankov struct aiocb **aiocb = md->aio.aiocb; 26493f20c0fSAlexey Budankov struct aiocb *cblocks = md->aio.cblocks; 265d3d1af6fSAlexey Budankov struct timespec timeout = { 0, 1000 * 1000 * 1 }; /* 1ms */ 26693f20c0fSAlexey Budankov int i, do_suspend; 267d3d1af6fSAlexey Budankov 268d3d1af6fSAlexey Budankov do { 26993f20c0fSAlexey Budankov do_suspend = 0; 27093f20c0fSAlexey Budankov for (i = 0; i < md->aio.nr_cblocks; ++i) { 27193f20c0fSAlexey Budankov if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) { 27293f20c0fSAlexey Budankov if (sync_all) 27393f20c0fSAlexey Budankov aiocb[i] = NULL; 27493f20c0fSAlexey Budankov else 27593f20c0fSAlexey Budankov return i; 27693f20c0fSAlexey Budankov } else { 27793f20c0fSAlexey Budankov /* 27893f20c0fSAlexey Budankov * Started aio write is not complete yet 27993f20c0fSAlexey Budankov * so it has to be waited before the 28093f20c0fSAlexey Budankov * next allocation. 28193f20c0fSAlexey Budankov */ 28293f20c0fSAlexey Budankov aiocb[i] = &cblocks[i]; 28393f20c0fSAlexey Budankov do_suspend = 1; 28493f20c0fSAlexey Budankov } 28593f20c0fSAlexey Budankov } 28693f20c0fSAlexey Budankov if (!do_suspend) 28793f20c0fSAlexey Budankov return -1; 288d3d1af6fSAlexey Budankov 28993f20c0fSAlexey Budankov while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) { 290d3d1af6fSAlexey Budankov if (!(errno == EAGAIN || errno == EINTR)) 291d3d1af6fSAlexey Budankov pr_err("failed to sync perf data, error: %m\n"); 292d3d1af6fSAlexey Budankov } 293d3d1af6fSAlexey Budankov } while (1); 294d3d1af6fSAlexey Budankov } 295d3d1af6fSAlexey Budankov 296ef781128SAlexey Budankov struct record_aio { 297ef781128SAlexey Budankov struct record *rec; 298ef781128SAlexey Budankov void *data; 299ef781128SAlexey Budankov size_t size; 300ef781128SAlexey Budankov }; 301ef781128SAlexey Budankov 302a5830532SJiri Olsa static int record__aio_pushfn(struct mmap *map, void *to, void *buf, size_t size) 303d3d1af6fSAlexey Budankov { 304ef781128SAlexey Budankov struct record_aio *aio = to; 305ef781128SAlexey Budankov 306ef781128SAlexey Budankov /* 307547740f7SJiri Olsa * map->core.base data pointed by buf is copied into free map->aio.data[] buffer 308ef781128SAlexey Budankov * to release space in the kernel buffer as fast as possible, calling 309ef781128SAlexey Budankov * perf_mmap__consume() from perf_mmap__push() function. 310ef781128SAlexey Budankov * 311ef781128SAlexey Budankov * That lets the kernel to proceed with storing more profiling data into 312ef781128SAlexey Budankov * the kernel buffer earlier than other per-cpu kernel buffers are handled. 313ef781128SAlexey Budankov * 314ef781128SAlexey Budankov * Coping can be done in two steps in case the chunk of profiling data 315ef781128SAlexey Budankov * crosses the upper bound of the kernel buffer. In this case we first move 316ef781128SAlexey Budankov * part of data from map->start till the upper bound and then the reminder 317ef781128SAlexey Budankov * from the beginning of the kernel buffer till the end of the data chunk. 318ef781128SAlexey Budankov */ 319ef781128SAlexey Budankov 320ef781128SAlexey Budankov if (record__comp_enabled(aio->rec)) { 321ef781128SAlexey Budankov size = zstd_compress(aio->rec->session, aio->data + aio->size, 322bf59b305SJiri Olsa mmap__mmap_len(map) - aio->size, 323ef781128SAlexey Budankov buf, size); 324ef781128SAlexey Budankov } else { 325ef781128SAlexey Budankov memcpy(aio->data + aio->size, buf, size); 326ef781128SAlexey Budankov } 327ef781128SAlexey Budankov 328ef781128SAlexey Budankov if (!aio->size) { 329ef781128SAlexey Budankov /* 330ef781128SAlexey Budankov * Increment map->refcount to guard map->aio.data[] buffer 331ef781128SAlexey Budankov * from premature deallocation because map object can be 332ef781128SAlexey Budankov * released earlier than aio write request started on 333ef781128SAlexey Budankov * map->aio.data[] buffer is complete. 334ef781128SAlexey Budankov * 335ef781128SAlexey Budankov * perf_mmap__put() is done at record__aio_complete() 336ef781128SAlexey Budankov * after started aio request completion or at record__aio_push() 337ef781128SAlexey Budankov * if the request failed to start. 338ef781128SAlexey Budankov */ 339e75710f0SJiri Olsa perf_mmap__get(&map->core); 340ef781128SAlexey Budankov } 341ef781128SAlexey Budankov 342ef781128SAlexey Budankov aio->size += size; 343ef781128SAlexey Budankov 344ef781128SAlexey Budankov return size; 345ef781128SAlexey Budankov } 346ef781128SAlexey Budankov 347a5830532SJiri Olsa static int record__aio_push(struct record *rec, struct mmap *map, off_t *off) 348ef781128SAlexey Budankov { 349ef781128SAlexey Budankov int ret, idx; 350ef781128SAlexey Budankov int trace_fd = rec->session->data->file.fd; 351ef781128SAlexey Budankov struct record_aio aio = { .rec = rec, .size = 0 }; 352ef781128SAlexey Budankov 353ef781128SAlexey Budankov /* 354ef781128SAlexey Budankov * Call record__aio_sync() to wait till map->aio.data[] buffer 355ef781128SAlexey Budankov * becomes available after previous aio write operation. 356ef781128SAlexey Budankov */ 357ef781128SAlexey Budankov 358ef781128SAlexey Budankov idx = record__aio_sync(map, false); 359ef781128SAlexey Budankov aio.data = map->aio.data[idx]; 360ef781128SAlexey Budankov ret = perf_mmap__push(map, &aio, record__aio_pushfn); 361ef781128SAlexey Budankov if (ret != 0) /* ret > 0 - no data, ret < 0 - error */ 362ef781128SAlexey Budankov return ret; 363d3d1af6fSAlexey Budankov 364d3d1af6fSAlexey Budankov rec->samples++; 365ef781128SAlexey Budankov ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off); 366d3d1af6fSAlexey Budankov if (!ret) { 367ef781128SAlexey Budankov *off += aio.size; 368ef781128SAlexey Budankov rec->bytes_written += aio.size; 369d3d1af6fSAlexey Budankov if (switch_output_size(rec)) 370d3d1af6fSAlexey Budankov trigger_hit(&switch_output_trigger); 371ef781128SAlexey Budankov } else { 372ef781128SAlexey Budankov /* 373ef781128SAlexey Budankov * Decrement map->refcount incremented in record__aio_pushfn() 374ef781128SAlexey Budankov * back if record__aio_write() operation failed to start, otherwise 375ef781128SAlexey Budankov * map->refcount is decremented in record__aio_complete() after 376ef781128SAlexey Budankov * aio write operation finishes successfully. 377ef781128SAlexey Budankov */ 37880e53d11SJiri Olsa perf_mmap__put(&map->core); 379d3d1af6fSAlexey Budankov } 380d3d1af6fSAlexey Budankov 381d3d1af6fSAlexey Budankov return ret; 382d3d1af6fSAlexey Budankov } 383d3d1af6fSAlexey Budankov 384d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd) 385d3d1af6fSAlexey Budankov { 386d3d1af6fSAlexey Budankov return lseek(trace_fd, 0, SEEK_CUR); 387d3d1af6fSAlexey Budankov } 388d3d1af6fSAlexey Budankov 389d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos) 390d3d1af6fSAlexey Budankov { 391d3d1af6fSAlexey Budankov lseek(trace_fd, pos, SEEK_SET); 392d3d1af6fSAlexey Budankov } 393d3d1af6fSAlexey Budankov 394d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec) 395d3d1af6fSAlexey Budankov { 396d3d1af6fSAlexey Budankov int i; 39763503dbaSJiri Olsa struct evlist *evlist = rec->evlist; 398a5830532SJiri Olsa struct mmap *maps = evlist->mmap; 399d3d1af6fSAlexey Budankov 400ef781128SAlexey Budankov if (!record__aio_enabled(rec)) 401d3d1af6fSAlexey Budankov return; 402d3d1af6fSAlexey Budankov 403c976ee11SJiri Olsa for (i = 0; i < evlist->core.nr_mmaps; i++) { 404a5830532SJiri Olsa struct mmap *map = &maps[i]; 405d3d1af6fSAlexey Budankov 406547740f7SJiri Olsa if (map->core.base) 40793f20c0fSAlexey Budankov record__aio_sync(map, true); 408d3d1af6fSAlexey Budankov } 409d3d1af6fSAlexey Budankov } 410d3d1af6fSAlexey Budankov 411d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1; 41293f20c0fSAlexey Budankov static int nr_cblocks_max = 4; 413d3d1af6fSAlexey Budankov 414d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt, 41593f20c0fSAlexey Budankov const char *str, 416d3d1af6fSAlexey Budankov int unset) 417d3d1af6fSAlexey Budankov { 418d3d1af6fSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 419d3d1af6fSAlexey Budankov 42093f20c0fSAlexey Budankov if (unset) { 421d3d1af6fSAlexey Budankov opts->nr_cblocks = 0; 42293f20c0fSAlexey Budankov } else { 42393f20c0fSAlexey Budankov if (str) 42493f20c0fSAlexey Budankov opts->nr_cblocks = strtol(str, NULL, 0); 42593f20c0fSAlexey Budankov if (!opts->nr_cblocks) 426d3d1af6fSAlexey Budankov opts->nr_cblocks = nr_cblocks_default; 42793f20c0fSAlexey Budankov } 428d3d1af6fSAlexey Budankov 429d3d1af6fSAlexey Budankov return 0; 430d3d1af6fSAlexey Budankov } 431d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */ 43293f20c0fSAlexey Budankov static int nr_cblocks_max = 0; 43393f20c0fSAlexey Budankov 434a5830532SJiri Olsa static int record__aio_push(struct record *rec __maybe_unused, struct mmap *map __maybe_unused, 435ef781128SAlexey Budankov off_t *off __maybe_unused) 436d3d1af6fSAlexey Budankov { 437d3d1af6fSAlexey Budankov return -1; 438d3d1af6fSAlexey Budankov } 439d3d1af6fSAlexey Budankov 440d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused) 441d3d1af6fSAlexey Budankov { 442d3d1af6fSAlexey Budankov return -1; 443d3d1af6fSAlexey Budankov } 444d3d1af6fSAlexey Budankov 445d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused) 446d3d1af6fSAlexey Budankov { 447d3d1af6fSAlexey Budankov } 448d3d1af6fSAlexey Budankov 449d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused) 450d3d1af6fSAlexey Budankov { 451d3d1af6fSAlexey Budankov } 452d3d1af6fSAlexey Budankov #endif 453d3d1af6fSAlexey Budankov 454d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec) 455d3d1af6fSAlexey Budankov { 456d3d1af6fSAlexey Budankov return rec->opts.nr_cblocks > 0; 457d3d1af6fSAlexey Budankov } 458d3d1af6fSAlexey Budankov 459470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1 460470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt, 461470530bbSAlexey Budankov const char *str, 462470530bbSAlexey Budankov int unset) 463470530bbSAlexey Budankov { 464470530bbSAlexey Budankov int flush_max; 465470530bbSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 466470530bbSAlexey Budankov static struct parse_tag tags[] = { 467470530bbSAlexey Budankov { .tag = 'B', .mult = 1 }, 468470530bbSAlexey Budankov { .tag = 'K', .mult = 1 << 10 }, 469470530bbSAlexey Budankov { .tag = 'M', .mult = 1 << 20 }, 470470530bbSAlexey Budankov { .tag = 'G', .mult = 1 << 30 }, 471470530bbSAlexey Budankov { .tag = 0 }, 472470530bbSAlexey Budankov }; 473470530bbSAlexey Budankov 474470530bbSAlexey Budankov if (unset) 475470530bbSAlexey Budankov return 0; 476470530bbSAlexey Budankov 477470530bbSAlexey Budankov if (str) { 478470530bbSAlexey Budankov opts->mmap_flush = parse_tag_value(str, tags); 479470530bbSAlexey Budankov if (opts->mmap_flush == (int)-1) 480470530bbSAlexey Budankov opts->mmap_flush = strtol(str, NULL, 0); 481470530bbSAlexey Budankov } 482470530bbSAlexey Budankov 483470530bbSAlexey Budankov if (!opts->mmap_flush) 484470530bbSAlexey Budankov opts->mmap_flush = MMAP_FLUSH_DEFAULT; 485470530bbSAlexey Budankov 4869521b5f2SJiri Olsa flush_max = evlist__mmap_size(opts->mmap_pages); 487470530bbSAlexey Budankov flush_max /= 4; 488470530bbSAlexey Budankov if (opts->mmap_flush > flush_max) 489470530bbSAlexey Budankov opts->mmap_flush = flush_max; 490470530bbSAlexey Budankov 491470530bbSAlexey Budankov return 0; 492470530bbSAlexey Budankov } 493470530bbSAlexey Budankov 494504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT 495504c1ad1SAlexey Budankov static unsigned int comp_level_default = 1; 496504c1ad1SAlexey Budankov 497504c1ad1SAlexey Budankov static int record__parse_comp_level(const struct option *opt, const char *str, int unset) 498504c1ad1SAlexey Budankov { 499504c1ad1SAlexey Budankov struct record_opts *opts = opt->value; 500504c1ad1SAlexey Budankov 501504c1ad1SAlexey Budankov if (unset) { 502504c1ad1SAlexey Budankov opts->comp_level = 0; 503504c1ad1SAlexey Budankov } else { 504504c1ad1SAlexey Budankov if (str) 505504c1ad1SAlexey Budankov opts->comp_level = strtol(str, NULL, 0); 506504c1ad1SAlexey Budankov if (!opts->comp_level) 507504c1ad1SAlexey Budankov opts->comp_level = comp_level_default; 508504c1ad1SAlexey Budankov } 509504c1ad1SAlexey Budankov 510504c1ad1SAlexey Budankov return 0; 511504c1ad1SAlexey Budankov } 512504c1ad1SAlexey Budankov #endif 51351255a8aSAlexey Budankov static unsigned int comp_level_max = 22; 51451255a8aSAlexey Budankov 51542e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec) 51642e1fd80SAlexey Budankov { 51742e1fd80SAlexey Budankov return rec->opts.comp_level > 0; 51842e1fd80SAlexey Budankov } 51942e1fd80SAlexey Budankov 52045694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 521d20deb64SArnaldo Carvalho de Melo union perf_event *event, 5221d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 5231d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 524234fbbf5SArnaldo Carvalho de Melo { 5258c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 526ded2b8feSJiri Olsa return record__write(rec, NULL, event, event->header.size); 527234fbbf5SArnaldo Carvalho de Melo } 528234fbbf5SArnaldo Carvalho de Melo 529d99c22eaSStephane Eranian static int process_locked_synthesized_event(struct perf_tool *tool, 530d99c22eaSStephane Eranian union perf_event *event, 531d99c22eaSStephane Eranian struct perf_sample *sample __maybe_unused, 532d99c22eaSStephane Eranian struct machine *machine __maybe_unused) 533d99c22eaSStephane Eranian { 534d99c22eaSStephane Eranian static pthread_mutex_t synth_lock = PTHREAD_MUTEX_INITIALIZER; 535d99c22eaSStephane Eranian int ret; 536d99c22eaSStephane Eranian 537d99c22eaSStephane Eranian pthread_mutex_lock(&synth_lock); 538d99c22eaSStephane Eranian ret = process_synthesized_event(tool, event, sample, machine); 539d99c22eaSStephane Eranian pthread_mutex_unlock(&synth_lock); 540d99c22eaSStephane Eranian return ret; 541d99c22eaSStephane Eranian } 542d99c22eaSStephane Eranian 543a5830532SJiri Olsa static int record__pushfn(struct mmap *map, void *to, void *bf, size_t size) 544d37f1586SArnaldo Carvalho de Melo { 545d37f1586SArnaldo Carvalho de Melo struct record *rec = to; 546d37f1586SArnaldo Carvalho de Melo 5475d7f4116SAlexey Budankov if (record__comp_enabled(rec)) { 548bf59b305SJiri Olsa size = zstd_compress(rec->session, map->data, mmap__mmap_len(map), bf, size); 5495d7f4116SAlexey Budankov bf = map->data; 5505d7f4116SAlexey Budankov } 5515d7f4116SAlexey Budankov 552d37f1586SArnaldo Carvalho de Melo rec->samples++; 553ded2b8feSJiri Olsa return record__write(rec, map, bf, size); 554d37f1586SArnaldo Carvalho de Melo } 555d37f1586SArnaldo Carvalho de Melo 5562dd6d8a1SAdrian Hunter static volatile int signr = -1; 5572dd6d8a1SAdrian Hunter static volatile int child_finished; 558da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 559da231338SAnand K Mistry static int done_fd = -1; 560da231338SAnand K Mistry #endif 561c0bdc1c4SWang Nan 5622dd6d8a1SAdrian Hunter static void sig_handler(int sig) 5632dd6d8a1SAdrian Hunter { 5642dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 5652dd6d8a1SAdrian Hunter child_finished = 1; 5662dd6d8a1SAdrian Hunter else 5672dd6d8a1SAdrian Hunter signr = sig; 5682dd6d8a1SAdrian Hunter 5692dd6d8a1SAdrian Hunter done = 1; 570da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 571da231338SAnand K Mistry { 572da231338SAnand K Mistry u64 tmp = 1; 573da231338SAnand K Mistry /* 574da231338SAnand K Mistry * It is possible for this signal handler to run after done is checked 575da231338SAnand K Mistry * in the main loop, but before the perf counter fds are polled. If this 576da231338SAnand K Mistry * happens, the poll() will continue to wait even though done is set, 577da231338SAnand K Mistry * and will only break out if either another signal is received, or the 578da231338SAnand K Mistry * counters are ready for read. To ensure the poll() doesn't sleep when 579da231338SAnand K Mistry * done is set, use an eventfd (done_fd) to wake up the poll(). 580da231338SAnand K Mistry */ 581da231338SAnand K Mistry if (write(done_fd, &tmp, sizeof(tmp)) < 0) 582da231338SAnand K Mistry pr_err("failed to signal wakeup fd, error: %m\n"); 583da231338SAnand K Mistry } 584da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT 5852dd6d8a1SAdrian Hunter } 5862dd6d8a1SAdrian Hunter 587a074865eSWang Nan static void sigsegv_handler(int sig) 588a074865eSWang Nan { 589a074865eSWang Nan perf_hooks__recover(); 590a074865eSWang Nan sighandler_dump_stack(sig); 591a074865eSWang Nan } 592a074865eSWang Nan 5932dd6d8a1SAdrian Hunter static void record__sig_exit(void) 5942dd6d8a1SAdrian Hunter { 5952dd6d8a1SAdrian Hunter if (signr == -1) 5962dd6d8a1SAdrian Hunter return; 5972dd6d8a1SAdrian Hunter 5982dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 5992dd6d8a1SAdrian Hunter raise(signr); 6002dd6d8a1SAdrian Hunter } 6012dd6d8a1SAdrian Hunter 602e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 603e31f0d01SAdrian Hunter 604ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 605a5830532SJiri Olsa struct mmap *map, 606ef149c25SAdrian Hunter union perf_event *event, void *data1, 607ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 608ef149c25SAdrian Hunter { 609ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 6108ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 611ef149c25SAdrian Hunter size_t padding; 612ef149c25SAdrian Hunter u8 pad[8] = {0}; 613ef149c25SAdrian Hunter 61446e201efSAdrian Hunter if (!perf_data__is_pipe(data) && perf_data__is_single_file(data)) { 61599fa2984SAdrian Hunter off_t file_offset; 6168ceb41d7SJiri Olsa int fd = perf_data__fd(data); 61799fa2984SAdrian Hunter int err; 61899fa2984SAdrian Hunter 61999fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 62099fa2984SAdrian Hunter if (file_offset == -1) 62199fa2984SAdrian Hunter return -1; 62299fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 62399fa2984SAdrian Hunter event, file_offset); 62499fa2984SAdrian Hunter if (err) 62599fa2984SAdrian Hunter return err; 62699fa2984SAdrian Hunter } 62799fa2984SAdrian Hunter 628ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 629ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 630ef149c25SAdrian Hunter if (padding) 631ef149c25SAdrian Hunter padding = 8 - padding; 632ef149c25SAdrian Hunter 633ded2b8feSJiri Olsa record__write(rec, map, event, event->header.size); 634ded2b8feSJiri Olsa record__write(rec, map, data1, len1); 635ef149c25SAdrian Hunter if (len2) 636ded2b8feSJiri Olsa record__write(rec, map, data2, len2); 637ded2b8feSJiri Olsa record__write(rec, map, &pad, padding); 638ef149c25SAdrian Hunter 639ef149c25SAdrian Hunter return 0; 640ef149c25SAdrian Hunter } 641ef149c25SAdrian Hunter 642ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 643a5830532SJiri Olsa struct mmap *map) 644ef149c25SAdrian Hunter { 645ef149c25SAdrian Hunter int ret; 646ef149c25SAdrian Hunter 647e035f4caSJiri Olsa ret = auxtrace_mmap__read(map, rec->itr, &rec->tool, 648ef149c25SAdrian Hunter record__process_auxtrace); 649ef149c25SAdrian Hunter if (ret < 0) 650ef149c25SAdrian Hunter return ret; 651ef149c25SAdrian Hunter 652ef149c25SAdrian Hunter if (ret) 653ef149c25SAdrian Hunter rec->samples++; 654ef149c25SAdrian Hunter 655ef149c25SAdrian Hunter return 0; 656ef149c25SAdrian Hunter } 657ef149c25SAdrian Hunter 6582dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 659a5830532SJiri Olsa struct mmap *map) 6602dd6d8a1SAdrian Hunter { 6612dd6d8a1SAdrian Hunter int ret; 6622dd6d8a1SAdrian Hunter 663e035f4caSJiri Olsa ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool, 6642dd6d8a1SAdrian Hunter record__process_auxtrace, 6652dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 6662dd6d8a1SAdrian Hunter if (ret < 0) 6672dd6d8a1SAdrian Hunter return ret; 6682dd6d8a1SAdrian Hunter 6692dd6d8a1SAdrian Hunter if (ret) 6702dd6d8a1SAdrian Hunter rec->samples++; 6712dd6d8a1SAdrian Hunter 6722dd6d8a1SAdrian Hunter return 0; 6732dd6d8a1SAdrian Hunter } 6742dd6d8a1SAdrian Hunter 6752dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 6762dd6d8a1SAdrian Hunter { 6772dd6d8a1SAdrian Hunter int i; 6782dd6d8a1SAdrian Hunter int rc = 0; 6792dd6d8a1SAdrian Hunter 680c976ee11SJiri Olsa for (i = 0; i < rec->evlist->core.nr_mmaps; i++) { 681a5830532SJiri Olsa struct mmap *map = &rec->evlist->mmap[i]; 6822dd6d8a1SAdrian Hunter 683e035f4caSJiri Olsa if (!map->auxtrace_mmap.base) 6842dd6d8a1SAdrian Hunter continue; 6852dd6d8a1SAdrian Hunter 686e035f4caSJiri Olsa if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) { 6872dd6d8a1SAdrian Hunter rc = -1; 6882dd6d8a1SAdrian Hunter goto out; 6892dd6d8a1SAdrian Hunter } 6902dd6d8a1SAdrian Hunter } 6912dd6d8a1SAdrian Hunter out: 6922dd6d8a1SAdrian Hunter return rc; 6932dd6d8a1SAdrian Hunter } 6942dd6d8a1SAdrian Hunter 695ce7b0e42SAlexander Shishkin static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit) 6962dd6d8a1SAdrian Hunter { 6972dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 6982dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 6995f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 7002dd6d8a1SAdrian Hunter } else { 701ce7b0e42SAlexander Shishkin if (auxtrace_record__snapshot_finish(rec->itr, on_exit)) 7025f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 7035f9cf599SWang Nan else 7045f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 7052dd6d8a1SAdrian Hunter } 7062dd6d8a1SAdrian Hunter } 7072dd6d8a1SAdrian Hunter 708ce7b0e42SAlexander Shishkin static int record__auxtrace_snapshot_exit(struct record *rec) 709ce7b0e42SAlexander Shishkin { 710ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger)) 711ce7b0e42SAlexander Shishkin return 0; 712ce7b0e42SAlexander Shishkin 713ce7b0e42SAlexander Shishkin if (!auxtrace_record__snapshot_started && 714ce7b0e42SAlexander Shishkin auxtrace_record__snapshot_start(rec->itr)) 715ce7b0e42SAlexander Shishkin return -1; 716ce7b0e42SAlexander Shishkin 717ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, true); 718ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger)) 719ce7b0e42SAlexander Shishkin return -1; 720ce7b0e42SAlexander Shishkin 721ce7b0e42SAlexander Shishkin return 0; 722ce7b0e42SAlexander Shishkin } 723ce7b0e42SAlexander Shishkin 7244b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec) 7254b5ea3bdSAdrian Hunter { 7264b5ea3bdSAdrian Hunter int err; 7274b5ea3bdSAdrian Hunter 7284b5ea3bdSAdrian Hunter if (!rec->itr) { 7294b5ea3bdSAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 7304b5ea3bdSAdrian Hunter if (err) 7314b5ea3bdSAdrian Hunter return err; 7324b5ea3bdSAdrian Hunter } 7334b5ea3bdSAdrian Hunter 7344b5ea3bdSAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 7354b5ea3bdSAdrian Hunter rec->opts.auxtrace_snapshot_opts); 7364b5ea3bdSAdrian Hunter if (err) 7374b5ea3bdSAdrian Hunter return err; 7384b5ea3bdSAdrian Hunter 739c0a6de06SAdrian Hunter err = auxtrace_parse_sample_options(rec->itr, rec->evlist, &rec->opts, 740c0a6de06SAdrian Hunter rec->opts.auxtrace_sample_opts); 741c0a6de06SAdrian Hunter if (err) 742c0a6de06SAdrian Hunter return err; 743c0a6de06SAdrian Hunter 744d58b3f7eSAdrian Hunter auxtrace_regroup_aux_output(rec->evlist); 745d58b3f7eSAdrian Hunter 7464b5ea3bdSAdrian Hunter return auxtrace_parse_filters(rec->evlist); 7474b5ea3bdSAdrian Hunter } 7484b5ea3bdSAdrian Hunter 749e31f0d01SAdrian Hunter #else 750e31f0d01SAdrian Hunter 751e31f0d01SAdrian Hunter static inline 752e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 753a5830532SJiri Olsa struct mmap *map __maybe_unused) 754e31f0d01SAdrian Hunter { 755e31f0d01SAdrian Hunter return 0; 756e31f0d01SAdrian Hunter } 757e31f0d01SAdrian Hunter 7582dd6d8a1SAdrian Hunter static inline 759ce7b0e42SAlexander Shishkin void record__read_auxtrace_snapshot(struct record *rec __maybe_unused, 760ce7b0e42SAlexander Shishkin bool on_exit __maybe_unused) 7612dd6d8a1SAdrian Hunter { 7622dd6d8a1SAdrian Hunter } 7632dd6d8a1SAdrian Hunter 7642dd6d8a1SAdrian Hunter static inline 7652dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 7662dd6d8a1SAdrian Hunter { 7672dd6d8a1SAdrian Hunter return 0; 7682dd6d8a1SAdrian Hunter } 7692dd6d8a1SAdrian Hunter 770ce7b0e42SAlexander Shishkin static inline 771ce7b0e42SAlexander Shishkin int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused) 772ce7b0e42SAlexander Shishkin { 773ce7b0e42SAlexander Shishkin return 0; 774ce7b0e42SAlexander Shishkin } 775ce7b0e42SAlexander Shishkin 7764b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused) 7774b5ea3bdSAdrian Hunter { 7784b5ea3bdSAdrian Hunter return 0; 7794b5ea3bdSAdrian Hunter } 7804b5ea3bdSAdrian Hunter 781e31f0d01SAdrian Hunter #endif 782e31f0d01SAdrian Hunter 783246eba8eSAdrian Hunter static int record__config_text_poke(struct evlist *evlist) 784246eba8eSAdrian Hunter { 785246eba8eSAdrian Hunter struct evsel *evsel; 786246eba8eSAdrian Hunter int err; 787246eba8eSAdrian Hunter 788246eba8eSAdrian Hunter /* Nothing to do if text poke is already configured */ 789246eba8eSAdrian Hunter evlist__for_each_entry(evlist, evsel) { 790246eba8eSAdrian Hunter if (evsel->core.attr.text_poke) 791246eba8eSAdrian Hunter return 0; 792246eba8eSAdrian Hunter } 793246eba8eSAdrian Hunter 794246eba8eSAdrian Hunter err = parse_events(evlist, "dummy:u", NULL); 795246eba8eSAdrian Hunter if (err) 796246eba8eSAdrian Hunter return err; 797246eba8eSAdrian Hunter 798246eba8eSAdrian Hunter evsel = evlist__last(evlist); 799246eba8eSAdrian Hunter 800246eba8eSAdrian Hunter evsel->core.attr.freq = 0; 801246eba8eSAdrian Hunter evsel->core.attr.sample_period = 1; 802246eba8eSAdrian Hunter evsel->core.attr.text_poke = 1; 803246eba8eSAdrian Hunter evsel->core.attr.ksymbol = 1; 804246eba8eSAdrian Hunter 805246eba8eSAdrian Hunter evsel->core.system_wide = true; 806246eba8eSAdrian Hunter evsel->no_aux_samples = true; 807246eba8eSAdrian Hunter evsel->immediate = true; 808246eba8eSAdrian Hunter 809246eba8eSAdrian Hunter /* Text poke must be collected on all CPUs */ 810246eba8eSAdrian Hunter perf_cpu_map__put(evsel->core.own_cpus); 811246eba8eSAdrian Hunter evsel->core.own_cpus = perf_cpu_map__new(NULL); 812246eba8eSAdrian Hunter perf_cpu_map__put(evsel->core.cpus); 813246eba8eSAdrian Hunter evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); 814246eba8eSAdrian Hunter 815246eba8eSAdrian Hunter evsel__set_sample_bit(evsel, TIME); 816246eba8eSAdrian Hunter 817246eba8eSAdrian Hunter return 0; 818246eba8eSAdrian Hunter } 819246eba8eSAdrian Hunter 820eeb399b5SAdrian Hunter static bool record__kcore_readable(struct machine *machine) 821eeb399b5SAdrian Hunter { 822eeb399b5SAdrian Hunter char kcore[PATH_MAX]; 823eeb399b5SAdrian Hunter int fd; 824eeb399b5SAdrian Hunter 825eeb399b5SAdrian Hunter scnprintf(kcore, sizeof(kcore), "%s/proc/kcore", machine->root_dir); 826eeb399b5SAdrian Hunter 827eeb399b5SAdrian Hunter fd = open(kcore, O_RDONLY); 828eeb399b5SAdrian Hunter if (fd < 0) 829eeb399b5SAdrian Hunter return false; 830eeb399b5SAdrian Hunter 831eeb399b5SAdrian Hunter close(fd); 832eeb399b5SAdrian Hunter 833eeb399b5SAdrian Hunter return true; 834eeb399b5SAdrian Hunter } 835eeb399b5SAdrian Hunter 836eeb399b5SAdrian Hunter static int record__kcore_copy(struct machine *machine, struct perf_data *data) 837eeb399b5SAdrian Hunter { 838eeb399b5SAdrian Hunter char from_dir[PATH_MAX]; 839eeb399b5SAdrian Hunter char kcore_dir[PATH_MAX]; 840eeb399b5SAdrian Hunter int ret; 841eeb399b5SAdrian Hunter 842eeb399b5SAdrian Hunter snprintf(from_dir, sizeof(from_dir), "%s/proc", machine->root_dir); 843eeb399b5SAdrian Hunter 844eeb399b5SAdrian Hunter ret = perf_data__make_kcore_dir(data, kcore_dir, sizeof(kcore_dir)); 845eeb399b5SAdrian Hunter if (ret) 846eeb399b5SAdrian Hunter return ret; 847eeb399b5SAdrian Hunter 848eeb399b5SAdrian Hunter return kcore_copy(from_dir, kcore_dir); 849eeb399b5SAdrian Hunter } 850eeb399b5SAdrian Hunter 851cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 85263503dbaSJiri Olsa struct evlist *evlist) 853cda57a8cSWang Nan { 854cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 855c0a6de06SAdrian Hunter bool auxtrace_overwrite = opts->auxtrace_snapshot_mode || 856c0a6de06SAdrian Hunter opts->auxtrace_sample_mode; 857cda57a8cSWang Nan char msg[512]; 858cda57a8cSWang Nan 859f13de660SAlexey Budankov if (opts->affinity != PERF_AFFINITY_SYS) 860f13de660SAlexey Budankov cpu__setup_cpunode_map(); 861f13de660SAlexey Budankov 8629521b5f2SJiri Olsa if (evlist__mmap_ex(evlist, opts->mmap_pages, 863cda57a8cSWang Nan opts->auxtrace_mmap_pages, 864c0a6de06SAdrian Hunter auxtrace_overwrite, 865470530bbSAlexey Budankov opts->nr_cblocks, opts->affinity, 86651255a8aSAlexey Budankov opts->mmap_flush, opts->comp_level) < 0) { 867cda57a8cSWang Nan if (errno == EPERM) { 868cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 869cda57a8cSWang Nan "Consider increasing " 870cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 871cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 872cda57a8cSWang Nan "(current value: %u,%u)\n", 873cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 874cda57a8cSWang Nan return -errno; 875cda57a8cSWang Nan } else { 876cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 877c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 878cda57a8cSWang Nan if (errno) 879cda57a8cSWang Nan return -errno; 880cda57a8cSWang Nan else 881cda57a8cSWang Nan return -EINVAL; 882cda57a8cSWang Nan } 883cda57a8cSWang Nan } 884cda57a8cSWang Nan return 0; 885cda57a8cSWang Nan } 886cda57a8cSWang Nan 887cda57a8cSWang Nan static int record__mmap(struct record *rec) 888cda57a8cSWang Nan { 889cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 890cda57a8cSWang Nan } 891cda57a8cSWang Nan 8928c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 893dd7927f4SArnaldo Carvalho de Melo { 894d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 89532dcd021SJiri Olsa struct evsel *pos; 89663503dbaSJiri Olsa struct evlist *evlist = rec->evlist; 897d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 898b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 8998d3eca20SDavid Ahern int rc = 0; 900dd7927f4SArnaldo Carvalho de Melo 901d3dbf43cSArnaldo Carvalho de Melo /* 902b91e5492SKan Liang * For initial_delay, system wide or a hybrid system, we need to add a 903b91e5492SKan Liang * dummy event so that we can track PERF_RECORD_MMAP to cover the delay 904b91e5492SKan Liang * of waiting or event synthesis. 905d3dbf43cSArnaldo Carvalho de Melo */ 906b91e5492SKan Liang if (opts->initial_delay || target__has_cpu(&opts->target) || 907b91e5492SKan Liang perf_pmu__has_hybrid()) { 908e80db255SArnaldo Carvalho de Melo pos = evlist__get_tracking_event(evlist); 909442ad225SAdrian Hunter if (!evsel__is_dummy_event(pos)) { 910442ad225SAdrian Hunter /* Set up dummy event. */ 911e251abeeSArnaldo Carvalho de Melo if (evlist__add_dummy(evlist)) 912d3dbf43cSArnaldo Carvalho de Melo return -ENOMEM; 913515dbe48SJiri Olsa pos = evlist__last(evlist); 914e80db255SArnaldo Carvalho de Melo evlist__set_tracking_event(evlist, pos); 915442ad225SAdrian Hunter } 916442ad225SAdrian Hunter 9170a892c1cSIan Rogers /* 9180a892c1cSIan Rogers * Enable the dummy event when the process is forked for 9190a892c1cSIan Rogers * initial_delay, immediately for system wide. 9200a892c1cSIan Rogers */ 921bb07d62eSNamhyung Kim if (opts->initial_delay && !pos->immediate && 922bb07d62eSNamhyung Kim !target__has_cpu(&opts->target)) 9231fc632ceSJiri Olsa pos->core.attr.enable_on_exec = 1; 9240a892c1cSIan Rogers else 9250a892c1cSIan Rogers pos->immediate = 1; 926d3dbf43cSArnaldo Carvalho de Melo } 927d3dbf43cSArnaldo Carvalho de Melo 92878e1bc25SArnaldo Carvalho de Melo evlist__config(evlist, opts, &callchain_param); 929cac21425SJiri Olsa 930e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 9313da297a6SIngo Molnar try_again: 932af663bd0SJiri Olsa if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) { 933ae430892SArnaldo Carvalho de Melo if (evsel__fallback(pos, errno, msg, sizeof(msg))) { 934bb963e16SNamhyung Kim if (verbose > 0) 935c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 9363da297a6SIngo Molnar goto try_again; 9373da297a6SIngo Molnar } 938cf99ad14SAndi Kleen if ((errno == EINVAL || errno == EBADF) && 939fba7c866SJiri Olsa pos->core.leader != &pos->core && 940cf99ad14SAndi Kleen pos->weak_group) { 94164b4778bSArnaldo Carvalho de Melo pos = evlist__reset_weak_group(evlist, pos, true); 942cf99ad14SAndi Kleen goto try_again; 943cf99ad14SAndi Kleen } 94456e52e85SArnaldo Carvalho de Melo rc = -errno; 9452bb72dbbSArnaldo Carvalho de Melo evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg)); 94656e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 9478d3eca20SDavid Ahern goto out; 9487c6a1c65SPeter Zijlstra } 949bfd8f72cSAndi Kleen 950bfd8f72cSAndi Kleen pos->supported = true; 9517c6a1c65SPeter Zijlstra } 9527c6a1c65SPeter Zijlstra 95378e1bc25SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict && !evlist__exclude_kernel(evlist)) { 954c8b567c8SArnaldo Carvalho de Melo pr_warning( 955c8b567c8SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 956c8b567c8SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n" 957c8b567c8SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 958c8b567c8SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 959c8b567c8SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 960c8b567c8SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 961c8b567c8SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 962c8b567c8SArnaldo Carvalho de Melo } 963c8b567c8SArnaldo Carvalho de Melo 96424bf91a7SArnaldo Carvalho de Melo if (evlist__apply_filters(evlist, &pos)) { 96562d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 9668ab2e96dSArnaldo Carvalho de Melo pos->filter, evsel__name(pos), errno, 967c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 9688d3eca20SDavid Ahern rc = -1; 9698d3eca20SDavid Ahern goto out; 9700a102479SFrederic Weisbecker } 9710a102479SFrederic Weisbecker 972cda57a8cSWang Nan rc = record__mmap(rec); 973cda57a8cSWang Nan if (rc) 9748d3eca20SDavid Ahern goto out; 9750a27d7f9SArnaldo Carvalho de Melo 976a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 9777b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 9788d3eca20SDavid Ahern out: 9798d3eca20SDavid Ahern return rc; 980a91e5431SArnaldo Carvalho de Melo } 981a91e5431SArnaldo Carvalho de Melo 98266286ed3SAdrian Hunter static void set_timestamp_boundary(struct record *rec, u64 sample_time) 98366286ed3SAdrian Hunter { 98466286ed3SAdrian Hunter if (rec->evlist->first_sample_time == 0) 98566286ed3SAdrian Hunter rec->evlist->first_sample_time = sample_time; 98666286ed3SAdrian Hunter 98766286ed3SAdrian Hunter if (sample_time) 98866286ed3SAdrian Hunter rec->evlist->last_sample_time = sample_time; 98966286ed3SAdrian Hunter } 99066286ed3SAdrian Hunter 991e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 992e3d59112SNamhyung Kim union perf_event *event, 993e3d59112SNamhyung Kim struct perf_sample *sample, 99432dcd021SJiri Olsa struct evsel *evsel, 995e3d59112SNamhyung Kim struct machine *machine) 996e3d59112SNamhyung Kim { 997e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 998e3d59112SNamhyung Kim 99966286ed3SAdrian Hunter set_timestamp_boundary(rec, sample->time); 100068588bafSJin Yao 100168588bafSJin Yao if (rec->buildid_all) 100268588bafSJin Yao return 0; 100368588bafSJin Yao 100468588bafSJin Yao rec->samples++; 1005e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 1006e3d59112SNamhyung Kim } 1007e3d59112SNamhyung Kim 10088c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 10096122e4e4SArnaldo Carvalho de Melo { 1010f5fc1412SJiri Olsa struct perf_session *session = rec->session; 10116122e4e4SArnaldo Carvalho de Melo 101245112e89SJiri Olsa if (perf_data__size(&rec->data) == 0) 10139f591fd7SArnaldo Carvalho de Melo return 0; 10149f591fd7SArnaldo Carvalho de Melo 101500dc8657SNamhyung Kim /* 101600dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 101700dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 101800dc8657SNamhyung Kim * we prefer the vmlinux path like 101900dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 102000dc8657SNamhyung Kim * 102100dc8657SNamhyung Kim * rather than build-id path (in debug directory). 102200dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 102300dc8657SNamhyung Kim */ 102400dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 102500dc8657SNamhyung Kim 10266156681bSNamhyung Kim /* 10276156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 102868588bafSJin Yao * so no need to process samples. But if timestamp_boundary is enabled, 102968588bafSJin Yao * it still needs to walk on all samples to get the timestamps of 103068588bafSJin Yao * first/last samples. 10316156681bSNamhyung Kim */ 103268588bafSJin Yao if (rec->buildid_all && !rec->timestamp_boundary) 10336156681bSNamhyung Kim rec->tool.sample = NULL; 10346156681bSNamhyung Kim 1035b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 10366122e4e4SArnaldo Carvalho de Melo } 10376122e4e4SArnaldo Carvalho de Melo 10388115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 1039a1645ce1SZhang, Yanmin { 1040a1645ce1SZhang, Yanmin int err; 104145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 1042a1645ce1SZhang, Yanmin /* 1043a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 1044a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 1045a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 1046a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 1047a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 1048a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 1049a1645ce1SZhang, Yanmin */ 105045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 1051743eb868SArnaldo Carvalho de Melo machine); 1052a1645ce1SZhang, Yanmin if (err < 0) 1053a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 105423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 1055a1645ce1SZhang, Yanmin 1056a1645ce1SZhang, Yanmin /* 1057a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 1058a1645ce1SZhang, Yanmin * have no _text sometimes. 1059a1645ce1SZhang, Yanmin */ 106045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 10610ae617beSAdrian Hunter machine); 1062a1645ce1SZhang, Yanmin if (err < 0) 1063a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 106423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 1065a1645ce1SZhang, Yanmin } 1066a1645ce1SZhang, Yanmin 106798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 106898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 106998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 107098402807SFrederic Weisbecker }; 107198402807SFrederic Weisbecker 1072a5830532SJiri Olsa static void record__adjust_affinity(struct record *rec, struct mmap *map) 1073f13de660SAlexey Budankov { 1074f13de660SAlexey Budankov if (rec->opts.affinity != PERF_AFFINITY_SYS && 10758384a260SAlexey Budankov !bitmap_equal(rec->affinity_mask.bits, map->affinity_mask.bits, 10768384a260SAlexey Budankov rec->affinity_mask.nbits)) { 10778384a260SAlexey Budankov bitmap_zero(rec->affinity_mask.bits, rec->affinity_mask.nbits); 10788384a260SAlexey Budankov bitmap_or(rec->affinity_mask.bits, rec->affinity_mask.bits, 10798384a260SAlexey Budankov map->affinity_mask.bits, rec->affinity_mask.nbits); 10808384a260SAlexey Budankov sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&rec->affinity_mask), 10818384a260SAlexey Budankov (cpu_set_t *)rec->affinity_mask.bits); 10828384a260SAlexey Budankov if (verbose == 2) 10838384a260SAlexey Budankov mmap_cpu_mask__scnprintf(&rec->affinity_mask, "thread"); 1084f13de660SAlexey Budankov } 1085f13de660SAlexey Budankov } 1086f13de660SAlexey Budankov 10875d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment) 10885d7f4116SAlexey Budankov { 108972932371SJiri Olsa struct perf_record_compressed *event = record; 10905d7f4116SAlexey Budankov size_t size = sizeof(*event); 10915d7f4116SAlexey Budankov 10925d7f4116SAlexey Budankov if (increment) { 10935d7f4116SAlexey Budankov event->header.size += increment; 10945d7f4116SAlexey Budankov return increment; 10955d7f4116SAlexey Budankov } 10965d7f4116SAlexey Budankov 10975d7f4116SAlexey Budankov event->header.type = PERF_RECORD_COMPRESSED; 10985d7f4116SAlexey Budankov event->header.size = size; 10995d7f4116SAlexey Budankov 11005d7f4116SAlexey Budankov return size; 11015d7f4116SAlexey Budankov } 11025d7f4116SAlexey Budankov 11035d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 11045d7f4116SAlexey Budankov void *src, size_t src_size) 11055d7f4116SAlexey Budankov { 11065d7f4116SAlexey Budankov size_t compressed; 110772932371SJiri Olsa size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1; 11085d7f4116SAlexey Budankov 11095d7f4116SAlexey Budankov compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size, 11105d7f4116SAlexey Budankov max_record_size, process_comp_header); 11115d7f4116SAlexey Budankov 11125d7f4116SAlexey Budankov session->bytes_transferred += src_size; 11135d7f4116SAlexey Budankov session->bytes_compressed += compressed; 11145d7f4116SAlexey Budankov 11155d7f4116SAlexey Budankov return compressed; 11165d7f4116SAlexey Budankov } 11175d7f4116SAlexey Budankov 111863503dbaSJiri Olsa static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist, 1119470530bbSAlexey Budankov bool overwrite, bool synch) 112098402807SFrederic Weisbecker { 1121dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 11220e2e63ddSPeter Zijlstra int i; 11238d3eca20SDavid Ahern int rc = 0; 1124a5830532SJiri Olsa struct mmap *maps; 1125d3d1af6fSAlexey Budankov int trace_fd = rec->data.file.fd; 1126ef781128SAlexey Budankov off_t off = 0; 112798402807SFrederic Weisbecker 1128cb21686bSWang Nan if (!evlist) 1129cb21686bSWang Nan return 0; 1130ef149c25SAdrian Hunter 11310b72d69aSWang Nan maps = overwrite ? evlist->overwrite_mmap : evlist->mmap; 1132a4ea0ec4SWang Nan if (!maps) 1133a4ea0ec4SWang Nan return 0; 1134cb21686bSWang Nan 11350b72d69aSWang Nan if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 113654cc54deSWang Nan return 0; 113754cc54deSWang Nan 1138d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 1139d3d1af6fSAlexey Budankov off = record__aio_get_pos(trace_fd); 1140d3d1af6fSAlexey Budankov 1141c976ee11SJiri Olsa for (i = 0; i < evlist->core.nr_mmaps; i++) { 1142470530bbSAlexey Budankov u64 flush = 0; 1143a5830532SJiri Olsa struct mmap *map = &maps[i]; 1144a4ea0ec4SWang Nan 1145547740f7SJiri Olsa if (map->core.base) { 1146f13de660SAlexey Budankov record__adjust_affinity(rec, map); 1147470530bbSAlexey Budankov if (synch) { 114865aa2e6bSJiri Olsa flush = map->core.flush; 114965aa2e6bSJiri Olsa map->core.flush = 1; 1150470530bbSAlexey Budankov } 1151d3d1af6fSAlexey Budankov if (!record__aio_enabled(rec)) { 1152ef781128SAlexey Budankov if (perf_mmap__push(map, rec, record__pushfn) < 0) { 1153470530bbSAlexey Budankov if (synch) 115465aa2e6bSJiri Olsa map->core.flush = flush; 11558d3eca20SDavid Ahern rc = -1; 11568d3eca20SDavid Ahern goto out; 11578d3eca20SDavid Ahern } 1158d3d1af6fSAlexey Budankov } else { 1159ef781128SAlexey Budankov if (record__aio_push(rec, map, &off) < 0) { 1160d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 1161470530bbSAlexey Budankov if (synch) 116265aa2e6bSJiri Olsa map->core.flush = flush; 1163d3d1af6fSAlexey Budankov rc = -1; 1164d3d1af6fSAlexey Budankov goto out; 1165d3d1af6fSAlexey Budankov } 1166d3d1af6fSAlexey Budankov } 1167470530bbSAlexey Budankov if (synch) 116865aa2e6bSJiri Olsa map->core.flush = flush; 11698d3eca20SDavid Ahern } 1170ef149c25SAdrian Hunter 1171e035f4caSJiri Olsa if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode && 1172c0a6de06SAdrian Hunter !rec->opts.auxtrace_sample_mode && 1173e035f4caSJiri Olsa record__auxtrace_mmap_read(rec, map) != 0) { 1174ef149c25SAdrian Hunter rc = -1; 1175ef149c25SAdrian Hunter goto out; 1176ef149c25SAdrian Hunter } 117798402807SFrederic Weisbecker } 117898402807SFrederic Weisbecker 1179d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 1180d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 1181d3d1af6fSAlexey Budankov 1182dcabb507SJiri Olsa /* 1183dcabb507SJiri Olsa * Mark the round finished in case we wrote 1184dcabb507SJiri Olsa * at least one event. 1185dcabb507SJiri Olsa */ 1186dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 1187ded2b8feSJiri Olsa rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event)); 11888d3eca20SDavid Ahern 11890b72d69aSWang Nan if (overwrite) 1190ade9d208SArnaldo Carvalho de Melo evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 11918d3eca20SDavid Ahern out: 11928d3eca20SDavid Ahern return rc; 119398402807SFrederic Weisbecker } 119498402807SFrederic Weisbecker 1195470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch) 1196cb21686bSWang Nan { 1197cb21686bSWang Nan int err; 1198cb21686bSWang Nan 1199470530bbSAlexey Budankov err = record__mmap_read_evlist(rec, rec->evlist, false, synch); 1200cb21686bSWang Nan if (err) 1201cb21686bSWang Nan return err; 1202cb21686bSWang Nan 1203470530bbSAlexey Budankov return record__mmap_read_evlist(rec, rec->evlist, true, synch); 1204cb21686bSWang Nan } 1205cb21686bSWang Nan 12068c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 120757706abcSDavid Ahern { 120857706abcSDavid Ahern struct perf_session *session = rec->session; 120957706abcSDavid Ahern int feat; 121057706abcSDavid Ahern 121157706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 121257706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 121357706abcSDavid Ahern 121457706abcSDavid Ahern if (rec->no_buildid) 121557706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 121657706abcSDavid Ahern 1217ce9036a6SJiri Olsa if (!have_tracepoints(&rec->evlist->core.entries)) 121857706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 121957706abcSDavid Ahern 122057706abcSDavid Ahern if (!rec->opts.branch_stack) 122157706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 1222ef149c25SAdrian Hunter 1223ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 1224ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 1225ffa517adSJiri Olsa 1226cf790516SAlexey Budankov if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 1227cf790516SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_CLOCKID); 1228cf790516SAlexey Budankov 1229d1e325cfSJiri Olsa if (!rec->opts.use_clockid) 1230d1e325cfSJiri Olsa perf_header__clear_feat(&session->header, HEADER_CLOCK_DATA); 1231d1e325cfSJiri Olsa 1232258031c0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); 123342e1fd80SAlexey Budankov if (!record__comp_enabled(rec)) 123442e1fd80SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_COMPRESSED); 1235258031c0SJiri Olsa 1236ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 123757706abcSDavid Ahern } 123857706abcSDavid Ahern 1239e1ab48baSWang Nan static void 1240e1ab48baSWang Nan record__finish_output(struct record *rec) 1241e1ab48baSWang Nan { 12428ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 12438ceb41d7SJiri Olsa int fd = perf_data__fd(data); 1244e1ab48baSWang Nan 12458ceb41d7SJiri Olsa if (data->is_pipe) 1246e1ab48baSWang Nan return; 1247e1ab48baSWang Nan 1248e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 124945112e89SJiri Olsa data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR); 1250e1ab48baSWang Nan 1251e1ab48baSWang Nan if (!rec->no_buildid) { 1252e1ab48baSWang Nan process_buildids(rec); 1253e1ab48baSWang Nan 1254e1ab48baSWang Nan if (rec->buildid_all) 1255e1ab48baSWang Nan dsos__hit_all(rec->session); 1256e1ab48baSWang Nan } 1257e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 1258e1ab48baSWang Nan 1259e1ab48baSWang Nan return; 1260e1ab48baSWang Nan } 1261e1ab48baSWang Nan 12624ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 1263be7b0c9eSWang Nan { 12649d6aae72SArnaldo Carvalho de Melo int err; 12659749b90eSJiri Olsa struct perf_thread_map *thread_map; 126641b740b6SNamhyung Kim bool needs_mmap = rec->opts.synth & PERF_SYNTH_MMAP; 1267be7b0c9eSWang Nan 12684ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 12694ea648aeSWang Nan return 0; 12704ea648aeSWang Nan 12719d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 12729d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL) 12739d6aae72SArnaldo Carvalho de Melo return -1; 12749d6aae72SArnaldo Carvalho de Melo 12759d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 1276be7b0c9eSWang Nan process_synthesized_event, 1277be7b0c9eSWang Nan &rec->session->machines.host, 127841b740b6SNamhyung Kim needs_mmap, 12793fcb10e4SMark Drayton rec->opts.sample_address); 12807836e52eSJiri Olsa perf_thread_map__put(thread_map); 12819d6aae72SArnaldo Carvalho de Melo return err; 1282be7b0c9eSWang Nan } 1283be7b0c9eSWang Nan 12844ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 12853c1cb7e3SWang Nan 1286ecfd7a9cSWang Nan static int 1287ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 1288ecfd7a9cSWang Nan { 12898ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1290ecfd7a9cSWang Nan int fd, err; 129103724b2eSAndi Kleen char *new_filename; 1292ecfd7a9cSWang Nan 1293ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 1294ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 1295ecfd7a9cSWang Nan 1296d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 1297d3d1af6fSAlexey Budankov 12984ea648aeSWang Nan record__synthesize(rec, true); 12994ea648aeSWang Nan if (target__none(&rec->opts.target)) 13004ea648aeSWang Nan record__synthesize_workload(rec, true); 13014ea648aeSWang Nan 1302ecfd7a9cSWang Nan rec->samples = 0; 1303ecfd7a9cSWang Nan record__finish_output(rec); 1304ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 1305ecfd7a9cSWang Nan if (err) { 1306ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 1307ecfd7a9cSWang Nan return -EINVAL; 1308ecfd7a9cSWang Nan } 1309ecfd7a9cSWang Nan 13108ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp, 1311ecfd7a9cSWang Nan rec->session->header.data_offset, 131203724b2eSAndi Kleen at_exit, &new_filename); 1313ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 1314ecfd7a9cSWang Nan rec->bytes_written = 0; 1315ecfd7a9cSWang Nan rec->session->header.data_size = 0; 1316ecfd7a9cSWang Nan } 1317ecfd7a9cSWang Nan 1318ecfd7a9cSWang Nan if (!quiet) 1319ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 13202d4f2799SJiri Olsa data->path, timestamp); 13213c1cb7e3SWang Nan 132203724b2eSAndi Kleen if (rec->switch_output.num_files) { 132303724b2eSAndi Kleen int n = rec->switch_output.cur_file + 1; 132403724b2eSAndi Kleen 132503724b2eSAndi Kleen if (n >= rec->switch_output.num_files) 132603724b2eSAndi Kleen n = 0; 132703724b2eSAndi Kleen rec->switch_output.cur_file = n; 132803724b2eSAndi Kleen if (rec->switch_output.filenames[n]) { 132903724b2eSAndi Kleen remove(rec->switch_output.filenames[n]); 1330d8f9da24SArnaldo Carvalho de Melo zfree(&rec->switch_output.filenames[n]); 133103724b2eSAndi Kleen } 133203724b2eSAndi Kleen rec->switch_output.filenames[n] = new_filename; 133303724b2eSAndi Kleen } else { 133403724b2eSAndi Kleen free(new_filename); 133503724b2eSAndi Kleen } 133603724b2eSAndi Kleen 13373c1cb7e3SWang Nan /* Output tracking events */ 1338be7b0c9eSWang Nan if (!at_exit) { 13394ea648aeSWang Nan record__synthesize(rec, false); 13403c1cb7e3SWang Nan 1341be7b0c9eSWang Nan /* 1342be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 1343be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 1344be7b0c9eSWang Nan * generate tracking events because there's no thread_map 1345be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 1346be7b0c9eSWang Nan * contain map and comm information. 1347be7b0c9eSWang Nan * Create a fake thread_map and directly call 1348be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 1349be7b0c9eSWang Nan */ 1350be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 13514ea648aeSWang Nan record__synthesize_workload(rec, false); 1352be7b0c9eSWang Nan } 1353ecfd7a9cSWang Nan return fd; 1354ecfd7a9cSWang Nan } 1355ecfd7a9cSWang Nan 1356f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 1357f33cbe72SArnaldo Carvalho de Melo 1358f33cbe72SArnaldo Carvalho de Melo /* 13597b392ef0SArnaldo Carvalho de Melo * evlist__prepare_workload will send a SIGUSR1 1360f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 1361f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 1362f33cbe72SArnaldo Carvalho de Melo */ 136345604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 136445604710SNamhyung Kim siginfo_t *info, 1365f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 1366f33cbe72SArnaldo Carvalho de Melo { 1367f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 1368f33cbe72SArnaldo Carvalho de Melo done = 1; 1369f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 1370f33cbe72SArnaldo Carvalho de Melo } 1371f33cbe72SArnaldo Carvalho de Melo 13722dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 1373bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig); 13742dd6d8a1SAdrian Hunter 1375db0ea13cSArnaldo Carvalho de Melo static const struct perf_event_mmap_page *evlist__pick_pc(struct evlist *evlist) 1376ee667f94SWang Nan { 1377b2cb615dSWang Nan if (evlist) { 1378547740f7SJiri Olsa if (evlist->mmap && evlist->mmap[0].core.base) 1379547740f7SJiri Olsa return evlist->mmap[0].core.base; 1380547740f7SJiri Olsa if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].core.base) 1381547740f7SJiri Olsa return evlist->overwrite_mmap[0].core.base; 1382b2cb615dSWang Nan } 1383ee667f94SWang Nan return NULL; 1384ee667f94SWang Nan } 1385ee667f94SWang Nan 1386c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 1387c45628b0SWang Nan { 1388db0ea13cSArnaldo Carvalho de Melo const struct perf_event_mmap_page *pc = evlist__pick_pc(rec->evlist); 1389ee667f94SWang Nan if (pc) 1390ee667f94SWang Nan return pc; 1391c45628b0SWang Nan return NULL; 1392c45628b0SWang Nan } 1393c45628b0SWang Nan 13944ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 1395c45c86ebSWang Nan { 1396c45c86ebSWang Nan struct perf_session *session = rec->session; 1397c45c86ebSWang Nan struct machine *machine = &session->machines.host; 13988ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1399c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 1400c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 1401c45c86ebSWang Nan int err = 0; 1402d99c22eaSStephane Eranian event_op f = process_synthesized_event; 1403c45c86ebSWang Nan 14044ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 14054ea648aeSWang Nan return 0; 14064ea648aeSWang Nan 14078ceb41d7SJiri Olsa if (data->is_pipe) { 1408c3a057dcSNamhyung Kim err = perf_event__synthesize_for_pipe(tool, session, data, 1409c45c86ebSWang Nan process_synthesized_event); 1410c3a057dcSNamhyung Kim if (err < 0) 1411c45c86ebSWang Nan goto out; 1412c45c86ebSWang Nan 1413c45c86ebSWang Nan rec->bytes_written += err; 1414c45c86ebSWang Nan } 1415c45c86ebSWang Nan 1416c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 141746bc29b9SAdrian Hunter process_synthesized_event, machine); 141846bc29b9SAdrian Hunter if (err) 141946bc29b9SAdrian Hunter goto out; 142046bc29b9SAdrian Hunter 1421c0a6de06SAdrian Hunter /* Synthesize id_index before auxtrace_info */ 142261750473SAdrian Hunter if (rec->opts.auxtrace_sample_mode || rec->opts.full_auxtrace) { 1423c0a6de06SAdrian Hunter err = perf_event__synthesize_id_index(tool, 1424c0a6de06SAdrian Hunter process_synthesized_event, 1425c0a6de06SAdrian Hunter session->evlist, machine); 1426c0a6de06SAdrian Hunter if (err) 1427c0a6de06SAdrian Hunter goto out; 1428c0a6de06SAdrian Hunter } 1429c0a6de06SAdrian Hunter 1430c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 1431c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 1432c45c86ebSWang Nan session, process_synthesized_event); 1433c45c86ebSWang Nan if (err) 1434c45c86ebSWang Nan goto out; 1435c45c86ebSWang Nan } 1436c45c86ebSWang Nan 143778e1bc25SArnaldo Carvalho de Melo if (!evlist__exclude_kernel(rec->evlist)) { 1438c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 1439c45c86ebSWang Nan machine); 1440c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 1441c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1442c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 1443c45c86ebSWang Nan 1444c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 1445c45c86ebSWang Nan machine); 1446c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 1447c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1448c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 14496c443954SArnaldo Carvalho de Melo } 1450c45c86ebSWang Nan 1451c45c86ebSWang Nan if (perf_guest) { 1452c45c86ebSWang Nan machines__process_guests(&session->machines, 1453c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 1454c45c86ebSWang Nan } 1455c45c86ebSWang Nan 1456bfd8f72cSAndi Kleen err = perf_event__synthesize_extra_attr(&rec->tool, 1457bfd8f72cSAndi Kleen rec->evlist, 1458bfd8f72cSAndi Kleen process_synthesized_event, 1459bfd8f72cSAndi Kleen data->is_pipe); 1460bfd8f72cSAndi Kleen if (err) 1461bfd8f72cSAndi Kleen goto out; 1462bfd8f72cSAndi Kleen 146303617c22SJiri Olsa err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads, 1464373565d2SAndi Kleen process_synthesized_event, 1465373565d2SAndi Kleen NULL); 1466373565d2SAndi Kleen if (err < 0) { 1467373565d2SAndi Kleen pr_err("Couldn't synthesize thread map.\n"); 1468373565d2SAndi Kleen return err; 1469373565d2SAndi Kleen } 1470373565d2SAndi Kleen 1471f72f901dSJiri Olsa err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus, 1472373565d2SAndi Kleen process_synthesized_event, NULL); 1473373565d2SAndi Kleen if (err < 0) { 1474373565d2SAndi Kleen pr_err("Couldn't synthesize cpu map.\n"); 1475373565d2SAndi Kleen return err; 1476373565d2SAndi Kleen } 1477373565d2SAndi Kleen 1478e5416950SSong Liu err = perf_event__synthesize_bpf_events(session, process_synthesized_event, 14797b612e29SSong Liu machine, opts); 14807b612e29SSong Liu if (err < 0) 14817b612e29SSong Liu pr_warning("Couldn't synthesize bpf events.\n"); 14827b612e29SSong Liu 148341b740b6SNamhyung Kim if (rec->opts.synth & PERF_SYNTH_CGROUP) { 1484ab64069fSNamhyung Kim err = perf_event__synthesize_cgroups(tool, process_synthesized_event, 1485ab64069fSNamhyung Kim machine); 1486ab64069fSNamhyung Kim if (err < 0) 1487ab64069fSNamhyung Kim pr_warning("Couldn't synthesize cgroup events.\n"); 148841b740b6SNamhyung Kim } 1489ab64069fSNamhyung Kim 1490d99c22eaSStephane Eranian if (rec->opts.nr_threads_synthesize > 1) { 1491d99c22eaSStephane Eranian perf_set_multithreaded(); 1492d99c22eaSStephane Eranian f = process_locked_synthesized_event; 1493d99c22eaSStephane Eranian } 1494d99c22eaSStephane Eranian 149541b740b6SNamhyung Kim if (rec->opts.synth & PERF_SYNTH_TASK) { 149641b740b6SNamhyung Kim bool needs_mmap = rec->opts.synth & PERF_SYNTH_MMAP; 149741b740b6SNamhyung Kim 149884111b9cSNamhyung Kim err = __machine__synthesize_threads(machine, tool, &opts->target, 149984111b9cSNamhyung Kim rec->evlist->core.threads, 150041b740b6SNamhyung Kim f, needs_mmap, opts->sample_address, 1501d99c22eaSStephane Eranian rec->opts.nr_threads_synthesize); 150241b740b6SNamhyung Kim } 1503d99c22eaSStephane Eranian 1504d99c22eaSStephane Eranian if (rec->opts.nr_threads_synthesize > 1) 1505d99c22eaSStephane Eranian perf_set_singlethreaded(); 1506d99c22eaSStephane Eranian 1507c45c86ebSWang Nan out: 1508c45c86ebSWang Nan return err; 1509c45c86ebSWang Nan } 1510c45c86ebSWang Nan 1511899e5ffbSArnaldo Carvalho de Melo static int record__process_signal_event(union perf_event *event __maybe_unused, void *data) 1512899e5ffbSArnaldo Carvalho de Melo { 1513899e5ffbSArnaldo Carvalho de Melo struct record *rec = data; 1514899e5ffbSArnaldo Carvalho de Melo pthread_kill(rec->thread_id, SIGUSR2); 1515899e5ffbSArnaldo Carvalho de Melo return 0; 1516899e5ffbSArnaldo Carvalho de Melo } 1517899e5ffbSArnaldo Carvalho de Melo 151823cbb41cSArnaldo Carvalho de Melo static int record__setup_sb_evlist(struct record *rec) 151923cbb41cSArnaldo Carvalho de Melo { 152023cbb41cSArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 152123cbb41cSArnaldo Carvalho de Melo 152223cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist != NULL) { 152323cbb41cSArnaldo Carvalho de Melo /* 152423cbb41cSArnaldo Carvalho de Melo * We get here if --switch-output-event populated the 152523cbb41cSArnaldo Carvalho de Melo * sb_evlist, so associate a callback that will send a SIGUSR2 152623cbb41cSArnaldo Carvalho de Melo * to the main thread. 152723cbb41cSArnaldo Carvalho de Melo */ 152823cbb41cSArnaldo Carvalho de Melo evlist__set_cb(rec->sb_evlist, record__process_signal_event, rec); 152923cbb41cSArnaldo Carvalho de Melo rec->thread_id = pthread_self(); 153023cbb41cSArnaldo Carvalho de Melo } 15311101c872SJin Yao #ifdef HAVE_LIBBPF_SUPPORT 153223cbb41cSArnaldo Carvalho de Melo if (!opts->no_bpf_event) { 153323cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist == NULL) { 153423cbb41cSArnaldo Carvalho de Melo rec->sb_evlist = evlist__new(); 153523cbb41cSArnaldo Carvalho de Melo 153623cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist == NULL) { 153723cbb41cSArnaldo Carvalho de Melo pr_err("Couldn't create side band evlist.\n."); 153823cbb41cSArnaldo Carvalho de Melo return -1; 153923cbb41cSArnaldo Carvalho de Melo } 154023cbb41cSArnaldo Carvalho de Melo } 154123cbb41cSArnaldo Carvalho de Melo 154223cbb41cSArnaldo Carvalho de Melo if (evlist__add_bpf_sb_event(rec->sb_evlist, &rec->session->header.env)) { 154323cbb41cSArnaldo Carvalho de Melo pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n."); 154423cbb41cSArnaldo Carvalho de Melo return -1; 154523cbb41cSArnaldo Carvalho de Melo } 154623cbb41cSArnaldo Carvalho de Melo } 15471101c872SJin Yao #endif 154808c83997SArnaldo Carvalho de Melo if (evlist__start_sb_thread(rec->sb_evlist, &rec->opts.target)) { 154923cbb41cSArnaldo Carvalho de Melo pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); 155023cbb41cSArnaldo Carvalho de Melo opts->no_bpf_event = true; 155123cbb41cSArnaldo Carvalho de Melo } 155223cbb41cSArnaldo Carvalho de Melo 155323cbb41cSArnaldo Carvalho de Melo return 0; 155423cbb41cSArnaldo Carvalho de Melo } 155523cbb41cSArnaldo Carvalho de Melo 1556d1e325cfSJiri Olsa static int record__init_clock(struct record *rec) 1557d1e325cfSJiri Olsa { 1558d1e325cfSJiri Olsa struct perf_session *session = rec->session; 1559d1e325cfSJiri Olsa struct timespec ref_clockid; 1560d1e325cfSJiri Olsa struct timeval ref_tod; 1561d1e325cfSJiri Olsa u64 ref; 1562d1e325cfSJiri Olsa 1563d1e325cfSJiri Olsa if (!rec->opts.use_clockid) 1564d1e325cfSJiri Olsa return 0; 1565d1e325cfSJiri Olsa 15669d88a1a1SJiri Olsa if (rec->opts.use_clockid && rec->opts.clockid_res_ns) 15679d88a1a1SJiri Olsa session->header.env.clock.clockid_res_ns = rec->opts.clockid_res_ns; 15689d88a1a1SJiri Olsa 1569d1e325cfSJiri Olsa session->header.env.clock.clockid = rec->opts.clockid; 1570d1e325cfSJiri Olsa 1571d1e325cfSJiri Olsa if (gettimeofday(&ref_tod, NULL) != 0) { 1572d1e325cfSJiri Olsa pr_err("gettimeofday failed, cannot set reference time.\n"); 1573d1e325cfSJiri Olsa return -1; 1574d1e325cfSJiri Olsa } 1575d1e325cfSJiri Olsa 1576d1e325cfSJiri Olsa if (clock_gettime(rec->opts.clockid, &ref_clockid)) { 1577d1e325cfSJiri Olsa pr_err("clock_gettime failed, cannot set reference time.\n"); 1578d1e325cfSJiri Olsa return -1; 1579d1e325cfSJiri Olsa } 1580d1e325cfSJiri Olsa 1581d1e325cfSJiri Olsa ref = (u64) ref_tod.tv_sec * NSEC_PER_SEC + 1582d1e325cfSJiri Olsa (u64) ref_tod.tv_usec * NSEC_PER_USEC; 1583d1e325cfSJiri Olsa 1584d1e325cfSJiri Olsa session->header.env.clock.tod_ns = ref; 1585d1e325cfSJiri Olsa 1586d1e325cfSJiri Olsa ref = (u64) ref_clockid.tv_sec * NSEC_PER_SEC + 1587d1e325cfSJiri Olsa (u64) ref_clockid.tv_nsec; 1588d1e325cfSJiri Olsa 1589d1e325cfSJiri Olsa session->header.env.clock.clockid_ns = ref; 1590d1e325cfSJiri Olsa return 0; 1591d1e325cfSJiri Olsa } 1592d1e325cfSJiri Olsa 1593d20aff15SAdrian Hunter static void hit_auxtrace_snapshot_trigger(struct record *rec) 1594d20aff15SAdrian Hunter { 1595d20aff15SAdrian Hunter if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 1596d20aff15SAdrian Hunter trigger_hit(&auxtrace_snapshot_trigger); 1597d20aff15SAdrian Hunter auxtrace_record__snapshot_started = 1; 1598d20aff15SAdrian Hunter if (auxtrace_record__snapshot_start(rec->itr)) 1599d20aff15SAdrian Hunter trigger_error(&auxtrace_snapshot_trigger); 1600d20aff15SAdrian Hunter } 1601d20aff15SAdrian Hunter } 1602d20aff15SAdrian Hunter 160391c0f5ecSJin Yao static void record__uniquify_name(struct record *rec) 160491c0f5ecSJin Yao { 160591c0f5ecSJin Yao struct evsel *pos; 160691c0f5ecSJin Yao struct evlist *evlist = rec->evlist; 160791c0f5ecSJin Yao char *new_name; 160891c0f5ecSJin Yao int ret; 160991c0f5ecSJin Yao 161091c0f5ecSJin Yao if (!perf_pmu__has_hybrid()) 161191c0f5ecSJin Yao return; 161291c0f5ecSJin Yao 161391c0f5ecSJin Yao evlist__for_each_entry(evlist, pos) { 161491c0f5ecSJin Yao if (!evsel__is_hybrid(pos)) 161591c0f5ecSJin Yao continue; 161691c0f5ecSJin Yao 161791c0f5ecSJin Yao if (strchr(pos->name, '/')) 161891c0f5ecSJin Yao continue; 161991c0f5ecSJin Yao 162091c0f5ecSJin Yao ret = asprintf(&new_name, "%s/%s/", 162191c0f5ecSJin Yao pos->pmu_name, pos->name); 162291c0f5ecSJin Yao if (ret) { 162391c0f5ecSJin Yao free(pos->name); 162491c0f5ecSJin Yao pos->name = new_name; 162591c0f5ecSJin Yao } 162691c0f5ecSJin Yao } 162791c0f5ecSJin Yao } 162891c0f5ecSJin Yao 16298c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 163086470930SIngo Molnar { 163157706abcSDavid Ahern int err; 163245604710SNamhyung Kim int status = 0; 16338b412664SPeter Zijlstra unsigned long waking = 0; 163446be604bSZhang, Yanmin const bool forks = argc > 0; 163545694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 1636b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 16378ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1638d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 16396dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 164042aa276fSNamhyung Kim int fd; 1641d3c8c08eSAlexey Budankov float ratio = 0; 1642acce0223SAlexey Budankov enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED; 164386470930SIngo Molnar 164445604710SNamhyung Kim atexit(record__sig_exit); 1645f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 1646f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 1647804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 1648a074865eSWang Nan signal(SIGSEGV, sigsegv_handler); 1649c0bdc1c4SWang Nan 1650f3b3614aSHari Bathini if (rec->opts.record_namespaces) 1651f3b3614aSHari Bathini tool->namespace_events = true; 1652f3b3614aSHari Bathini 16538fb4b679SNamhyung Kim if (rec->opts.record_cgroup) { 16548fb4b679SNamhyung Kim #ifdef HAVE_FILE_HANDLE 16558fb4b679SNamhyung Kim tool->cgroup_events = true; 16568fb4b679SNamhyung Kim #else 16578fb4b679SNamhyung Kim pr_err("cgroup tracking is not supported\n"); 16588fb4b679SNamhyung Kim return -1; 16598fb4b679SNamhyung Kim #endif 16608fb4b679SNamhyung Kim } 16618fb4b679SNamhyung Kim 1662dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 16632dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 16643c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 16655f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 1666dc0c6127SJiri Olsa if (rec->switch_output.enabled) 16673c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 1668c0bdc1c4SWang Nan } else { 16692dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 1670c0bdc1c4SWang Nan } 1671f5970550SPeter Zijlstra 16722681bd85SNamhyung Kim session = perf_session__new(data, tool); 16736ef81c55SMamatha Inamdar if (IS_ERR(session)) { 1674ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 16756ef81c55SMamatha Inamdar return PTR_ERR(session); 1676a9a70bbcSArnaldo Carvalho de Melo } 1677a9a70bbcSArnaldo Carvalho de Melo 16788ceb41d7SJiri Olsa fd = perf_data__fd(data); 1679d20deb64SArnaldo Carvalho de Melo rec->session = session; 1680d20deb64SArnaldo Carvalho de Melo 16815d7f4116SAlexey Budankov if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) { 16825d7f4116SAlexey Budankov pr_err("Compression initialization failed.\n"); 16835d7f4116SAlexey Budankov return -1; 16845d7f4116SAlexey Budankov } 1685da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 1686da231338SAnand K Mistry done_fd = eventfd(0, EFD_NONBLOCK); 1687da231338SAnand K Mistry if (done_fd < 0) { 1688da231338SAnand K Mistry pr_err("Failed to create wakeup eventfd, error: %m\n"); 1689da231338SAnand K Mistry status = -1; 1690da231338SAnand K Mistry goto out_delete_session; 1691da231338SAnand K Mistry } 1692e16c2ce7SYang Jihong err = evlist__add_wakeup_eventfd(rec->evlist, done_fd); 1693da231338SAnand K Mistry if (err < 0) { 1694da231338SAnand K Mistry pr_err("Failed to add wakeup eventfd to poll list\n"); 1695da231338SAnand K Mistry status = err; 1696da231338SAnand K Mistry goto out_delete_session; 1697da231338SAnand K Mistry } 1698da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT 16995d7f4116SAlexey Budankov 17005d7f4116SAlexey Budankov session->header.env.comp_type = PERF_COMP_ZSTD; 17015d7f4116SAlexey Budankov session->header.env.comp_level = rec->opts.comp_level; 17025d7f4116SAlexey Budankov 1703eeb399b5SAdrian Hunter if (rec->opts.kcore && 1704eeb399b5SAdrian Hunter !record__kcore_readable(&session->machines.host)) { 1705eeb399b5SAdrian Hunter pr_err("ERROR: kcore is not readable.\n"); 1706eeb399b5SAdrian Hunter return -1; 1707eeb399b5SAdrian Hunter } 1708eeb399b5SAdrian Hunter 1709d1e325cfSJiri Olsa if (record__init_clock(rec)) 1710d1e325cfSJiri Olsa return -1; 1711d1e325cfSJiri Olsa 17128c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 1713330aa675SStephane Eranian 1714d4db3f16SArnaldo Carvalho de Melo if (forks) { 17157b392ef0SArnaldo Carvalho de Melo err = evlist__prepare_workload(rec->evlist, &opts->target, argv, data->is_pipe, 1716735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 171735b9d88eSArnaldo Carvalho de Melo if (err < 0) { 171835b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 171945604710SNamhyung Kim status = err; 172035b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 1721856e9660SPeter Zijlstra } 1722856e9660SPeter Zijlstra } 1723856e9660SPeter Zijlstra 1724ad46e48cSJiri Olsa /* 1725ad46e48cSJiri Olsa * If we have just single event and are sending data 1726ad46e48cSJiri Olsa * through pipe, we need to force the ids allocation, 1727ad46e48cSJiri Olsa * because we synthesize event name through the pipe 1728ad46e48cSJiri Olsa * and need the id for that. 1729ad46e48cSJiri Olsa */ 17306484d2f9SJiri Olsa if (data->is_pipe && rec->evlist->core.nr_entries == 1) 1731ad46e48cSJiri Olsa rec->opts.sample_id = true; 1732ad46e48cSJiri Olsa 173391c0f5ecSJin Yao record__uniquify_name(rec); 173491c0f5ecSJin Yao 17358c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 17368d3eca20SDavid Ahern err = -1; 173745604710SNamhyung Kim goto out_child; 17388d3eca20SDavid Ahern } 1739f6fa4375SJiri Olsa session->header.env.comp_mmap_len = session->evlist->core.mmap_len; 174086470930SIngo Molnar 1741eeb399b5SAdrian Hunter if (rec->opts.kcore) { 1742eeb399b5SAdrian Hunter err = record__kcore_copy(&session->machines.host, data); 1743eeb399b5SAdrian Hunter if (err) { 1744eeb399b5SAdrian Hunter pr_err("ERROR: Failed to copy kcore\n"); 1745eeb399b5SAdrian Hunter goto out_child; 1746eeb399b5SAdrian Hunter } 1747eeb399b5SAdrian Hunter } 1748eeb399b5SAdrian Hunter 17498690a2a7SWang Nan err = bpf__apply_obj_config(); 17508690a2a7SWang Nan if (err) { 17518690a2a7SWang Nan char errbuf[BUFSIZ]; 17528690a2a7SWang Nan 17538690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 17548690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 17558690a2a7SWang Nan errbuf); 17568690a2a7SWang Nan goto out_child; 17578690a2a7SWang Nan } 17588690a2a7SWang Nan 1759cca8482cSAdrian Hunter /* 1760cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 1761cca8482cSAdrian Hunter * evlist. 1762cca8482cSAdrian Hunter */ 17638cedf3a5SArnaldo Carvalho de Melo if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) { 1764cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 1765cca8482cSAdrian Hunter rec->tool.ordered_events = false; 1766cca8482cSAdrian Hunter } 1767cca8482cSAdrian Hunter 17683a683120SJiri Olsa if (!rec->evlist->core.nr_groups) 1769a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 1770a8bb559bSNamhyung Kim 17718ceb41d7SJiri Olsa if (data->is_pipe) { 177242aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 1773529870e3STom Zanussi if (err < 0) 177445604710SNamhyung Kim goto out_child; 1775563aecb2SJiri Olsa } else { 177642aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 1777d5eed904SArnaldo Carvalho de Melo if (err < 0) 177845604710SNamhyung Kim goto out_child; 1779d5eed904SArnaldo Carvalho de Melo } 17807c6a1c65SPeter Zijlstra 1781b38d85efSArnaldo Carvalho de Melo err = -1; 1782d3665498SDavid Ahern if (!rec->no_buildid 1783e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 1784d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 1785e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 178645604710SNamhyung Kim goto out_child; 1787e20960c0SRobert Richter } 1788e20960c0SRobert Richter 178923cbb41cSArnaldo Carvalho de Melo err = record__setup_sb_evlist(rec); 179023cbb41cSArnaldo Carvalho de Melo if (err) 1791b38d85efSArnaldo Carvalho de Melo goto out_child; 1792657ee553SSong Liu 17934ea648aeSWang Nan err = record__synthesize(rec, false); 1794c45c86ebSWang Nan if (err < 0) 179545604710SNamhyung Kim goto out_child; 17968d3eca20SDavid Ahern 1797d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 179886470930SIngo Molnar struct sched_param param; 179986470930SIngo Molnar 1800d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 180186470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 18026beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 18038d3eca20SDavid Ahern err = -1; 180445604710SNamhyung Kim goto out_child; 180586470930SIngo Molnar } 180686470930SIngo Molnar } 180786470930SIngo Molnar 1808774cb499SJiri Olsa /* 1809774cb499SJiri Olsa * When perf is starting the traced process, all the events 1810774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 1811774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 1812774cb499SJiri Olsa */ 18136619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 18141c87f165SJiri Olsa evlist__enable(rec->evlist); 1815764e16a3SDavid Ahern 1816856e9660SPeter Zijlstra /* 1817856e9660SPeter Zijlstra * Let the child rip 1818856e9660SPeter Zijlstra */ 1819e803cf97SNamhyung Kim if (forks) { 182020a8a3cfSJiri Olsa struct machine *machine = &session->machines.host; 1821e5bed564SNamhyung Kim union perf_event *event; 1822e907caf3SHari Bathini pid_t tgid; 1823e5bed564SNamhyung Kim 1824e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 1825e5bed564SNamhyung Kim if (event == NULL) { 1826e5bed564SNamhyung Kim err = -ENOMEM; 1827e5bed564SNamhyung Kim goto out_child; 1828e5bed564SNamhyung Kim } 1829e5bed564SNamhyung Kim 1830e803cf97SNamhyung Kim /* 1831e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 1832e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 1833e803cf97SNamhyung Kim * cannot see a correct process name for those events. 1834e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 1835e803cf97SNamhyung Kim */ 1836e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event, 1837e803cf97SNamhyung Kim rec->evlist->workload.pid, 1838e803cf97SNamhyung Kim process_synthesized_event, 1839e803cf97SNamhyung Kim machine); 1840e5bed564SNamhyung Kim free(event); 1841e803cf97SNamhyung Kim 1842e907caf3SHari Bathini if (tgid == -1) 1843e907caf3SHari Bathini goto out_child; 1844e907caf3SHari Bathini 1845e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) + 1846e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 1847e907caf3SHari Bathini machine->id_hdr_size); 1848e907caf3SHari Bathini if (event == NULL) { 1849e907caf3SHari Bathini err = -ENOMEM; 1850e907caf3SHari Bathini goto out_child; 1851e907caf3SHari Bathini } 1852e907caf3SHari Bathini 1853e907caf3SHari Bathini /* 1854e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified. 1855e907caf3SHari Bathini */ 1856e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event, 1857e907caf3SHari Bathini rec->evlist->workload.pid, 1858e907caf3SHari Bathini tgid, process_synthesized_event, 1859e907caf3SHari Bathini machine); 1860e907caf3SHari Bathini free(event); 1861e907caf3SHari Bathini 18627b392ef0SArnaldo Carvalho de Melo evlist__start_workload(rec->evlist); 1863e803cf97SNamhyung Kim } 1864856e9660SPeter Zijlstra 18651d078ccbSAlexey Budankov if (evlist__initialize_ctlfd(rec->evlist, opts->ctl_fd, opts->ctl_fd_ack)) 18661d078ccbSAlexey Budankov goto out_child; 18671d078ccbSAlexey Budankov 18686619a53eSAndi Kleen if (opts->initial_delay) { 186968cd3b45SAlexey Budankov pr_info(EVLIST_DISABLED_MSG); 187068cd3b45SAlexey Budankov if (opts->initial_delay > 0) { 18710693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 18721c87f165SJiri Olsa evlist__enable(rec->evlist); 187368cd3b45SAlexey Budankov pr_info(EVLIST_ENABLED_MSG); 187468cd3b45SAlexey Budankov } 18756619a53eSAndi Kleen } 18766619a53eSAndi Kleen 18775f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 18783c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 1879a074865eSWang Nan perf_hooks__invoke_record_start(); 1880649c48a9SPeter Zijlstra for (;;) { 18819f065194SYang Shi unsigned long long hits = rec->samples; 188286470930SIngo Molnar 188305737464SWang Nan /* 188405737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 188505737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 188605737464SWang Nan * hits != rec->samples in previous round. 188705737464SWang Nan * 1888ade9d208SArnaldo Carvalho de Melo * evlist__toggle_bkw_mmap ensure we never 188905737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 189005737464SWang Nan */ 189105737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 1892ade9d208SArnaldo Carvalho de Melo evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 189305737464SWang Nan 1894470530bbSAlexey Budankov if (record__mmap_read_all(rec, false) < 0) { 18955f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 18963c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 18978d3eca20SDavid Ahern err = -1; 189845604710SNamhyung Kim goto out_child; 18998d3eca20SDavid Ahern } 190086470930SIngo Molnar 19012dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 19022dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 19035f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 1904ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, false); 19055f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 19062dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 19072dd6d8a1SAdrian Hunter err = -1; 19082dd6d8a1SAdrian Hunter goto out_child; 19092dd6d8a1SAdrian Hunter } 19102dd6d8a1SAdrian Hunter } 19112dd6d8a1SAdrian Hunter 19123c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 191305737464SWang Nan /* 191405737464SWang Nan * If switch_output_trigger is hit, the data in 191505737464SWang Nan * overwritable ring buffer should have been collected, 191605737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 191705737464SWang Nan * 191805737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 191905737464SWang Nan * record__mmap_read_all() didn't collect data from 192005737464SWang Nan * overwritable ring buffer. Read again. 192105737464SWang Nan */ 192205737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 192305737464SWang Nan continue; 19243c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 19253c1cb7e3SWang Nan 192605737464SWang Nan /* 192705737464SWang Nan * Reenable events in overwrite ring buffer after 192805737464SWang Nan * record__mmap_read_all(): we should have collected 192905737464SWang Nan * data from it. 193005737464SWang Nan */ 1931ade9d208SArnaldo Carvalho de Melo evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 193205737464SWang Nan 19333c1cb7e3SWang Nan if (!quiet) 19343c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 19353c1cb7e3SWang Nan waking); 19363c1cb7e3SWang Nan waking = 0; 19373c1cb7e3SWang Nan fd = record__switch_output(rec, false); 19383c1cb7e3SWang Nan if (fd < 0) { 19393c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 19403c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 19413c1cb7e3SWang Nan err = fd; 19423c1cb7e3SWang Nan goto out_child; 19433c1cb7e3SWang Nan } 1944bfacbe3bSJiri Olsa 1945bfacbe3bSJiri Olsa /* re-arm the alarm */ 1946bfacbe3bSJiri Olsa if (rec->switch_output.time) 1947bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 19483c1cb7e3SWang Nan } 19493c1cb7e3SWang Nan 1950d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 19516dcf45efSArnaldo Carvalho de Melo if (done || draining) 1952649c48a9SPeter Zijlstra break; 195380ab2987SJiri Olsa err = evlist__poll(rec->evlist, -1); 1954a515114fSJiri Olsa /* 1955a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1956a515114fSJiri Olsa * number of returned events and interrupt error. 1957a515114fSJiri Olsa */ 1958a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 195945604710SNamhyung Kim err = 0; 19608b412664SPeter Zijlstra waking++; 19616dcf45efSArnaldo Carvalho de Melo 1962f4009e7bSJiri Olsa if (evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 19636dcf45efSArnaldo Carvalho de Melo draining = true; 19648b412664SPeter Zijlstra } 19658b412664SPeter Zijlstra 1966acce0223SAlexey Budankov if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) { 1967acce0223SAlexey Budankov switch (cmd) { 1968d20aff15SAdrian Hunter case EVLIST_CTL_CMD_SNAPSHOT: 1969d20aff15SAdrian Hunter hit_auxtrace_snapshot_trigger(rec); 1970d20aff15SAdrian Hunter evlist__ctlfd_ack(rec->evlist); 1971d20aff15SAdrian Hunter break; 1972f186cd61SJiri Olsa case EVLIST_CTL_CMD_STOP: 1973f186cd61SJiri Olsa done = 1; 1974f186cd61SJiri Olsa break; 1975acce0223SAlexey Budankov case EVLIST_CTL_CMD_ACK: 1976acce0223SAlexey Budankov case EVLIST_CTL_CMD_UNSUPPORTED: 1977991ae4ebSJiri Olsa case EVLIST_CTL_CMD_ENABLE: 1978991ae4ebSJiri Olsa case EVLIST_CTL_CMD_DISABLE: 1979142544a9SJiri Olsa case EVLIST_CTL_CMD_EVLIST: 198047fddcb4SJiri Olsa case EVLIST_CTL_CMD_PING: 1981acce0223SAlexey Budankov default: 1982acce0223SAlexey Budankov break; 1983acce0223SAlexey Budankov } 1984acce0223SAlexey Budankov } 1985acce0223SAlexey Budankov 1986774cb499SJiri Olsa /* 1987774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1988774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1989774cb499SJiri Olsa * disable events in this case. 1990774cb499SJiri Olsa */ 1991602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 19925f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 1993e74676deSJiri Olsa evlist__disable(rec->evlist); 19942711926aSJiri Olsa disabled = true; 19952711926aSJiri Olsa } 19968b412664SPeter Zijlstra } 1997ce7b0e42SAlexander Shishkin 19985f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 19993c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 20008b412664SPeter Zijlstra 2001ce7b0e42SAlexander Shishkin if (opts->auxtrace_snapshot_on_exit) 2002ce7b0e42SAlexander Shishkin record__auxtrace_snapshot_exit(rec); 2003ce7b0e42SAlexander Shishkin 2004f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 20053535a696SArnaldo Carvalho de Melo char msg[STRERR_BUFSIZE], strevsels[2048]; 2006c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 20073535a696SArnaldo Carvalho de Melo 20083535a696SArnaldo Carvalho de Melo evlist__scnprintf_evsels(rec->evlist, sizeof(strevsels), strevsels); 20093535a696SArnaldo Carvalho de Melo 20103535a696SArnaldo Carvalho de Melo pr_err("Failed to collect '%s' for the '%s' workload: %s\n", 20113535a696SArnaldo Carvalho de Melo strevsels, argv[0], emsg); 2012f33cbe72SArnaldo Carvalho de Melo err = -1; 201345604710SNamhyung Kim goto out_child; 2014f33cbe72SArnaldo Carvalho de Melo } 2015f33cbe72SArnaldo Carvalho de Melo 2016e3d59112SNamhyung Kim if (!quiet) 20178b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 201886470930SIngo Molnar 20194ea648aeSWang Nan if (target__none(&rec->opts.target)) 20204ea648aeSWang Nan record__synthesize_workload(rec, true); 20214ea648aeSWang Nan 202245604710SNamhyung Kim out_child: 20231d078ccbSAlexey Budankov evlist__finalize_ctlfd(rec->evlist); 2024470530bbSAlexey Budankov record__mmap_read_all(rec, true); 2025d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 2026d3d1af6fSAlexey Budankov 2027d3c8c08eSAlexey Budankov if (rec->session->bytes_transferred && rec->session->bytes_compressed) { 2028d3c8c08eSAlexey Budankov ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed; 2029d3c8c08eSAlexey Budankov session->header.env.comp_ratio = ratio + 0.5; 2030d3c8c08eSAlexey Budankov } 2031d3c8c08eSAlexey Budankov 203245604710SNamhyung Kim if (forks) { 203345604710SNamhyung Kim int exit_status; 203445604710SNamhyung Kim 203545604710SNamhyung Kim if (!child_finished) 203645604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 203745604710SNamhyung Kim 203845604710SNamhyung Kim wait(&exit_status); 203945604710SNamhyung Kim 204045604710SNamhyung Kim if (err < 0) 204145604710SNamhyung Kim status = err; 204245604710SNamhyung Kim else if (WIFEXITED(exit_status)) 204345604710SNamhyung Kim status = WEXITSTATUS(exit_status); 204445604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 204545604710SNamhyung Kim signr = WTERMSIG(exit_status); 204645604710SNamhyung Kim } else 204745604710SNamhyung Kim status = err; 204845604710SNamhyung Kim 20494ea648aeSWang Nan record__synthesize(rec, true); 2050e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 2051e3d59112SNamhyung Kim rec->samples = 0; 2052e3d59112SNamhyung Kim 2053ecfd7a9cSWang Nan if (!err) { 2054ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 2055e1ab48baSWang Nan record__finish_output(rec); 2056ecfd7a9cSWang Nan } else { 2057ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 2058ecfd7a9cSWang Nan if (fd < 0) { 2059ecfd7a9cSWang Nan status = fd; 2060ecfd7a9cSWang Nan goto out_delete_session; 2061ecfd7a9cSWang Nan } 2062ecfd7a9cSWang Nan } 2063ecfd7a9cSWang Nan } 206439d17dacSArnaldo Carvalho de Melo 2065a074865eSWang Nan perf_hooks__invoke_record_end(); 2066a074865eSWang Nan 2067e3d59112SNamhyung Kim if (!err && !quiet) { 2068e3d59112SNamhyung Kim char samples[128]; 2069ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 2070ecfd7a9cSWang Nan ".<timestamp>" : ""; 2071e3d59112SNamhyung Kim 2072ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 2073e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 2074e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 2075e3d59112SNamhyung Kim else 2076e3d59112SNamhyung Kim samples[0] = '\0'; 2077e3d59112SNamhyung Kim 2078d3c8c08eSAlexey Budankov fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s", 20798ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0, 20802d4f2799SJiri Olsa data->path, postfix, samples); 2081d3c8c08eSAlexey Budankov if (ratio) { 2082d3c8c08eSAlexey Budankov fprintf(stderr, ", compressed (original %.3f MB, ratio is %.3f)", 2083d3c8c08eSAlexey Budankov rec->session->bytes_transferred / 1024.0 / 1024.0, 2084d3c8c08eSAlexey Budankov ratio); 2085d3c8c08eSAlexey Budankov } 2086d3c8c08eSAlexey Budankov fprintf(stderr, " ]\n"); 2087e3d59112SNamhyung Kim } 2088e3d59112SNamhyung Kim 208939d17dacSArnaldo Carvalho de Melo out_delete_session: 2090da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 2091da231338SAnand K Mistry if (done_fd >= 0) 2092da231338SAnand K Mistry close(done_fd); 2093da231338SAnand K Mistry #endif 20945d7f4116SAlexey Budankov zstd_fini(&session->zstd_data); 209539d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 2096657ee553SSong Liu 2097657ee553SSong Liu if (!opts->no_bpf_event) 209808c83997SArnaldo Carvalho de Melo evlist__stop_sb_thread(rec->sb_evlist); 209945604710SNamhyung Kim return status; 210086470930SIngo Molnar } 210186470930SIngo Molnar 21020883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 210309b0fd45SJiri Olsa { 2104aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 2105a601fdffSJiri Olsa 21060883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 210726d33022SJiri Olsa 21080883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 210909b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 21100883e820SArnaldo Carvalho de Melo callchain->dump_size); 21110883e820SArnaldo Carvalho de Melo } 21120883e820SArnaldo Carvalho de Melo 21130883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 21140883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 21150883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 21160883e820SArnaldo Carvalho de Melo { 21170883e820SArnaldo Carvalho de Melo int ret; 21180883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 21190883e820SArnaldo Carvalho de Melo 21200883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 21210883e820SArnaldo Carvalho de Melo if (unset) { 21220883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 21230883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 21240883e820SArnaldo Carvalho de Melo return 0; 21250883e820SArnaldo Carvalho de Melo } 21260883e820SArnaldo Carvalho de Melo 21270883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 21280883e820SArnaldo Carvalho de Melo if (!ret) { 21290883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 21300883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 21310883e820SArnaldo Carvalho de Melo record->sample_address = true; 21320883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 21330883e820SArnaldo Carvalho de Melo } 21340883e820SArnaldo Carvalho de Melo 21350883e820SArnaldo Carvalho de Melo return ret; 213609b0fd45SJiri Olsa } 213709b0fd45SJiri Olsa 2138c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 213909b0fd45SJiri Olsa const char *arg, 214009b0fd45SJiri Olsa int unset) 214109b0fd45SJiri Olsa { 21420883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 214326d33022SJiri Olsa } 214426d33022SJiri Olsa 2145c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 214609b0fd45SJiri Olsa const char *arg __maybe_unused, 214709b0fd45SJiri Olsa int unset __maybe_unused) 214809b0fd45SJiri Olsa { 21492ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 2150c421e80bSKan Liang 21512ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 215209b0fd45SJiri Olsa 21532ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 21542ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 2155eb853e80SJiri Olsa 21562ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 215709b0fd45SJiri Olsa return 0; 215809b0fd45SJiri Olsa } 215909b0fd45SJiri Olsa 2160eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 2161eb853e80SJiri Olsa { 21627a29c087SNamhyung Kim struct record *rec = cb; 21637a29c087SNamhyung Kim 21647a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 21657a29c087SNamhyung Kim if (!strcmp(value, "cache")) 21667a29c087SNamhyung Kim rec->no_buildid_cache = false; 21677a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 21687a29c087SNamhyung Kim rec->no_buildid_cache = true; 21697a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 21707a29c087SNamhyung Kim rec->no_buildid = true; 2171e29386c8SJiri Olsa else if (!strcmp(value, "mmap")) 2172e29386c8SJiri Olsa rec->buildid_mmap = true; 21737a29c087SNamhyung Kim else 21747a29c087SNamhyung Kim return -1; 21757a29c087SNamhyung Kim return 0; 21767a29c087SNamhyung Kim } 2177cff17205SYisheng Xie if (!strcmp(var, "record.call-graph")) { 2178cff17205SYisheng Xie var = "call-graph.record-mode"; 2179eb853e80SJiri Olsa return perf_default_config(var, value, cb); 2180eb853e80SJiri Olsa } 218193f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 218293f20c0fSAlexey Budankov if (!strcmp(var, "record.aio")) { 218393f20c0fSAlexey Budankov rec->opts.nr_cblocks = strtol(value, NULL, 0); 218493f20c0fSAlexey Budankov if (!rec->opts.nr_cblocks) 218593f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_default; 218693f20c0fSAlexey Budankov } 218793f20c0fSAlexey Budankov #endif 21889bce13eaSJiri Olsa if (!strcmp(var, "record.debuginfod")) { 21899bce13eaSJiri Olsa rec->debuginfod.urls = strdup(value); 21909bce13eaSJiri Olsa if (!rec->debuginfod.urls) 21919bce13eaSJiri Olsa return -ENOMEM; 21929bce13eaSJiri Olsa rec->debuginfod.set = true; 21939bce13eaSJiri Olsa } 2194eb853e80SJiri Olsa 2195cff17205SYisheng Xie return 0; 2196cff17205SYisheng Xie } 2197cff17205SYisheng Xie 2198814c8c38SPeter Zijlstra 2199f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset) 2200f4fe11b7SAlexey Budankov { 2201f4fe11b7SAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 2202f4fe11b7SAlexey Budankov 2203f4fe11b7SAlexey Budankov if (unset || !str) 2204f4fe11b7SAlexey Budankov return 0; 2205f4fe11b7SAlexey Budankov 2206f4fe11b7SAlexey Budankov if (!strcasecmp(str, "node")) 2207f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_NODE; 2208f4fe11b7SAlexey Budankov else if (!strcasecmp(str, "cpu")) 2209f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_CPU; 2210f4fe11b7SAlexey Budankov 2211f4fe11b7SAlexey Budankov return 0; 2212f4fe11b7SAlexey Budankov } 2213f4fe11b7SAlexey Budankov 2214*7954f716SAlexey Bayduraev static int record__mmap_cpu_mask_alloc(struct mmap_cpu_mask *mask, int nr_bits) 2215*7954f716SAlexey Bayduraev { 2216*7954f716SAlexey Bayduraev mask->nbits = nr_bits; 2217*7954f716SAlexey Bayduraev mask->bits = bitmap_zalloc(mask->nbits); 2218*7954f716SAlexey Bayduraev if (!mask->bits) 2219*7954f716SAlexey Bayduraev return -ENOMEM; 2220*7954f716SAlexey Bayduraev 2221*7954f716SAlexey Bayduraev return 0; 2222*7954f716SAlexey Bayduraev } 2223*7954f716SAlexey Bayduraev 2224*7954f716SAlexey Bayduraev static void record__mmap_cpu_mask_free(struct mmap_cpu_mask *mask) 2225*7954f716SAlexey Bayduraev { 2226*7954f716SAlexey Bayduraev bitmap_free(mask->bits); 2227*7954f716SAlexey Bayduraev mask->nbits = 0; 2228*7954f716SAlexey Bayduraev } 2229*7954f716SAlexey Bayduraev 2230*7954f716SAlexey Bayduraev static int record__thread_mask_alloc(struct thread_mask *mask, int nr_bits) 2231*7954f716SAlexey Bayduraev { 2232*7954f716SAlexey Bayduraev int ret; 2233*7954f716SAlexey Bayduraev 2234*7954f716SAlexey Bayduraev ret = record__mmap_cpu_mask_alloc(&mask->maps, nr_bits); 2235*7954f716SAlexey Bayduraev if (ret) { 2236*7954f716SAlexey Bayduraev mask->affinity.bits = NULL; 2237*7954f716SAlexey Bayduraev return ret; 2238*7954f716SAlexey Bayduraev } 2239*7954f716SAlexey Bayduraev 2240*7954f716SAlexey Bayduraev ret = record__mmap_cpu_mask_alloc(&mask->affinity, nr_bits); 2241*7954f716SAlexey Bayduraev if (ret) { 2242*7954f716SAlexey Bayduraev record__mmap_cpu_mask_free(&mask->maps); 2243*7954f716SAlexey Bayduraev mask->maps.bits = NULL; 2244*7954f716SAlexey Bayduraev } 2245*7954f716SAlexey Bayduraev 2246*7954f716SAlexey Bayduraev return ret; 2247*7954f716SAlexey Bayduraev } 2248*7954f716SAlexey Bayduraev 2249*7954f716SAlexey Bayduraev static void record__thread_mask_free(struct thread_mask *mask) 2250*7954f716SAlexey Bayduraev { 2251*7954f716SAlexey Bayduraev record__mmap_cpu_mask_free(&mask->maps); 2252*7954f716SAlexey Bayduraev record__mmap_cpu_mask_free(&mask->affinity); 2253*7954f716SAlexey Bayduraev } 2254*7954f716SAlexey Bayduraev 22556d575816SJiwei Sun static int parse_output_max_size(const struct option *opt, 22566d575816SJiwei Sun const char *str, int unset) 22576d575816SJiwei Sun { 22586d575816SJiwei Sun unsigned long *s = (unsigned long *)opt->value; 22596d575816SJiwei Sun static struct parse_tag tags_size[] = { 22606d575816SJiwei Sun { .tag = 'B', .mult = 1 }, 22616d575816SJiwei Sun { .tag = 'K', .mult = 1 << 10 }, 22626d575816SJiwei Sun { .tag = 'M', .mult = 1 << 20 }, 22636d575816SJiwei Sun { .tag = 'G', .mult = 1 << 30 }, 22646d575816SJiwei Sun { .tag = 0 }, 22656d575816SJiwei Sun }; 22666d575816SJiwei Sun unsigned long val; 22676d575816SJiwei Sun 22686d575816SJiwei Sun if (unset) { 22696d575816SJiwei Sun *s = 0; 22706d575816SJiwei Sun return 0; 22716d575816SJiwei Sun } 22726d575816SJiwei Sun 22736d575816SJiwei Sun val = parse_tag_value(str, tags_size); 22746d575816SJiwei Sun if (val != (unsigned long) -1) { 22756d575816SJiwei Sun *s = val; 22766d575816SJiwei Sun return 0; 22776d575816SJiwei Sun } 22786d575816SJiwei Sun 22796d575816SJiwei Sun return -1; 22806d575816SJiwei Sun } 22816d575816SJiwei Sun 2282e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 2283e9db1310SAdrian Hunter const char *str, 2284e9db1310SAdrian Hunter int unset __maybe_unused) 2285e9db1310SAdrian Hunter { 2286e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 2287e9db1310SAdrian Hunter char *s, *p; 2288e9db1310SAdrian Hunter unsigned int mmap_pages; 2289e9db1310SAdrian Hunter int ret; 2290e9db1310SAdrian Hunter 2291e9db1310SAdrian Hunter if (!str) 2292e9db1310SAdrian Hunter return -EINVAL; 2293e9db1310SAdrian Hunter 2294e9db1310SAdrian Hunter s = strdup(str); 2295e9db1310SAdrian Hunter if (!s) 2296e9db1310SAdrian Hunter return -ENOMEM; 2297e9db1310SAdrian Hunter 2298e9db1310SAdrian Hunter p = strchr(s, ','); 2299e9db1310SAdrian Hunter if (p) 2300e9db1310SAdrian Hunter *p = '\0'; 2301e9db1310SAdrian Hunter 2302e9db1310SAdrian Hunter if (*s) { 230325f84702SArnaldo Carvalho de Melo ret = __evlist__parse_mmap_pages(&mmap_pages, s); 2304e9db1310SAdrian Hunter if (ret) 2305e9db1310SAdrian Hunter goto out_free; 2306e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 2307e9db1310SAdrian Hunter } 2308e9db1310SAdrian Hunter 2309e9db1310SAdrian Hunter if (!p) { 2310e9db1310SAdrian Hunter ret = 0; 2311e9db1310SAdrian Hunter goto out_free; 2312e9db1310SAdrian Hunter } 2313e9db1310SAdrian Hunter 231425f84702SArnaldo Carvalho de Melo ret = __evlist__parse_mmap_pages(&mmap_pages, p + 1); 2315e9db1310SAdrian Hunter if (ret) 2316e9db1310SAdrian Hunter goto out_free; 2317e9db1310SAdrian Hunter 2318e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 2319e9db1310SAdrian Hunter 2320e9db1310SAdrian Hunter out_free: 2321e9db1310SAdrian Hunter free(s); 2322e9db1310SAdrian Hunter return ret; 2323e9db1310SAdrian Hunter } 2324e9db1310SAdrian Hunter 23257248e308SAlexandre Truong void __weak arch__add_leaf_frame_record_opts(struct record_opts *opts __maybe_unused) 23267248e308SAlexandre Truong { 23277248e308SAlexandre Truong } 23287248e308SAlexandre Truong 23291d078ccbSAlexey Budankov static int parse_control_option(const struct option *opt, 23301d078ccbSAlexey Budankov const char *str, 23311d078ccbSAlexey Budankov int unset __maybe_unused) 23321d078ccbSAlexey Budankov { 23339864a66dSAdrian Hunter struct record_opts *opts = opt->value; 23341d078ccbSAlexey Budankov 2335a8fcbd26SAdrian Hunter return evlist__parse_control(str, &opts->ctl_fd, &opts->ctl_fd_ack, &opts->ctl_fd_close); 2336a8fcbd26SAdrian Hunter } 2337a8fcbd26SAdrian Hunter 23380c582449SJiri Olsa static void switch_output_size_warn(struct record *rec) 23390c582449SJiri Olsa { 23409521b5f2SJiri Olsa u64 wakeup_size = evlist__mmap_size(rec->opts.mmap_pages); 23410c582449SJiri Olsa struct switch_output *s = &rec->switch_output; 23420c582449SJiri Olsa 23430c582449SJiri Olsa wakeup_size /= 2; 23440c582449SJiri Olsa 23450c582449SJiri Olsa if (s->size < wakeup_size) { 23460c582449SJiri Olsa char buf[100]; 23470c582449SJiri Olsa 23480c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 23490c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than " 23500c582449SJiri Olsa "wakeup kernel buffer size (%s) " 23510c582449SJiri Olsa "expect bigger perf.data sizes\n", buf); 23520c582449SJiri Olsa } 23530c582449SJiri Olsa } 23540c582449SJiri Olsa 2355cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec) 2356cb4e1ebbSJiri Olsa { 2357cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output; 2358dc0c6127SJiri Olsa static struct parse_tag tags_size[] = { 2359dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 }, 2360dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 2361dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 2362dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 2363dc0c6127SJiri Olsa { .tag = 0 }, 2364dc0c6127SJiri Olsa }; 2365bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = { 2366bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 }, 2367bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 }, 2368bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 }, 2369bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 }, 2370bfacbe3bSJiri Olsa { .tag = 0 }, 2371bfacbe3bSJiri Olsa }; 2372dc0c6127SJiri Olsa unsigned long val; 2373cb4e1ebbSJiri Olsa 2374899e5ffbSArnaldo Carvalho de Melo /* 2375899e5ffbSArnaldo Carvalho de Melo * If we're using --switch-output-events, then we imply its 2376899e5ffbSArnaldo Carvalho de Melo * --switch-output=signal, as we'll send a SIGUSR2 from the side band 2377899e5ffbSArnaldo Carvalho de Melo * thread to its parent. 2378899e5ffbSArnaldo Carvalho de Melo */ 2379899e5ffbSArnaldo Carvalho de Melo if (rec->switch_output_event_set) 2380899e5ffbSArnaldo Carvalho de Melo goto do_signal; 2381899e5ffbSArnaldo Carvalho de Melo 2382cb4e1ebbSJiri Olsa if (!s->set) 2383cb4e1ebbSJiri Olsa return 0; 2384cb4e1ebbSJiri Olsa 2385cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) { 2386899e5ffbSArnaldo Carvalho de Melo do_signal: 2387cb4e1ebbSJiri Olsa s->signal = true; 2388cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n"); 2389dc0c6127SJiri Olsa goto enabled; 2390dc0c6127SJiri Olsa } 2391dc0c6127SJiri Olsa 2392dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size); 2393dc0c6127SJiri Olsa if (val != (unsigned long) -1) { 2394dc0c6127SJiri Olsa s->size = val; 2395dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str); 2396dc0c6127SJiri Olsa goto enabled; 2397cb4e1ebbSJiri Olsa } 2398cb4e1ebbSJiri Olsa 2399bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time); 2400bfacbe3bSJiri Olsa if (val != (unsigned long) -1) { 2401bfacbe3bSJiri Olsa s->time = val; 2402bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n", 2403bfacbe3bSJiri Olsa s->str, s->time); 2404bfacbe3bSJiri Olsa goto enabled; 2405bfacbe3bSJiri Olsa } 2406bfacbe3bSJiri Olsa 2407cb4e1ebbSJiri Olsa return -1; 2408dc0c6127SJiri Olsa 2409dc0c6127SJiri Olsa enabled: 2410dc0c6127SJiri Olsa rec->timestamp_filename = true; 2411dc0c6127SJiri Olsa s->enabled = true; 24120c582449SJiri Olsa 24130c582449SJiri Olsa if (s->size && !rec->opts.no_buffering) 24140c582449SJiri Olsa switch_output_size_warn(rec); 24150c582449SJiri Olsa 2416dc0c6127SJiri Olsa return 0; 2417cb4e1ebbSJiri Olsa } 2418cb4e1ebbSJiri Olsa 2419e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 242086470930SIngo Molnar "perf record [<options>] [<command>]", 242186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 242286470930SIngo Molnar NULL 242386470930SIngo Molnar }; 2424e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 242586470930SIngo Molnar 24266e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap(struct perf_tool *tool, union perf_event *event, 24276e0a9b3dSArnaldo Carvalho de Melo struct perf_sample *sample, struct machine *machine) 24286e0a9b3dSArnaldo Carvalho de Melo { 24296e0a9b3dSArnaldo Carvalho de Melo /* 24306e0a9b3dSArnaldo Carvalho de Melo * We already have the kernel maps, put in place via perf_session__create_kernel_maps() 24316e0a9b3dSArnaldo Carvalho de Melo * no need to add them twice. 24326e0a9b3dSArnaldo Carvalho de Melo */ 24336e0a9b3dSArnaldo Carvalho de Melo if (!(event->header.misc & PERF_RECORD_MISC_USER)) 24346e0a9b3dSArnaldo Carvalho de Melo return 0; 24356e0a9b3dSArnaldo Carvalho de Melo return perf_event__process_mmap(tool, event, sample, machine); 24366e0a9b3dSArnaldo Carvalho de Melo } 24376e0a9b3dSArnaldo Carvalho de Melo 24386e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap2(struct perf_tool *tool, union perf_event *event, 24396e0a9b3dSArnaldo Carvalho de Melo struct perf_sample *sample, struct machine *machine) 24406e0a9b3dSArnaldo Carvalho de Melo { 24416e0a9b3dSArnaldo Carvalho de Melo /* 24426e0a9b3dSArnaldo Carvalho de Melo * We already have the kernel maps, put in place via perf_session__create_kernel_maps() 24436e0a9b3dSArnaldo Carvalho de Melo * no need to add them twice. 24446e0a9b3dSArnaldo Carvalho de Melo */ 24456e0a9b3dSArnaldo Carvalho de Melo if (!(event->header.misc & PERF_RECORD_MISC_USER)) 24466e0a9b3dSArnaldo Carvalho de Melo return 0; 24476e0a9b3dSArnaldo Carvalho de Melo 24486e0a9b3dSArnaldo Carvalho de Melo return perf_event__process_mmap2(tool, event, sample, machine); 24496e0a9b3dSArnaldo Carvalho de Melo } 24506e0a9b3dSArnaldo Carvalho de Melo 245166286ed3SAdrian Hunter static int process_timestamp_boundary(struct perf_tool *tool, 245266286ed3SAdrian Hunter union perf_event *event __maybe_unused, 245366286ed3SAdrian Hunter struct perf_sample *sample, 245466286ed3SAdrian Hunter struct machine *machine __maybe_unused) 245566286ed3SAdrian Hunter { 245666286ed3SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 245766286ed3SAdrian Hunter 245866286ed3SAdrian Hunter set_timestamp_boundary(rec, sample->time); 245966286ed3SAdrian Hunter return 0; 246066286ed3SAdrian Hunter } 246166286ed3SAdrian Hunter 246241b740b6SNamhyung Kim static int parse_record_synth_option(const struct option *opt, 246341b740b6SNamhyung Kim const char *str, 246441b740b6SNamhyung Kim int unset __maybe_unused) 246541b740b6SNamhyung Kim { 246641b740b6SNamhyung Kim struct record_opts *opts = opt->value; 246741b740b6SNamhyung Kim char *p = strdup(str); 246841b740b6SNamhyung Kim 246941b740b6SNamhyung Kim if (p == NULL) 247041b740b6SNamhyung Kim return -1; 247141b740b6SNamhyung Kim 247241b740b6SNamhyung Kim opts->synth = parse_synth_opt(p); 247341b740b6SNamhyung Kim free(p); 247441b740b6SNamhyung Kim 247541b740b6SNamhyung Kim if (opts->synth < 0) { 247641b740b6SNamhyung Kim pr_err("Invalid synth option: %s\n", str); 247741b740b6SNamhyung Kim return -1; 247841b740b6SNamhyung Kim } 247941b740b6SNamhyung Kim return 0; 248041b740b6SNamhyung Kim } 248141b740b6SNamhyung Kim 2482d20deb64SArnaldo Carvalho de Melo /* 24838c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 24848c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 2485d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 2486d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 2487d20deb64SArnaldo Carvalho de Melo * 2488d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 2489d20deb64SArnaldo Carvalho de Melo * 2490d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 2491d20deb64SArnaldo Carvalho de Melo */ 24928c6f45a7SArnaldo Carvalho de Melo static struct record record = { 2493d20deb64SArnaldo Carvalho de Melo .opts = { 24948affc2b8SAndi Kleen .sample_time = true, 2495d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 2496d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 2497d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 2498447a6013SArnaldo Carvalho de Melo .freq = 4000, 2499d1cb9fceSNamhyung Kim .target = { 2500d1cb9fceSNamhyung Kim .uses_mmap = true, 25013aa5939dSAdrian Hunter .default_per_cpu = true, 2502d1cb9fceSNamhyung Kim }, 2503470530bbSAlexey Budankov .mmap_flush = MMAP_FLUSH_DEFAULT, 2504d99c22eaSStephane Eranian .nr_threads_synthesize = 1, 25051d078ccbSAlexey Budankov .ctl_fd = -1, 25061d078ccbSAlexey Budankov .ctl_fd_ack = -1, 250741b740b6SNamhyung Kim .synth = PERF_SYNTH_ALL, 2508d20deb64SArnaldo Carvalho de Melo }, 2509e3d59112SNamhyung Kim .tool = { 2510e3d59112SNamhyung Kim .sample = process_sample_event, 2511e3d59112SNamhyung Kim .fork = perf_event__process_fork, 2512cca8482cSAdrian Hunter .exit = perf_event__process_exit, 2513e3d59112SNamhyung Kim .comm = perf_event__process_comm, 2514f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces, 25156e0a9b3dSArnaldo Carvalho de Melo .mmap = build_id__process_mmap, 25166e0a9b3dSArnaldo Carvalho de Melo .mmap2 = build_id__process_mmap2, 251766286ed3SAdrian Hunter .itrace_start = process_timestamp_boundary, 251866286ed3SAdrian Hunter .aux = process_timestamp_boundary, 2519cca8482cSAdrian Hunter .ordered_events = true, 2520e3d59112SNamhyung Kim }, 2521d20deb64SArnaldo Carvalho de Melo }; 25227865e817SFrederic Weisbecker 252376a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 252476a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 252561eaa3beSArnaldo Carvalho de Melo 25260aab2136SWang Nan static bool dry_run; 25270aab2136SWang Nan 2528d20deb64SArnaldo Carvalho de Melo /* 2529d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 2530d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 2531b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 25327b392ef0SArnaldo Carvalho de Melo * evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 2533d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 2534d20deb64SArnaldo Carvalho de Melo */ 2535efd21307SJiri Olsa static struct option __record_options[] = { 2536d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 253786470930SIngo Molnar "event selector. use 'perf list' to list available events", 2538f120f9d5SJiri Olsa parse_events_option), 2539d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 2540c171b552SLi Zefan "event filter", parse_filter), 25414ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 25424ba1faa1SWang Nan NULL, "don't record events from perf itself", 25434ba1faa1SWang Nan exclude_perf), 2544bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 2545d6d901c2SZhang, Yanmin "record events on existing process id"), 2546bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 2547d6d901c2SZhang, Yanmin "record events on existing thread id"), 2548d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 254986470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 2550509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 2551acac03faSKirill Smelkov "collect data without buffering"), 2552d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 2553daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 2554bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 255586470930SIngo Molnar "system-wide collection from all CPUs"), 2556bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 2557c45c6ea2SStephane Eranian "list of cpus to monitor"), 2558d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 25592d4f2799SJiri Olsa OPT_STRING('o', "output", &record.data.path, "file", 256086470930SIngo Molnar "output file name"), 256169e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 256269e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 25632e6cdf99SStephane Eranian "child tasks do not inherit counters"), 25644ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 25654ea648aeSWang Nan "synthesize non-sample events at the end of output"), 2566626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 2567a060c1f1SWei Li OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "do not record bpf events"), 2568b09c2364SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 2569b09c2364SArnaldo Carvalho de Melo "Fail if the specified frequency can't be used"), 257067230479SArnaldo Carvalho de Melo OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 257167230479SArnaldo Carvalho de Melo "profile at this frequency", 257267230479SArnaldo Carvalho de Melo record__parse_freq), 2573e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 2574e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 2575e9db1310SAdrian Hunter record__parse_mmap_pages), 2576470530bbSAlexey Budankov OPT_CALLBACK(0, "mmap-flush", &record.opts, "number", 2577470530bbSAlexey Budankov "Minimal number of bytes that is extracted from mmap data pages (default: 1)", 2578470530bbSAlexey Budankov record__mmap_flush_parse), 2579d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 258043bece79SLin Ming "put the counters into a counter group"), 25812ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 258209b0fd45SJiri Olsa NULL, "enables call-graph recording" , 258309b0fd45SJiri Olsa &record_callchain_opt), 258409b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 258576a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 258609b0fd45SJiri Olsa &record_parse_callchain_opt), 2587c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 25883da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 2589b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 2590d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 2591649c48a9SPeter Zijlstra "per thread counts"), 259256100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 25933b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 25943b0a5daaSKan Liang "Record the sample physical addresses"), 2595542b88fdSKan Liang OPT_BOOLEAN(0, "data-page-size", &record.opts.sample_data_page_size, 2596542b88fdSKan Liang "Record the sampled data address data page size"), 2597c1de7f3dSKan Liang OPT_BOOLEAN(0, "code-page-size", &record.opts.sample_code_page_size, 2598c1de7f3dSKan Liang "Record the sampled code address (ip) page size"), 2599b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 26003abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 26013abebc55SAdrian Hunter &record.opts.sample_time_set, 26023abebc55SAdrian Hunter "Record the sample timestamps"), 2603f290aa1fSJiri Olsa OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set, 2604f290aa1fSJiri Olsa "Record the sample period"), 2605d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 2606649c48a9SPeter Zijlstra "don't sample"), 2607d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 2608d2db9a98SWang Nan &record.no_buildid_cache_set, 2609a1ac1d3cSStephane Eranian "do not update the buildid cache"), 2610d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 2611d2db9a98SWang Nan &record.no_buildid_set, 2612baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 2613d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 2614023695d9SStephane Eranian "monitor event in cgroup name only", 2615023695d9SStephane Eranian parse_cgroups), 261668cd3b45SAlexey Budankov OPT_INTEGER('D', "delay", &record.opts.initial_delay, 261768cd3b45SAlexey Budankov "ms to wait before starting measurement after program start (-1: start with events disabled)"), 2618eeb399b5SAdrian Hunter OPT_BOOLEAN(0, "kcore", &record.opts.kcore, "copy /proc/kcore"), 2619bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 2620bea03405SNamhyung Kim "user to profile"), 2621a5aabdacSStephane Eranian 2622a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 2623a5aabdacSStephane Eranian "branch any", "sample any taken branches", 2624a5aabdacSStephane Eranian parse_branch_stack), 2625a5aabdacSStephane Eranian 2626a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 2627a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 2628bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 262905484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 263005484298SAndi Kleen "sample by weight (on special events only)"), 2631475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 2632475eeab9SAndi Kleen "sample transaction flags (special events only)"), 26333aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 26343aa5939dSAdrian Hunter "use per-thread mmaps"), 2635bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 2636bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 2637aeea9062SKan Liang " use '-I?' to list register names", parse_intr_regs), 263884c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 263984c41742SAndi Kleen "sample selected machine registers on interrupt," 2640aeea9062SKan Liang " use '--user-regs=?' to list register names", parse_user_regs), 264185c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 264285c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 2643814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 2644814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 2645814c8c38SPeter Zijlstra parse_clockid), 26462dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 26472dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 2648c0a6de06SAdrian Hunter OPT_STRING_OPTARG(0, "aux-sample", &record.opts.auxtrace_sample_opts, 2649c0a6de06SAdrian Hunter "opts", "sample AUX area", ""), 26503fcb10e4SMark Drayton OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout, 26519d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 2652f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 2653f3b3614aSHari Bathini "Record namespaces events"), 26548fb4b679SNamhyung Kim OPT_BOOLEAN(0, "all-cgroups", &record.opts.record_cgroup, 26558fb4b679SNamhyung Kim "Record cgroup events"), 265616b4b4e1SAdrian Hunter OPT_BOOLEAN_SET(0, "switch-events", &record.opts.record_switch_events, 265716b4b4e1SAdrian Hunter &record.opts.record_switch_events_set, 2658b757bb09SAdrian Hunter "Record context switch events"), 265985723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 266085723885SJiri Olsa "Configure all used events to run in kernel space.", 266185723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 266285723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 266385723885SJiri Olsa "Configure all used events to run in user space.", 266485723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 266553651b28Syuzhoujian OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains, 266653651b28Syuzhoujian "collect kernel callchains"), 266753651b28Syuzhoujian OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains, 266853651b28Syuzhoujian "collect user callchains"), 266971dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 267071dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 267171dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 267271dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 26737efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 26747efe0e03SHe Kuang "file", "vmlinux pathname"), 26756156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 26766156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 2677e29386c8SJiri Olsa OPT_BOOLEAN(0, "buildid-mmap", &record.buildid_mmap, 2678e29386c8SJiri Olsa "Record build-id in map events"), 2679ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 2680ecfd7a9cSWang Nan "append timestamp to output filename"), 268168588bafSJin Yao OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 268268588bafSJin Yao "Record timestamp boundary (time of first/last samples)"), 2683cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 2684c38dab7dSAndi Kleen &record.switch_output.set, "signal or size[BKMG] or time[smhd]", 2685c38dab7dSAndi Kleen "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold", 2686dc0c6127SJiri Olsa "signal"), 2687899e5ffbSArnaldo Carvalho de Melo OPT_CALLBACK_SET(0, "switch-output-event", &record.sb_evlist, &record.switch_output_event_set, "switch output event", 2688899e5ffbSArnaldo Carvalho de Melo "switch output event selector. use 'perf list' to list available events", 2689899e5ffbSArnaldo Carvalho de Melo parse_events_option_new_evlist), 269003724b2eSAndi Kleen OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, 269103724b2eSAndi Kleen "Limit number of switch output generated files"), 26920aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 26930aab2136SWang Nan "Parse options then exit"), 2694d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 269593f20c0fSAlexey Budankov OPT_CALLBACK_OPTARG(0, "aio", &record.opts, 269693f20c0fSAlexey Budankov &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)", 2697d3d1af6fSAlexey Budankov record__aio_parse), 2698d3d1af6fSAlexey Budankov #endif 2699f4fe11b7SAlexey Budankov OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", 2700f4fe11b7SAlexey Budankov "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", 2701f4fe11b7SAlexey Budankov record__parse_affinity), 2702504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT 2703504c1ad1SAlexey Budankov OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default, 2704504c1ad1SAlexey Budankov "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)", 2705504c1ad1SAlexey Budankov record__parse_comp_level), 2706504c1ad1SAlexey Budankov #endif 27076d575816SJiwei Sun OPT_CALLBACK(0, "max-size", &record.output_max_size, 27086d575816SJiwei Sun "size", "Limit the maximum size of the output file", parse_output_max_size), 2709d99c22eaSStephane Eranian OPT_UINTEGER(0, "num-thread-synthesize", 2710d99c22eaSStephane Eranian &record.opts.nr_threads_synthesize, 2711d99c22eaSStephane Eranian "number of threads to run for event synthesis"), 271270943490SStephane Eranian #ifdef HAVE_LIBPFM 271370943490SStephane Eranian OPT_CALLBACK(0, "pfm-events", &record.evlist, "event", 271470943490SStephane Eranian "libpfm4 event selector. use 'perf list' to list available events", 271570943490SStephane Eranian parse_libpfm_events_option), 271670943490SStephane Eranian #endif 2717a8fcbd26SAdrian Hunter OPT_CALLBACK(0, "control", &record.opts, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]", 2718d20aff15SAdrian Hunter "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events,\n" 2719d20aff15SAdrian Hunter "\t\t\t 'snapshot': AUX area tracing snapshot).\n" 2720a8fcbd26SAdrian Hunter "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n" 2721a8fcbd26SAdrian Hunter "\t\t\t Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.", 27221d078ccbSAlexey Budankov parse_control_option), 272341b740b6SNamhyung Kim OPT_CALLBACK(0, "synth", &record.opts, "no|all|task|mmap|cgroup", 272441b740b6SNamhyung Kim "Fine-tune event synthesis: default=all", parse_record_synth_option), 27259bce13eaSJiri Olsa OPT_STRING_OPTARG_SET(0, "debuginfod", &record.debuginfod.urls, 27269bce13eaSJiri Olsa &record.debuginfod.set, "debuginfod urls", 27279bce13eaSJiri Olsa "Enable debuginfod data retrieval from DEBUGINFOD_URLS or specified urls", 27289bce13eaSJiri Olsa "system"), 272986470930SIngo Molnar OPT_END() 273086470930SIngo Molnar }; 273186470930SIngo Molnar 2732e5b2c207SNamhyung Kim struct option *record_options = __record_options; 2733e5b2c207SNamhyung Kim 2734*7954f716SAlexey Bayduraev static void record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus) 2735*7954f716SAlexey Bayduraev { 2736*7954f716SAlexey Bayduraev int c; 2737*7954f716SAlexey Bayduraev 2738*7954f716SAlexey Bayduraev for (c = 0; c < cpus->nr; c++) 2739*7954f716SAlexey Bayduraev set_bit(cpus->map[c].cpu, mask->bits); 2740*7954f716SAlexey Bayduraev } 2741*7954f716SAlexey Bayduraev 2742*7954f716SAlexey Bayduraev static void record__free_thread_masks(struct record *rec, int nr_threads) 2743*7954f716SAlexey Bayduraev { 2744*7954f716SAlexey Bayduraev int t; 2745*7954f716SAlexey Bayduraev 2746*7954f716SAlexey Bayduraev if (rec->thread_masks) 2747*7954f716SAlexey Bayduraev for (t = 0; t < nr_threads; t++) 2748*7954f716SAlexey Bayduraev record__thread_mask_free(&rec->thread_masks[t]); 2749*7954f716SAlexey Bayduraev 2750*7954f716SAlexey Bayduraev zfree(&rec->thread_masks); 2751*7954f716SAlexey Bayduraev } 2752*7954f716SAlexey Bayduraev 2753*7954f716SAlexey Bayduraev static int record__alloc_thread_masks(struct record *rec, int nr_threads, int nr_bits) 2754*7954f716SAlexey Bayduraev { 2755*7954f716SAlexey Bayduraev int t, ret; 2756*7954f716SAlexey Bayduraev 2757*7954f716SAlexey Bayduraev rec->thread_masks = zalloc(nr_threads * sizeof(*(rec->thread_masks))); 2758*7954f716SAlexey Bayduraev if (!rec->thread_masks) { 2759*7954f716SAlexey Bayduraev pr_err("Failed to allocate thread masks\n"); 2760*7954f716SAlexey Bayduraev return -ENOMEM; 2761*7954f716SAlexey Bayduraev } 2762*7954f716SAlexey Bayduraev 2763*7954f716SAlexey Bayduraev for (t = 0; t < nr_threads; t++) { 2764*7954f716SAlexey Bayduraev ret = record__thread_mask_alloc(&rec->thread_masks[t], nr_bits); 2765*7954f716SAlexey Bayduraev if (ret) { 2766*7954f716SAlexey Bayduraev pr_err("Failed to allocate thread masks[%d]\n", t); 2767*7954f716SAlexey Bayduraev goto out_free; 2768*7954f716SAlexey Bayduraev } 2769*7954f716SAlexey Bayduraev } 2770*7954f716SAlexey Bayduraev 2771*7954f716SAlexey Bayduraev return 0; 2772*7954f716SAlexey Bayduraev 2773*7954f716SAlexey Bayduraev out_free: 2774*7954f716SAlexey Bayduraev record__free_thread_masks(rec, nr_threads); 2775*7954f716SAlexey Bayduraev 2776*7954f716SAlexey Bayduraev return ret; 2777*7954f716SAlexey Bayduraev } 2778*7954f716SAlexey Bayduraev 2779*7954f716SAlexey Bayduraev static int record__init_thread_default_masks(struct record *rec, struct perf_cpu_map *cpus) 2780*7954f716SAlexey Bayduraev { 2781*7954f716SAlexey Bayduraev int ret; 2782*7954f716SAlexey Bayduraev 2783*7954f716SAlexey Bayduraev ret = record__alloc_thread_masks(rec, 1, cpu__max_cpu().cpu); 2784*7954f716SAlexey Bayduraev if (ret) 2785*7954f716SAlexey Bayduraev return ret; 2786*7954f716SAlexey Bayduraev 2787*7954f716SAlexey Bayduraev record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus); 2788*7954f716SAlexey Bayduraev 2789*7954f716SAlexey Bayduraev rec->nr_threads = 1; 2790*7954f716SAlexey Bayduraev 2791*7954f716SAlexey Bayduraev return 0; 2792*7954f716SAlexey Bayduraev } 2793*7954f716SAlexey Bayduraev 2794*7954f716SAlexey Bayduraev static int record__init_thread_masks(struct record *rec) 2795*7954f716SAlexey Bayduraev { 2796*7954f716SAlexey Bayduraev struct perf_cpu_map *cpus = rec->evlist->core.cpus; 2797*7954f716SAlexey Bayduraev 2798*7954f716SAlexey Bayduraev return record__init_thread_default_masks(rec, cpus); 2799*7954f716SAlexey Bayduraev } 2800*7954f716SAlexey Bayduraev 2801b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv) 280286470930SIngo Molnar { 2803ef149c25SAdrian Hunter int err; 28048c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 280516ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 280686470930SIngo Molnar 280767230479SArnaldo Carvalho de Melo setlocale(LC_ALL, ""); 280867230479SArnaldo Carvalho de Melo 280948e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 281048e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 281148e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 281248e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 281348e1cab1SWang Nan # undef set_nobuild 281448e1cab1SWang Nan #endif 281548e1cab1SWang Nan 28167efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 28177efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 28187efe0e03SHe Kuang # define REASON "NO_DWARF=1" 28197efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 28207efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 28217efe0e03SHe Kuang # else 28227efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 28237efe0e03SHe Kuang # endif 28247efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 28257efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 28267efe0e03SHe Kuang # undef set_nobuild 28277efe0e03SHe Kuang # undef REASON 28287efe0e03SHe Kuang #endif 28297efe0e03SHe Kuang 28309d2ed645SAlexey Budankov rec->opts.affinity = PERF_AFFINITY_SYS; 28319d2ed645SAlexey Budankov 28320f98b11cSJiri Olsa rec->evlist = evlist__new(); 28333e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 2834361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 2835361c99a6SArnaldo Carvalho de Melo 2836ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec); 2837ecc4c561SArnaldo Carvalho de Melo if (err) 2838ecc4c561SArnaldo Carvalho de Melo return err; 2839eb853e80SJiri Olsa 2840bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 2841a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 284268ba3235SNamhyung Kim if (quiet) 284368ba3235SNamhyung Kim perf_quiet_option(); 2844483635a9SJiri Olsa 28457cc72553SJames Clark err = symbol__validate_sym_arguments(); 28467cc72553SJames Clark if (err) 28477cc72553SJames Clark return err; 28487cc72553SJames Clark 28499bce13eaSJiri Olsa perf_debuginfod_setup(&record.debuginfod); 28509bce13eaSJiri Olsa 2851483635a9SJiri Olsa /* Make system wide (-a) the default target. */ 2852602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 2853483635a9SJiri Olsa rec->opts.target.system_wide = true; 285486470930SIngo Molnar 2855bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 2856c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 2857c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 2858c7118369SNamhyung Kim 2859023695d9SStephane Eranian } 2860504c1ad1SAlexey Budankov 2861e29386c8SJiri Olsa if (rec->buildid_mmap) { 2862e29386c8SJiri Olsa if (!perf_can_record_build_id()) { 2863e29386c8SJiri Olsa pr_err("Failed: no support to record build id in mmap events, update your kernel.\n"); 2864e29386c8SJiri Olsa err = -EINVAL; 2865e29386c8SJiri Olsa goto out_opts; 2866e29386c8SJiri Olsa } 2867e29386c8SJiri Olsa pr_debug("Enabling build id in mmap2 events.\n"); 2868e29386c8SJiri Olsa /* Enable mmap build id synthesizing. */ 2869e29386c8SJiri Olsa symbol_conf.buildid_mmap2 = true; 2870e29386c8SJiri Olsa /* Enable perf_event_attr::build_id bit. */ 2871e29386c8SJiri Olsa rec->opts.build_id = true; 2872e29386c8SJiri Olsa /* Disable build id cache. */ 2873e29386c8SJiri Olsa rec->no_buildid = true; 2874e29386c8SJiri Olsa } 2875e29386c8SJiri Olsa 28764f2abe91SNamhyung Kim if (rec->opts.record_cgroup && !perf_can_record_cgroup()) { 28774f2abe91SNamhyung Kim pr_err("Kernel has no cgroup sampling support.\n"); 28784f2abe91SNamhyung Kim err = -EINVAL; 28794f2abe91SNamhyung Kim goto out_opts; 28804f2abe91SNamhyung Kim } 28814f2abe91SNamhyung Kim 2882eeb399b5SAdrian Hunter if (rec->opts.kcore) 2883eeb399b5SAdrian Hunter rec->data.is_dir = true; 2884eeb399b5SAdrian Hunter 2885504c1ad1SAlexey Budankov if (rec->opts.comp_level != 0) { 2886504c1ad1SAlexey Budankov pr_debug("Compression enabled, disabling build id collection at the end of the session.\n"); 2887504c1ad1SAlexey Budankov rec->no_buildid = true; 2888504c1ad1SAlexey Budankov } 2889504c1ad1SAlexey Budankov 2890b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 2891b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 2892c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 2893c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 2894a8fcbd26SAdrian Hunter err = -EINVAL; 2895a8fcbd26SAdrian Hunter goto out_opts; 2896b757bb09SAdrian Hunter } 2897023695d9SStephane Eranian 2898cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) { 2899cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0); 2900a8fcbd26SAdrian Hunter err = -EINVAL; 2901a8fcbd26SAdrian Hunter goto out_opts; 2902cb4e1ebbSJiri Olsa } 2903cb4e1ebbSJiri Olsa 2904bfacbe3bSJiri Olsa if (rec->switch_output.time) { 2905bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler); 2906bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 2907bfacbe3bSJiri Olsa } 2908bfacbe3bSJiri Olsa 290903724b2eSAndi Kleen if (rec->switch_output.num_files) { 291003724b2eSAndi Kleen rec->switch_output.filenames = calloc(sizeof(char *), 291103724b2eSAndi Kleen rec->switch_output.num_files); 2912a8fcbd26SAdrian Hunter if (!rec->switch_output.filenames) { 2913a8fcbd26SAdrian Hunter err = -EINVAL; 2914a8fcbd26SAdrian Hunter goto out_opts; 2915a8fcbd26SAdrian Hunter } 291603724b2eSAndi Kleen } 291703724b2eSAndi Kleen 29181b36c03eSAdrian Hunter /* 29191b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address 29201b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters(). 29211b36c03eSAdrian Hunter */ 29221b36c03eSAdrian Hunter symbol_conf.allow_aliases = true; 29231b36c03eSAdrian Hunter 29241b36c03eSAdrian Hunter symbol__init(NULL); 29251b36c03eSAdrian Hunter 29268384a260SAlexey Budankov if (rec->opts.affinity != PERF_AFFINITY_SYS) { 29276d18804bSIan Rogers rec->affinity_mask.nbits = cpu__max_cpu().cpu; 29287fc5b571SAndy Shevchenko rec->affinity_mask.bits = bitmap_zalloc(rec->affinity_mask.nbits); 29298384a260SAlexey Budankov if (!rec->affinity_mask.bits) { 29308384a260SAlexey Budankov pr_err("Failed to allocate thread mask for %zd cpus\n", rec->affinity_mask.nbits); 2931a8fcbd26SAdrian Hunter err = -ENOMEM; 2932a8fcbd26SAdrian Hunter goto out_opts; 29338384a260SAlexey Budankov } 29348384a260SAlexey Budankov pr_debug2("thread mask[%zd]: empty\n", rec->affinity_mask.nbits); 29358384a260SAlexey Budankov } 29368384a260SAlexey Budankov 29374b5ea3bdSAdrian Hunter err = record__auxtrace_init(rec); 29381b36c03eSAdrian Hunter if (err) 29391b36c03eSAdrian Hunter goto out; 29401b36c03eSAdrian Hunter 29410aab2136SWang Nan if (dry_run) 29425c01ad60SAdrian Hunter goto out; 29430aab2136SWang Nan 2944d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 2945d7888573SWang Nan if (err) { 2946d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 2947d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 2948d7888573SWang Nan errbuf); 29495c01ad60SAdrian Hunter goto out; 2950d7888573SWang Nan } 2951d7888573SWang Nan 2952ef149c25SAdrian Hunter err = -ENOMEM; 2953ef149c25SAdrian Hunter 29540c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 2955a1ac1d3cSStephane Eranian disable_buildid_cache(); 2956dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) { 29570c1d46a8SWang Nan /* 29580c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 29590c1d46a8SWang Nan * generation by default to reduce data file switching 29600c1d46a8SWang Nan * overhead. Still generate buildid if they are required 29610c1d46a8SWang Nan * explicitly using 29620c1d46a8SWang Nan * 296360437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \ 29640c1d46a8SWang Nan * --no-no-buildid-cache 29650c1d46a8SWang Nan * 29660c1d46a8SWang Nan * Following code equals to: 29670c1d46a8SWang Nan * 29680c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 29690c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 29700c1d46a8SWang Nan * disable_buildid_cache(); 29710c1d46a8SWang Nan */ 29720c1d46a8SWang Nan bool disable = true; 29730c1d46a8SWang Nan 29740c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 29750c1d46a8SWang Nan disable = false; 29760c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 29770c1d46a8SWang Nan disable = false; 29780c1d46a8SWang Nan if (disable) { 29790c1d46a8SWang Nan rec->no_buildid = true; 29800c1d46a8SWang Nan rec->no_buildid_cache = true; 29810c1d46a8SWang Nan disable_buildid_cache(); 29820c1d46a8SWang Nan } 29830c1d46a8SWang Nan } 2984655000e7SArnaldo Carvalho de Melo 29854ea648aeSWang Nan if (record.opts.overwrite) 29864ea648aeSWang Nan record.opts.tail_synthesize = true; 29874ea648aeSWang Nan 2988b53a0755SJin Yao if (rec->evlist->core.nr_entries == 0) { 2989b53a0755SJin Yao if (perf_pmu__has_hybrid()) { 2990b53a0755SJin Yao err = evlist__add_default_hybrid(rec->evlist, 2991b53a0755SJin Yao !record.opts.no_samples); 2992b53a0755SJin Yao } else { 2993b53a0755SJin Yao err = __evlist__add_default(rec->evlist, 2994b53a0755SJin Yao !record.opts.no_samples); 2995b53a0755SJin Yao } 2996b53a0755SJin Yao 2997b53a0755SJin Yao if (err < 0) { 299869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 2999394c01edSAdrian Hunter goto out; 3000bbd36e5eSPeter Zijlstra } 3001b53a0755SJin Yao } 300286470930SIngo Molnar 300369e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 300469e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 300569e7e5b0SAdrian Hunter 3006602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 300716ad2ffbSNamhyung Kim if (err) { 3008602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 3009c3dec27bSJiri Olsa ui__warning("%s\n", errbuf); 301016ad2ffbSNamhyung Kim } 30114bd0f2d2SNamhyung Kim 3012602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 301316ad2ffbSNamhyung Kim if (err) { 301416ad2ffbSNamhyung Kim int saved_errno = errno; 301516ad2ffbSNamhyung Kim 3016602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 30173780f488SNamhyung Kim ui__error("%s", errbuf); 301816ad2ffbSNamhyung Kim 301916ad2ffbSNamhyung Kim err = -saved_errno; 3020394c01edSAdrian Hunter goto out; 302116ad2ffbSNamhyung Kim } 30220d37aa34SArnaldo Carvalho de Melo 3023ca800068SMengting Zhang /* Enable ignoring missing threads when -u/-p option is defined. */ 3024ca800068SMengting Zhang rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; 302523dc4f15SJiri Olsa 30261d3351e6SJin Yao if (evlist__fix_hybrid_cpus(rec->evlist, rec->opts.target.cpu_list)) { 30271d3351e6SJin Yao pr_err("failed to use cpu list %s\n", 30281d3351e6SJin Yao rec->opts.target.cpu_list); 30291d3351e6SJin Yao goto out; 30301d3351e6SJin Yao } 30311d3351e6SJin Yao 30321d3351e6SJin Yao rec->opts.target.hybrid = perf_pmu__has_hybrid(); 30337248e308SAlexandre Truong 30347248e308SAlexandre Truong if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP) 30357248e308SAlexandre Truong arch__add_leaf_frame_record_opts(&rec->opts); 30367248e308SAlexandre Truong 303716ad2ffbSNamhyung Kim err = -ENOMEM; 30387748bb71SArnaldo Carvalho de Melo if (evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 3039dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 304069aad6f1SArnaldo Carvalho de Melo 3041ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 3042ef149c25SAdrian Hunter if (err) 3043394c01edSAdrian Hunter goto out; 3044ef149c25SAdrian Hunter 30456156681bSNamhyung Kim /* 30466156681bSNamhyung Kim * We take all buildids when the file contains 30476156681bSNamhyung Kim * AUX area tracing data because we do not decode the 30486156681bSNamhyung Kim * trace because it would take too long. 30496156681bSNamhyung Kim */ 30506156681bSNamhyung Kim if (rec->opts.full_auxtrace) 30516156681bSNamhyung Kim rec->buildid_all = true; 30526156681bSNamhyung Kim 3053246eba8eSAdrian Hunter if (rec->opts.text_poke) { 3054246eba8eSAdrian Hunter err = record__config_text_poke(rec->evlist); 3055246eba8eSAdrian Hunter if (err) { 3056246eba8eSAdrian Hunter pr_err("record__config_text_poke failed, error %d\n", err); 3057246eba8eSAdrian Hunter goto out; 3058246eba8eSAdrian Hunter } 3059246eba8eSAdrian Hunter } 3060246eba8eSAdrian Hunter 3061b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 306239d17dacSArnaldo Carvalho de Melo err = -EINVAL; 3063394c01edSAdrian Hunter goto out; 30647e4ff9e3SMike Galbraith } 30657e4ff9e3SMike Galbraith 3066*7954f716SAlexey Bayduraev err = record__init_thread_masks(rec); 3067*7954f716SAlexey Bayduraev if (err) { 3068*7954f716SAlexey Bayduraev pr_err("Failed to initialize parallel data streaming masks\n"); 3069*7954f716SAlexey Bayduraev goto out; 3070*7954f716SAlexey Bayduraev } 3071*7954f716SAlexey Bayduraev 307293f20c0fSAlexey Budankov if (rec->opts.nr_cblocks > nr_cblocks_max) 307393f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_max; 30745d7f4116SAlexey Budankov pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks); 3075d3d1af6fSAlexey Budankov 30769d2ed645SAlexey Budankov pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); 3077470530bbSAlexey Budankov pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); 30789d2ed645SAlexey Budankov 307951255a8aSAlexey Budankov if (rec->opts.comp_level > comp_level_max) 308051255a8aSAlexey Budankov rec->opts.comp_level = comp_level_max; 308151255a8aSAlexey Budankov pr_debug("comp level: %d\n", rec->opts.comp_level); 308251255a8aSAlexey Budankov 3083d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 3084394c01edSAdrian Hunter out: 30858384a260SAlexey Budankov bitmap_free(rec->affinity_mask.bits); 3086c12995a5SJiri Olsa evlist__delete(rec->evlist); 3087d65a458bSArnaldo Carvalho de Melo symbol__exit(); 3088ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 3089a8fcbd26SAdrian Hunter out_opts: 3090*7954f716SAlexey Bayduraev record__free_thread_masks(rec, rec->nr_threads); 3091*7954f716SAlexey Bayduraev rec->nr_threads = 0; 3092ee7fe31eSAdrian Hunter evlist__close_control(rec->opts.ctl_fd, rec->opts.ctl_fd_ack, &rec->opts.ctl_fd_close); 309339d17dacSArnaldo Carvalho de Melo return err; 309486470930SIngo Molnar } 30952dd6d8a1SAdrian Hunter 30962dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 30972dd6d8a1SAdrian Hunter { 3098dc0c6127SJiri Olsa struct record *rec = &record; 3099dc0c6127SJiri Olsa 3100d20aff15SAdrian Hunter hit_auxtrace_snapshot_trigger(rec); 31013c1cb7e3SWang Nan 3102dc0c6127SJiri Olsa if (switch_output_signal(rec)) 31033c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 31042dd6d8a1SAdrian Hunter } 3105bfacbe3bSJiri Olsa 3106bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused) 3107bfacbe3bSJiri Olsa { 3108bfacbe3bSJiri Olsa struct record *rec = &record; 3109bfacbe3bSJiri Olsa 3110bfacbe3bSJiri Olsa if (switch_output_time(rec)) 3111bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger); 3112bfacbe3bSJiri Olsa } 3113