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" 23aeb00b1aSArnaldo Carvalho de Melo #include "util/target.h" 2494c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2545694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 268d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 27aeb00b1aSArnaldo Carvalho de Melo #include "util/record.h" 28a12b51c4SPaul Mackerras #include "util/cpumap.h" 29fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 30f5fc1412SJiri Olsa #include "util/data.h" 31bcc84ec6SStephane Eranian #include "util/perf_regs.h" 32ef149c25SAdrian Hunter #include "util/auxtrace.h" 3346bc29b9SAdrian Hunter #include "util/tsc.h" 34f00898f4SAndi Kleen #include "util/parse-branch-options.h" 35bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3671dc2326SWang Nan #include "util/llvm-utils.h" 378690a2a7SWang Nan #include "util/bpf-loader.h" 385f9cf599SWang Nan #include "util/trigger.h" 39a074865eSWang Nan #include "util/perf-hooks.h" 40f13de660SAlexey Budankov #include "util/cpu-set-sched.h" 41ea49e01cSArnaldo Carvalho de Melo #include "util/synthetic-events.h" 42c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h" 4358db1d6eSArnaldo Carvalho de Melo #include "util/units.h" 447b612e29SSong Liu #include "util/bpf-event.h" 45d8871ea7SWang Nan #include "asm/bug.h" 46c1a604dfSArnaldo Carvalho de Melo #include "perf.h" 477c6a1c65SPeter Zijlstra 48a43783aeSArnaldo Carvalho de Melo #include <errno.h> 49fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 5067230479SArnaldo Carvalho de Melo #include <locale.h> 514208735dSArnaldo Carvalho de Melo #include <poll.h> 5286470930SIngo Molnar #include <unistd.h> 5386470930SIngo Molnar #include <sched.h> 549607ad3aSArnaldo Carvalho de Melo #include <signal.h> 55a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 564208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 576ef81c55SMamatha Inamdar #include <linux/err.h> 588520a98dSArnaldo Carvalho de Melo #include <linux/string.h> 590693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 60d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h> 6178da39faSBernhard Rosenkraenzer 621b43b704SJiri Olsa struct switch_output { 63dc0c6127SJiri Olsa bool enabled; 641b43b704SJiri Olsa bool signal; 65dc0c6127SJiri Olsa unsigned long size; 66bfacbe3bSJiri Olsa unsigned long time; 67cb4e1ebbSJiri Olsa const char *str; 68cb4e1ebbSJiri Olsa bool set; 6903724b2eSAndi Kleen char **filenames; 7003724b2eSAndi Kleen int num_files; 7103724b2eSAndi Kleen int cur_file; 721b43b704SJiri Olsa }; 731b43b704SJiri Olsa 748c6f45a7SArnaldo Carvalho de Melo struct record { 7545694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 76b4006796SArnaldo Carvalho de Melo struct record_opts opts; 77d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 788ceb41d7SJiri Olsa struct perf_data data; 79ef149c25SAdrian Hunter struct auxtrace_record *itr; 8063503dbaSJiri Olsa struct evlist *evlist; 81d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 82d20deb64SArnaldo Carvalho de Melo int realtime_prio; 83d20deb64SArnaldo Carvalho de Melo bool no_buildid; 84d2db9a98SWang Nan bool no_buildid_set; 85d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 86d2db9a98SWang Nan bool no_buildid_cache_set; 876156681bSNamhyung Kim bool buildid_all; 88ecfd7a9cSWang Nan bool timestamp_filename; 8968588bafSJin Yao bool timestamp_boundary; 901b43b704SJiri Olsa struct switch_output switch_output; 919f065194SYang Shi unsigned long long samples; 929d2ed645SAlexey Budankov cpu_set_t affinity_mask; 930f82ebc4SArnaldo Carvalho de Melo }; 9486470930SIngo Molnar 95dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started; 96dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 97dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger); 98dc0c6127SJiri Olsa 999d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = { 1009d2ed645SAlexey Budankov "SYS", "NODE", "CPU" 1019d2ed645SAlexey Budankov }; 1029d2ed645SAlexey Budankov 103dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec) 104dc0c6127SJiri Olsa { 105dc0c6127SJiri Olsa return rec->switch_output.signal && 106dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger); 107dc0c6127SJiri Olsa } 108dc0c6127SJiri Olsa 109dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec) 110dc0c6127SJiri Olsa { 111dc0c6127SJiri Olsa return rec->switch_output.size && 112dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) && 113dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size); 114dc0c6127SJiri Olsa } 115dc0c6127SJiri Olsa 116bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec) 117bfacbe3bSJiri Olsa { 118bfacbe3bSJiri Olsa return rec->switch_output.time && 119bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger); 120bfacbe3bSJiri Olsa } 121bfacbe3bSJiri Olsa 122ded2b8feSJiri Olsa static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused, 123ded2b8feSJiri Olsa void *bf, size_t size) 124f5970550SPeter Zijlstra { 125ded2b8feSJiri Olsa struct perf_data_file *file = &rec->session->data->file; 126ded2b8feSJiri Olsa 127ded2b8feSJiri Olsa if (perf_data_file__write(file, bf, size) < 0) { 1284f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 1298d3eca20SDavid Ahern return -1; 1308d3eca20SDavid Ahern } 131f5970550SPeter Zijlstra 132cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 133dc0c6127SJiri Olsa 134dc0c6127SJiri Olsa if (switch_output_size(rec)) 135dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger); 136dc0c6127SJiri Olsa 1378d3eca20SDavid Ahern return 0; 138f5970550SPeter Zijlstra } 139f5970550SPeter Zijlstra 140ef781128SAlexey Budankov static int record__aio_enabled(struct record *rec); 141ef781128SAlexey Budankov static int record__comp_enabled(struct record *rec); 1425d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 1435d7f4116SAlexey Budankov void *src, size_t src_size); 1445d7f4116SAlexey Budankov 145d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 146d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd, 147d3d1af6fSAlexey Budankov void *buf, size_t size, off_t off) 148d3d1af6fSAlexey Budankov { 149d3d1af6fSAlexey Budankov int rc; 150d3d1af6fSAlexey Budankov 151d3d1af6fSAlexey Budankov cblock->aio_fildes = trace_fd; 152d3d1af6fSAlexey Budankov cblock->aio_buf = buf; 153d3d1af6fSAlexey Budankov cblock->aio_nbytes = size; 154d3d1af6fSAlexey Budankov cblock->aio_offset = off; 155d3d1af6fSAlexey Budankov cblock->aio_sigevent.sigev_notify = SIGEV_NONE; 156d3d1af6fSAlexey Budankov 157d3d1af6fSAlexey Budankov do { 158d3d1af6fSAlexey Budankov rc = aio_write(cblock); 159d3d1af6fSAlexey Budankov if (rc == 0) { 160d3d1af6fSAlexey Budankov break; 161d3d1af6fSAlexey Budankov } else if (errno != EAGAIN) { 162d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 163d3d1af6fSAlexey Budankov pr_err("failed to queue perf data, error: %m\n"); 164d3d1af6fSAlexey Budankov break; 165d3d1af6fSAlexey Budankov } 166d3d1af6fSAlexey Budankov } while (1); 167d3d1af6fSAlexey Budankov 168d3d1af6fSAlexey Budankov return rc; 169d3d1af6fSAlexey Budankov } 170d3d1af6fSAlexey Budankov 171d3d1af6fSAlexey Budankov static int record__aio_complete(struct perf_mmap *md, struct aiocb *cblock) 172d3d1af6fSAlexey Budankov { 173d3d1af6fSAlexey Budankov void *rem_buf; 174d3d1af6fSAlexey Budankov off_t rem_off; 175d3d1af6fSAlexey Budankov size_t rem_size; 176d3d1af6fSAlexey Budankov int rc, aio_errno; 177d3d1af6fSAlexey Budankov ssize_t aio_ret, written; 178d3d1af6fSAlexey Budankov 179d3d1af6fSAlexey Budankov aio_errno = aio_error(cblock); 180d3d1af6fSAlexey Budankov if (aio_errno == EINPROGRESS) 181d3d1af6fSAlexey Budankov return 0; 182d3d1af6fSAlexey Budankov 183d3d1af6fSAlexey Budankov written = aio_ret = aio_return(cblock); 184d3d1af6fSAlexey Budankov if (aio_ret < 0) { 185d3d1af6fSAlexey Budankov if (aio_errno != EINTR) 186d3d1af6fSAlexey Budankov pr_err("failed to write perf data, error: %m\n"); 187d3d1af6fSAlexey Budankov written = 0; 188d3d1af6fSAlexey Budankov } 189d3d1af6fSAlexey Budankov 190d3d1af6fSAlexey Budankov rem_size = cblock->aio_nbytes - written; 191d3d1af6fSAlexey Budankov 192d3d1af6fSAlexey Budankov if (rem_size == 0) { 193d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 194d3d1af6fSAlexey Budankov /* 195ef781128SAlexey Budankov * md->refcount is incremented in record__aio_pushfn() for 196ef781128SAlexey Budankov * every aio write request started in record__aio_push() so 197ef781128SAlexey Budankov * decrement it because the request is now complete. 198d3d1af6fSAlexey Budankov */ 199d3d1af6fSAlexey Budankov perf_mmap__put(md); 200d3d1af6fSAlexey Budankov rc = 1; 201d3d1af6fSAlexey Budankov } else { 202d3d1af6fSAlexey Budankov /* 203d3d1af6fSAlexey Budankov * aio write request may require restart with the 204d3d1af6fSAlexey Budankov * reminder if the kernel didn't write whole 205d3d1af6fSAlexey Budankov * chunk at once. 206d3d1af6fSAlexey Budankov */ 207d3d1af6fSAlexey Budankov rem_off = cblock->aio_offset + written; 208d3d1af6fSAlexey Budankov rem_buf = (void *)(cblock->aio_buf + written); 209d3d1af6fSAlexey Budankov record__aio_write(cblock, cblock->aio_fildes, 210d3d1af6fSAlexey Budankov rem_buf, rem_size, rem_off); 211d3d1af6fSAlexey Budankov rc = 0; 212d3d1af6fSAlexey Budankov } 213d3d1af6fSAlexey Budankov 214d3d1af6fSAlexey Budankov return rc; 215d3d1af6fSAlexey Budankov } 216d3d1af6fSAlexey Budankov 21793f20c0fSAlexey Budankov static int record__aio_sync(struct perf_mmap *md, bool sync_all) 218d3d1af6fSAlexey Budankov { 21993f20c0fSAlexey Budankov struct aiocb **aiocb = md->aio.aiocb; 22093f20c0fSAlexey Budankov struct aiocb *cblocks = md->aio.cblocks; 221d3d1af6fSAlexey Budankov struct timespec timeout = { 0, 1000 * 1000 * 1 }; /* 1ms */ 22293f20c0fSAlexey Budankov int i, do_suspend; 223d3d1af6fSAlexey Budankov 224d3d1af6fSAlexey Budankov do { 22593f20c0fSAlexey Budankov do_suspend = 0; 22693f20c0fSAlexey Budankov for (i = 0; i < md->aio.nr_cblocks; ++i) { 22793f20c0fSAlexey Budankov if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) { 22893f20c0fSAlexey Budankov if (sync_all) 22993f20c0fSAlexey Budankov aiocb[i] = NULL; 23093f20c0fSAlexey Budankov else 23193f20c0fSAlexey Budankov return i; 23293f20c0fSAlexey Budankov } else { 23393f20c0fSAlexey Budankov /* 23493f20c0fSAlexey Budankov * Started aio write is not complete yet 23593f20c0fSAlexey Budankov * so it has to be waited before the 23693f20c0fSAlexey Budankov * next allocation. 23793f20c0fSAlexey Budankov */ 23893f20c0fSAlexey Budankov aiocb[i] = &cblocks[i]; 23993f20c0fSAlexey Budankov do_suspend = 1; 24093f20c0fSAlexey Budankov } 24193f20c0fSAlexey Budankov } 24293f20c0fSAlexey Budankov if (!do_suspend) 24393f20c0fSAlexey Budankov return -1; 244d3d1af6fSAlexey Budankov 24593f20c0fSAlexey Budankov while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) { 246d3d1af6fSAlexey Budankov if (!(errno == EAGAIN || errno == EINTR)) 247d3d1af6fSAlexey Budankov pr_err("failed to sync perf data, error: %m\n"); 248d3d1af6fSAlexey Budankov } 249d3d1af6fSAlexey Budankov } while (1); 250d3d1af6fSAlexey Budankov } 251d3d1af6fSAlexey Budankov 252ef781128SAlexey Budankov struct record_aio { 253ef781128SAlexey Budankov struct record *rec; 254ef781128SAlexey Budankov void *data; 255ef781128SAlexey Budankov size_t size; 256ef781128SAlexey Budankov }; 257ef781128SAlexey Budankov 258ef781128SAlexey Budankov static int record__aio_pushfn(struct perf_mmap *map, void *to, void *buf, size_t size) 259d3d1af6fSAlexey Budankov { 260ef781128SAlexey Budankov struct record_aio *aio = to; 261ef781128SAlexey Budankov 262ef781128SAlexey Budankov /* 263ef781128SAlexey Budankov * map->base data pointed by buf is copied into free map->aio.data[] buffer 264ef781128SAlexey Budankov * to release space in the kernel buffer as fast as possible, calling 265ef781128SAlexey Budankov * perf_mmap__consume() from perf_mmap__push() function. 266ef781128SAlexey Budankov * 267ef781128SAlexey Budankov * That lets the kernel to proceed with storing more profiling data into 268ef781128SAlexey Budankov * the kernel buffer earlier than other per-cpu kernel buffers are handled. 269ef781128SAlexey Budankov * 270ef781128SAlexey Budankov * Coping can be done in two steps in case the chunk of profiling data 271ef781128SAlexey Budankov * crosses the upper bound of the kernel buffer. In this case we first move 272ef781128SAlexey Budankov * part of data from map->start till the upper bound and then the reminder 273ef781128SAlexey Budankov * from the beginning of the kernel buffer till the end of the data chunk. 274ef781128SAlexey Budankov */ 275ef781128SAlexey Budankov 276ef781128SAlexey Budankov if (record__comp_enabled(aio->rec)) { 277ef781128SAlexey Budankov size = zstd_compress(aio->rec->session, aio->data + aio->size, 278ef781128SAlexey Budankov perf_mmap__mmap_len(map) - aio->size, 279ef781128SAlexey Budankov buf, size); 280ef781128SAlexey Budankov } else { 281ef781128SAlexey Budankov memcpy(aio->data + aio->size, buf, size); 282ef781128SAlexey Budankov } 283ef781128SAlexey Budankov 284ef781128SAlexey Budankov if (!aio->size) { 285ef781128SAlexey Budankov /* 286ef781128SAlexey Budankov * Increment map->refcount to guard map->aio.data[] buffer 287ef781128SAlexey Budankov * from premature deallocation because map object can be 288ef781128SAlexey Budankov * released earlier than aio write request started on 289ef781128SAlexey Budankov * map->aio.data[] buffer is complete. 290ef781128SAlexey Budankov * 291ef781128SAlexey Budankov * perf_mmap__put() is done at record__aio_complete() 292ef781128SAlexey Budankov * after started aio request completion or at record__aio_push() 293ef781128SAlexey Budankov * if the request failed to start. 294ef781128SAlexey Budankov */ 295ef781128SAlexey Budankov perf_mmap__get(map); 296ef781128SAlexey Budankov } 297ef781128SAlexey Budankov 298ef781128SAlexey Budankov aio->size += size; 299ef781128SAlexey Budankov 300ef781128SAlexey Budankov return size; 301ef781128SAlexey Budankov } 302ef781128SAlexey Budankov 303ef781128SAlexey Budankov static int record__aio_push(struct record *rec, struct perf_mmap *map, off_t *off) 304ef781128SAlexey Budankov { 305ef781128SAlexey Budankov int ret, idx; 306ef781128SAlexey Budankov int trace_fd = rec->session->data->file.fd; 307ef781128SAlexey Budankov struct record_aio aio = { .rec = rec, .size = 0 }; 308ef781128SAlexey Budankov 309ef781128SAlexey Budankov /* 310ef781128SAlexey Budankov * Call record__aio_sync() to wait till map->aio.data[] buffer 311ef781128SAlexey Budankov * becomes available after previous aio write operation. 312ef781128SAlexey Budankov */ 313ef781128SAlexey Budankov 314ef781128SAlexey Budankov idx = record__aio_sync(map, false); 315ef781128SAlexey Budankov aio.data = map->aio.data[idx]; 316ef781128SAlexey Budankov ret = perf_mmap__push(map, &aio, record__aio_pushfn); 317ef781128SAlexey Budankov if (ret != 0) /* ret > 0 - no data, ret < 0 - error */ 318ef781128SAlexey Budankov return ret; 319d3d1af6fSAlexey Budankov 320d3d1af6fSAlexey Budankov rec->samples++; 321ef781128SAlexey Budankov ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off); 322d3d1af6fSAlexey Budankov if (!ret) { 323ef781128SAlexey Budankov *off += aio.size; 324ef781128SAlexey Budankov rec->bytes_written += aio.size; 325d3d1af6fSAlexey Budankov if (switch_output_size(rec)) 326d3d1af6fSAlexey Budankov trigger_hit(&switch_output_trigger); 327ef781128SAlexey Budankov } else { 328ef781128SAlexey Budankov /* 329ef781128SAlexey Budankov * Decrement map->refcount incremented in record__aio_pushfn() 330ef781128SAlexey Budankov * back if record__aio_write() operation failed to start, otherwise 331ef781128SAlexey Budankov * map->refcount is decremented in record__aio_complete() after 332ef781128SAlexey Budankov * aio write operation finishes successfully. 333ef781128SAlexey Budankov */ 334ef781128SAlexey Budankov perf_mmap__put(map); 335d3d1af6fSAlexey Budankov } 336d3d1af6fSAlexey Budankov 337d3d1af6fSAlexey Budankov return ret; 338d3d1af6fSAlexey Budankov } 339d3d1af6fSAlexey Budankov 340d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd) 341d3d1af6fSAlexey Budankov { 342d3d1af6fSAlexey Budankov return lseek(trace_fd, 0, SEEK_CUR); 343d3d1af6fSAlexey Budankov } 344d3d1af6fSAlexey Budankov 345d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos) 346d3d1af6fSAlexey Budankov { 347d3d1af6fSAlexey Budankov lseek(trace_fd, pos, SEEK_SET); 348d3d1af6fSAlexey Budankov } 349d3d1af6fSAlexey Budankov 350d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec) 351d3d1af6fSAlexey Budankov { 352d3d1af6fSAlexey Budankov int i; 35363503dbaSJiri Olsa struct evlist *evlist = rec->evlist; 354d3d1af6fSAlexey Budankov struct perf_mmap *maps = evlist->mmap; 355d3d1af6fSAlexey Budankov 356ef781128SAlexey Budankov if (!record__aio_enabled(rec)) 357d3d1af6fSAlexey Budankov return; 358d3d1af6fSAlexey Budankov 359d3d1af6fSAlexey Budankov for (i = 0; i < evlist->nr_mmaps; i++) { 360d3d1af6fSAlexey Budankov struct perf_mmap *map = &maps[i]; 361d3d1af6fSAlexey Budankov 362d3d1af6fSAlexey Budankov if (map->base) 36393f20c0fSAlexey Budankov record__aio_sync(map, true); 364d3d1af6fSAlexey Budankov } 365d3d1af6fSAlexey Budankov } 366d3d1af6fSAlexey Budankov 367d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1; 36893f20c0fSAlexey Budankov static int nr_cblocks_max = 4; 369d3d1af6fSAlexey Budankov 370d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt, 37193f20c0fSAlexey Budankov const char *str, 372d3d1af6fSAlexey Budankov int unset) 373d3d1af6fSAlexey Budankov { 374d3d1af6fSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 375d3d1af6fSAlexey Budankov 37693f20c0fSAlexey Budankov if (unset) { 377d3d1af6fSAlexey Budankov opts->nr_cblocks = 0; 37893f20c0fSAlexey Budankov } else { 37993f20c0fSAlexey Budankov if (str) 38093f20c0fSAlexey Budankov opts->nr_cblocks = strtol(str, NULL, 0); 38193f20c0fSAlexey Budankov if (!opts->nr_cblocks) 382d3d1af6fSAlexey Budankov opts->nr_cblocks = nr_cblocks_default; 38393f20c0fSAlexey Budankov } 384d3d1af6fSAlexey Budankov 385d3d1af6fSAlexey Budankov return 0; 386d3d1af6fSAlexey Budankov } 387d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */ 38893f20c0fSAlexey Budankov static int nr_cblocks_max = 0; 38993f20c0fSAlexey Budankov 390ef781128SAlexey Budankov static int record__aio_push(struct record *rec __maybe_unused, struct perf_mmap *map __maybe_unused, 391ef781128SAlexey Budankov off_t *off __maybe_unused) 392d3d1af6fSAlexey Budankov { 393d3d1af6fSAlexey Budankov return -1; 394d3d1af6fSAlexey Budankov } 395d3d1af6fSAlexey Budankov 396d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused) 397d3d1af6fSAlexey Budankov { 398d3d1af6fSAlexey Budankov return -1; 399d3d1af6fSAlexey Budankov } 400d3d1af6fSAlexey Budankov 401d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused) 402d3d1af6fSAlexey Budankov { 403d3d1af6fSAlexey Budankov } 404d3d1af6fSAlexey Budankov 405d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused) 406d3d1af6fSAlexey Budankov { 407d3d1af6fSAlexey Budankov } 408d3d1af6fSAlexey Budankov #endif 409d3d1af6fSAlexey Budankov 410d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec) 411d3d1af6fSAlexey Budankov { 412d3d1af6fSAlexey Budankov return rec->opts.nr_cblocks > 0; 413d3d1af6fSAlexey Budankov } 414d3d1af6fSAlexey Budankov 415470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1 416470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt, 417470530bbSAlexey Budankov const char *str, 418470530bbSAlexey Budankov int unset) 419470530bbSAlexey Budankov { 420470530bbSAlexey Budankov int flush_max; 421470530bbSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 422470530bbSAlexey Budankov static struct parse_tag tags[] = { 423470530bbSAlexey Budankov { .tag = 'B', .mult = 1 }, 424470530bbSAlexey Budankov { .tag = 'K', .mult = 1 << 10 }, 425470530bbSAlexey Budankov { .tag = 'M', .mult = 1 << 20 }, 426470530bbSAlexey Budankov { .tag = 'G', .mult = 1 << 30 }, 427470530bbSAlexey Budankov { .tag = 0 }, 428470530bbSAlexey Budankov }; 429470530bbSAlexey Budankov 430470530bbSAlexey Budankov if (unset) 431470530bbSAlexey Budankov return 0; 432470530bbSAlexey Budankov 433470530bbSAlexey Budankov if (str) { 434470530bbSAlexey Budankov opts->mmap_flush = parse_tag_value(str, tags); 435470530bbSAlexey Budankov if (opts->mmap_flush == (int)-1) 436470530bbSAlexey Budankov opts->mmap_flush = strtol(str, NULL, 0); 437470530bbSAlexey Budankov } 438470530bbSAlexey Budankov 439470530bbSAlexey Budankov if (!opts->mmap_flush) 440470530bbSAlexey Budankov opts->mmap_flush = MMAP_FLUSH_DEFAULT; 441470530bbSAlexey Budankov 442470530bbSAlexey Budankov flush_max = perf_evlist__mmap_size(opts->mmap_pages); 443470530bbSAlexey Budankov flush_max /= 4; 444470530bbSAlexey Budankov if (opts->mmap_flush > flush_max) 445470530bbSAlexey Budankov opts->mmap_flush = flush_max; 446470530bbSAlexey Budankov 447470530bbSAlexey Budankov return 0; 448470530bbSAlexey Budankov } 449470530bbSAlexey Budankov 450504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT 451504c1ad1SAlexey Budankov static unsigned int comp_level_default = 1; 452504c1ad1SAlexey Budankov 453504c1ad1SAlexey Budankov static int record__parse_comp_level(const struct option *opt, const char *str, int unset) 454504c1ad1SAlexey Budankov { 455504c1ad1SAlexey Budankov struct record_opts *opts = opt->value; 456504c1ad1SAlexey Budankov 457504c1ad1SAlexey Budankov if (unset) { 458504c1ad1SAlexey Budankov opts->comp_level = 0; 459504c1ad1SAlexey Budankov } else { 460504c1ad1SAlexey Budankov if (str) 461504c1ad1SAlexey Budankov opts->comp_level = strtol(str, NULL, 0); 462504c1ad1SAlexey Budankov if (!opts->comp_level) 463504c1ad1SAlexey Budankov opts->comp_level = comp_level_default; 464504c1ad1SAlexey Budankov } 465504c1ad1SAlexey Budankov 466504c1ad1SAlexey Budankov return 0; 467504c1ad1SAlexey Budankov } 468504c1ad1SAlexey Budankov #endif 46951255a8aSAlexey Budankov static unsigned int comp_level_max = 22; 47051255a8aSAlexey Budankov 47142e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec) 47242e1fd80SAlexey Budankov { 47342e1fd80SAlexey Budankov return rec->opts.comp_level > 0; 47442e1fd80SAlexey Budankov } 47542e1fd80SAlexey Budankov 47645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 477d20deb64SArnaldo Carvalho de Melo union perf_event *event, 4781d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 4791d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 480234fbbf5SArnaldo Carvalho de Melo { 4818c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 482ded2b8feSJiri Olsa return record__write(rec, NULL, event, event->header.size); 483234fbbf5SArnaldo Carvalho de Melo } 484234fbbf5SArnaldo Carvalho de Melo 485ded2b8feSJiri Olsa static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size) 486d37f1586SArnaldo Carvalho de Melo { 487d37f1586SArnaldo Carvalho de Melo struct record *rec = to; 488d37f1586SArnaldo Carvalho de Melo 4895d7f4116SAlexey Budankov if (record__comp_enabled(rec)) { 4905d7f4116SAlexey Budankov size = zstd_compress(rec->session, map->data, perf_mmap__mmap_len(map), bf, size); 4915d7f4116SAlexey Budankov bf = map->data; 4925d7f4116SAlexey Budankov } 4935d7f4116SAlexey Budankov 494d37f1586SArnaldo Carvalho de Melo rec->samples++; 495ded2b8feSJiri Olsa return record__write(rec, map, bf, size); 496d37f1586SArnaldo Carvalho de Melo } 497d37f1586SArnaldo Carvalho de Melo 4982dd6d8a1SAdrian Hunter static volatile int done; 4992dd6d8a1SAdrian Hunter static volatile int signr = -1; 5002dd6d8a1SAdrian Hunter static volatile int child_finished; 501c0bdc1c4SWang Nan 5022dd6d8a1SAdrian Hunter static void sig_handler(int sig) 5032dd6d8a1SAdrian Hunter { 5042dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 5052dd6d8a1SAdrian Hunter child_finished = 1; 5062dd6d8a1SAdrian Hunter else 5072dd6d8a1SAdrian Hunter signr = sig; 5082dd6d8a1SAdrian Hunter 5092dd6d8a1SAdrian Hunter done = 1; 5102dd6d8a1SAdrian Hunter } 5112dd6d8a1SAdrian Hunter 512a074865eSWang Nan static void sigsegv_handler(int sig) 513a074865eSWang Nan { 514a074865eSWang Nan perf_hooks__recover(); 515a074865eSWang Nan sighandler_dump_stack(sig); 516a074865eSWang Nan } 517a074865eSWang Nan 5182dd6d8a1SAdrian Hunter static void record__sig_exit(void) 5192dd6d8a1SAdrian Hunter { 5202dd6d8a1SAdrian Hunter if (signr == -1) 5212dd6d8a1SAdrian Hunter return; 5222dd6d8a1SAdrian Hunter 5232dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 5242dd6d8a1SAdrian Hunter raise(signr); 5252dd6d8a1SAdrian Hunter } 5262dd6d8a1SAdrian Hunter 527e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 528e31f0d01SAdrian Hunter 529ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 530ded2b8feSJiri Olsa struct perf_mmap *map, 531ef149c25SAdrian Hunter union perf_event *event, void *data1, 532ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 533ef149c25SAdrian Hunter { 534ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 5358ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 536ef149c25SAdrian Hunter size_t padding; 537ef149c25SAdrian Hunter u8 pad[8] = {0}; 538ef149c25SAdrian Hunter 539cd3dd8ddSJiri Olsa if (!perf_data__is_pipe(data) && !perf_data__is_dir(data)) { 54099fa2984SAdrian Hunter off_t file_offset; 5418ceb41d7SJiri Olsa int fd = perf_data__fd(data); 54299fa2984SAdrian Hunter int err; 54399fa2984SAdrian Hunter 54499fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 54599fa2984SAdrian Hunter if (file_offset == -1) 54699fa2984SAdrian Hunter return -1; 54799fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 54899fa2984SAdrian Hunter event, file_offset); 54999fa2984SAdrian Hunter if (err) 55099fa2984SAdrian Hunter return err; 55199fa2984SAdrian Hunter } 55299fa2984SAdrian Hunter 553ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 554ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 555ef149c25SAdrian Hunter if (padding) 556ef149c25SAdrian Hunter padding = 8 - padding; 557ef149c25SAdrian Hunter 558ded2b8feSJiri Olsa record__write(rec, map, event, event->header.size); 559ded2b8feSJiri Olsa record__write(rec, map, data1, len1); 560ef149c25SAdrian Hunter if (len2) 561ded2b8feSJiri Olsa record__write(rec, map, data2, len2); 562ded2b8feSJiri Olsa record__write(rec, map, &pad, padding); 563ef149c25SAdrian Hunter 564ef149c25SAdrian Hunter return 0; 565ef149c25SAdrian Hunter } 566ef149c25SAdrian Hunter 567ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 568e035f4caSJiri Olsa struct perf_mmap *map) 569ef149c25SAdrian Hunter { 570ef149c25SAdrian Hunter int ret; 571ef149c25SAdrian Hunter 572e035f4caSJiri Olsa ret = auxtrace_mmap__read(map, rec->itr, &rec->tool, 573ef149c25SAdrian Hunter record__process_auxtrace); 574ef149c25SAdrian Hunter if (ret < 0) 575ef149c25SAdrian Hunter return ret; 576ef149c25SAdrian Hunter 577ef149c25SAdrian Hunter if (ret) 578ef149c25SAdrian Hunter rec->samples++; 579ef149c25SAdrian Hunter 580ef149c25SAdrian Hunter return 0; 581ef149c25SAdrian Hunter } 582ef149c25SAdrian Hunter 5832dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 584e035f4caSJiri Olsa struct perf_mmap *map) 5852dd6d8a1SAdrian Hunter { 5862dd6d8a1SAdrian Hunter int ret; 5872dd6d8a1SAdrian Hunter 588e035f4caSJiri Olsa ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool, 5892dd6d8a1SAdrian Hunter record__process_auxtrace, 5902dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 5912dd6d8a1SAdrian Hunter if (ret < 0) 5922dd6d8a1SAdrian Hunter return ret; 5932dd6d8a1SAdrian Hunter 5942dd6d8a1SAdrian Hunter if (ret) 5952dd6d8a1SAdrian Hunter rec->samples++; 5962dd6d8a1SAdrian Hunter 5972dd6d8a1SAdrian Hunter return 0; 5982dd6d8a1SAdrian Hunter } 5992dd6d8a1SAdrian Hunter 6002dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 6012dd6d8a1SAdrian Hunter { 6022dd6d8a1SAdrian Hunter int i; 6032dd6d8a1SAdrian Hunter int rc = 0; 6042dd6d8a1SAdrian Hunter 6052dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 606e035f4caSJiri Olsa struct perf_mmap *map = &rec->evlist->mmap[i]; 6072dd6d8a1SAdrian Hunter 608e035f4caSJiri Olsa if (!map->auxtrace_mmap.base) 6092dd6d8a1SAdrian Hunter continue; 6102dd6d8a1SAdrian Hunter 611e035f4caSJiri Olsa if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) { 6122dd6d8a1SAdrian Hunter rc = -1; 6132dd6d8a1SAdrian Hunter goto out; 6142dd6d8a1SAdrian Hunter } 6152dd6d8a1SAdrian Hunter } 6162dd6d8a1SAdrian Hunter out: 6172dd6d8a1SAdrian Hunter return rc; 6182dd6d8a1SAdrian Hunter } 6192dd6d8a1SAdrian Hunter 620ce7b0e42SAlexander Shishkin static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit) 6212dd6d8a1SAdrian Hunter { 6222dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 6232dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 6245f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 6252dd6d8a1SAdrian Hunter } else { 626ce7b0e42SAlexander Shishkin if (auxtrace_record__snapshot_finish(rec->itr, on_exit)) 6275f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 6285f9cf599SWang Nan else 6295f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 6302dd6d8a1SAdrian Hunter } 6312dd6d8a1SAdrian Hunter } 6322dd6d8a1SAdrian Hunter 633ce7b0e42SAlexander Shishkin static int record__auxtrace_snapshot_exit(struct record *rec) 634ce7b0e42SAlexander Shishkin { 635ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger)) 636ce7b0e42SAlexander Shishkin return 0; 637ce7b0e42SAlexander Shishkin 638ce7b0e42SAlexander Shishkin if (!auxtrace_record__snapshot_started && 639ce7b0e42SAlexander Shishkin auxtrace_record__snapshot_start(rec->itr)) 640ce7b0e42SAlexander Shishkin return -1; 641ce7b0e42SAlexander Shishkin 642ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, true); 643ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger)) 644ce7b0e42SAlexander Shishkin return -1; 645ce7b0e42SAlexander Shishkin 646ce7b0e42SAlexander Shishkin return 0; 647ce7b0e42SAlexander Shishkin } 648ce7b0e42SAlexander Shishkin 6494b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec) 6504b5ea3bdSAdrian Hunter { 6514b5ea3bdSAdrian Hunter int err; 6524b5ea3bdSAdrian Hunter 6534b5ea3bdSAdrian Hunter if (!rec->itr) { 6544b5ea3bdSAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 6554b5ea3bdSAdrian Hunter if (err) 6564b5ea3bdSAdrian Hunter return err; 6574b5ea3bdSAdrian Hunter } 6584b5ea3bdSAdrian Hunter 6594b5ea3bdSAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 6604b5ea3bdSAdrian Hunter rec->opts.auxtrace_snapshot_opts); 6614b5ea3bdSAdrian Hunter if (err) 6624b5ea3bdSAdrian Hunter return err; 6634b5ea3bdSAdrian Hunter 6644b5ea3bdSAdrian Hunter return auxtrace_parse_filters(rec->evlist); 6654b5ea3bdSAdrian Hunter } 6664b5ea3bdSAdrian Hunter 667e31f0d01SAdrian Hunter #else 668e31f0d01SAdrian Hunter 669e31f0d01SAdrian Hunter static inline 670e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 671e035f4caSJiri Olsa struct perf_mmap *map __maybe_unused) 672e31f0d01SAdrian Hunter { 673e31f0d01SAdrian Hunter return 0; 674e31f0d01SAdrian Hunter } 675e31f0d01SAdrian Hunter 6762dd6d8a1SAdrian Hunter static inline 677ce7b0e42SAlexander Shishkin void record__read_auxtrace_snapshot(struct record *rec __maybe_unused, 678ce7b0e42SAlexander Shishkin bool on_exit __maybe_unused) 6792dd6d8a1SAdrian Hunter { 6802dd6d8a1SAdrian Hunter } 6812dd6d8a1SAdrian Hunter 6822dd6d8a1SAdrian Hunter static inline 6832dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 6842dd6d8a1SAdrian Hunter { 6852dd6d8a1SAdrian Hunter return 0; 6862dd6d8a1SAdrian Hunter } 6872dd6d8a1SAdrian Hunter 688ce7b0e42SAlexander Shishkin static inline 689ce7b0e42SAlexander Shishkin int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused) 690ce7b0e42SAlexander Shishkin { 691ce7b0e42SAlexander Shishkin return 0; 692ce7b0e42SAlexander Shishkin } 693ce7b0e42SAlexander Shishkin 6944b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused) 6954b5ea3bdSAdrian Hunter { 6964b5ea3bdSAdrian Hunter return 0; 6974b5ea3bdSAdrian Hunter } 6984b5ea3bdSAdrian Hunter 699e31f0d01SAdrian Hunter #endif 700e31f0d01SAdrian Hunter 701cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 70263503dbaSJiri Olsa struct evlist *evlist) 703cda57a8cSWang Nan { 704cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 705cda57a8cSWang Nan char msg[512]; 706cda57a8cSWang Nan 707f13de660SAlexey Budankov if (opts->affinity != PERF_AFFINITY_SYS) 708f13de660SAlexey Budankov cpu__setup_cpunode_map(); 709f13de660SAlexey Budankov 7107a276ff6SWang Nan if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, 711cda57a8cSWang Nan opts->auxtrace_mmap_pages, 7129d2ed645SAlexey Budankov opts->auxtrace_snapshot_mode, 713470530bbSAlexey Budankov opts->nr_cblocks, opts->affinity, 71451255a8aSAlexey Budankov opts->mmap_flush, opts->comp_level) < 0) { 715cda57a8cSWang Nan if (errno == EPERM) { 716cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 717cda57a8cSWang Nan "Consider increasing " 718cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 719cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 720cda57a8cSWang Nan "(current value: %u,%u)\n", 721cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 722cda57a8cSWang Nan return -errno; 723cda57a8cSWang Nan } else { 724cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 725c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 726cda57a8cSWang Nan if (errno) 727cda57a8cSWang Nan return -errno; 728cda57a8cSWang Nan else 729cda57a8cSWang Nan return -EINVAL; 730cda57a8cSWang Nan } 731cda57a8cSWang Nan } 732cda57a8cSWang Nan return 0; 733cda57a8cSWang Nan } 734cda57a8cSWang Nan 735cda57a8cSWang Nan static int record__mmap(struct record *rec) 736cda57a8cSWang Nan { 737cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 738cda57a8cSWang Nan } 739cda57a8cSWang Nan 7408c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 741dd7927f4SArnaldo Carvalho de Melo { 742d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 74332dcd021SJiri Olsa struct evsel *pos; 74463503dbaSJiri Olsa struct evlist *evlist = rec->evlist; 745d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 746b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 7478d3eca20SDavid Ahern int rc = 0; 748dd7927f4SArnaldo Carvalho de Melo 749d3dbf43cSArnaldo Carvalho de Melo /* 750d3dbf43cSArnaldo Carvalho de Melo * For initial_delay we need to add a dummy event so that we can track 751d3dbf43cSArnaldo Carvalho de Melo * PERF_RECORD_MMAP while we wait for the initial delay to enable the 752d3dbf43cSArnaldo Carvalho de Melo * real events, the ones asked by the user. 753d3dbf43cSArnaldo Carvalho de Melo */ 754d3dbf43cSArnaldo Carvalho de Melo if (opts->initial_delay) { 755d3dbf43cSArnaldo Carvalho de Melo if (perf_evlist__add_dummy(evlist)) 756d3dbf43cSArnaldo Carvalho de Melo return -ENOMEM; 757d3dbf43cSArnaldo Carvalho de Melo 758d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__first(evlist); 759d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 0; 760d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__last(evlist); 761d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 1; 7621fc632ceSJiri Olsa pos->core.attr.enable_on_exec = 1; 763d3dbf43cSArnaldo Carvalho de Melo } 764d3dbf43cSArnaldo Carvalho de Melo 765e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 766cac21425SJiri Olsa 767e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 7683da297a6SIngo Molnar try_again: 769af663bd0SJiri Olsa if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) { 77056e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 771bb963e16SNamhyung Kim if (verbose > 0) 772c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 7733da297a6SIngo Molnar goto try_again; 7743da297a6SIngo Molnar } 775cf99ad14SAndi Kleen if ((errno == EINVAL || errno == EBADF) && 776cf99ad14SAndi Kleen pos->leader != pos && 777cf99ad14SAndi Kleen pos->weak_group) { 778cf99ad14SAndi Kleen pos = perf_evlist__reset_weak_group(evlist, pos); 779cf99ad14SAndi Kleen goto try_again; 780cf99ad14SAndi Kleen } 78156e52e85SArnaldo Carvalho de Melo rc = -errno; 78256e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 78356e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 78456e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 7858d3eca20SDavid Ahern goto out; 7867c6a1c65SPeter Zijlstra } 787bfd8f72cSAndi Kleen 788bfd8f72cSAndi Kleen pos->supported = true; 7897c6a1c65SPeter Zijlstra } 7907c6a1c65SPeter Zijlstra 791*c8b567c8SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(evlist)) { 792*c8b567c8SArnaldo Carvalho de Melo pr_warning( 793*c8b567c8SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 794*c8b567c8SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n" 795*c8b567c8SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 796*c8b567c8SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 797*c8b567c8SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 798*c8b567c8SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 799*c8b567c8SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 800*c8b567c8SArnaldo Carvalho de Melo } 801*c8b567c8SArnaldo Carvalho de Melo 80223d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 80362d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 80423d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 805c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 8068d3eca20SDavid Ahern rc = -1; 8078d3eca20SDavid Ahern goto out; 8080a102479SFrederic Weisbecker } 8090a102479SFrederic Weisbecker 810cda57a8cSWang Nan rc = record__mmap(rec); 811cda57a8cSWang Nan if (rc) 8128d3eca20SDavid Ahern goto out; 8130a27d7f9SArnaldo Carvalho de Melo 814a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 8157b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 8168d3eca20SDavid Ahern out: 8178d3eca20SDavid Ahern return rc; 818a91e5431SArnaldo Carvalho de Melo } 819a91e5431SArnaldo Carvalho de Melo 820e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 821e3d59112SNamhyung Kim union perf_event *event, 822e3d59112SNamhyung Kim struct perf_sample *sample, 82332dcd021SJiri Olsa struct evsel *evsel, 824e3d59112SNamhyung Kim struct machine *machine) 825e3d59112SNamhyung Kim { 826e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 827e3d59112SNamhyung Kim 82868588bafSJin Yao if (rec->evlist->first_sample_time == 0) 82968588bafSJin Yao rec->evlist->first_sample_time = sample->time; 830e3d59112SNamhyung Kim 83168588bafSJin Yao rec->evlist->last_sample_time = sample->time; 83268588bafSJin Yao 83368588bafSJin Yao if (rec->buildid_all) 83468588bafSJin Yao return 0; 83568588bafSJin Yao 83668588bafSJin Yao rec->samples++; 837e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 838e3d59112SNamhyung Kim } 839e3d59112SNamhyung Kim 8408c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 8416122e4e4SArnaldo Carvalho de Melo { 842f5fc1412SJiri Olsa struct perf_session *session = rec->session; 8436122e4e4SArnaldo Carvalho de Melo 84445112e89SJiri Olsa if (perf_data__size(&rec->data) == 0) 8459f591fd7SArnaldo Carvalho de Melo return 0; 8469f591fd7SArnaldo Carvalho de Melo 84700dc8657SNamhyung Kim /* 84800dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 84900dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 85000dc8657SNamhyung Kim * we prefer the vmlinux path like 85100dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 85200dc8657SNamhyung Kim * 85300dc8657SNamhyung Kim * rather than build-id path (in debug directory). 85400dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 85500dc8657SNamhyung Kim */ 85600dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 85700dc8657SNamhyung Kim 8586156681bSNamhyung Kim /* 8596156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 86068588bafSJin Yao * so no need to process samples. But if timestamp_boundary is enabled, 86168588bafSJin Yao * it still needs to walk on all samples to get the timestamps of 86268588bafSJin Yao * first/last samples. 8636156681bSNamhyung Kim */ 86468588bafSJin Yao if (rec->buildid_all && !rec->timestamp_boundary) 8656156681bSNamhyung Kim rec->tool.sample = NULL; 8666156681bSNamhyung Kim 867b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 8686122e4e4SArnaldo Carvalho de Melo } 8696122e4e4SArnaldo Carvalho de Melo 8708115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 871a1645ce1SZhang, Yanmin { 872a1645ce1SZhang, Yanmin int err; 87345694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 874a1645ce1SZhang, Yanmin /* 875a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 876a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 877a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 878a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 879a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 880a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 881a1645ce1SZhang, Yanmin */ 88245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 883743eb868SArnaldo Carvalho de Melo machine); 884a1645ce1SZhang, Yanmin if (err < 0) 885a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 88623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 887a1645ce1SZhang, Yanmin 888a1645ce1SZhang, Yanmin /* 889a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 890a1645ce1SZhang, Yanmin * have no _text sometimes. 891a1645ce1SZhang, Yanmin */ 89245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 8930ae617beSAdrian Hunter machine); 894a1645ce1SZhang, Yanmin if (err < 0) 895a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 89623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 897a1645ce1SZhang, Yanmin } 898a1645ce1SZhang, Yanmin 89998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 90098402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 90198402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 90298402807SFrederic Weisbecker }; 90398402807SFrederic Weisbecker 904f13de660SAlexey Budankov static void record__adjust_affinity(struct record *rec, struct perf_mmap *map) 905f13de660SAlexey Budankov { 906f13de660SAlexey Budankov if (rec->opts.affinity != PERF_AFFINITY_SYS && 907f13de660SAlexey Budankov !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) { 908f13de660SAlexey Budankov CPU_ZERO(&rec->affinity_mask); 909f13de660SAlexey Budankov CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask); 910f13de660SAlexey Budankov sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask); 911f13de660SAlexey Budankov } 912f13de660SAlexey Budankov } 913f13de660SAlexey Budankov 9145d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment) 9155d7f4116SAlexey Budankov { 91672932371SJiri Olsa struct perf_record_compressed *event = record; 9175d7f4116SAlexey Budankov size_t size = sizeof(*event); 9185d7f4116SAlexey Budankov 9195d7f4116SAlexey Budankov if (increment) { 9205d7f4116SAlexey Budankov event->header.size += increment; 9215d7f4116SAlexey Budankov return increment; 9225d7f4116SAlexey Budankov } 9235d7f4116SAlexey Budankov 9245d7f4116SAlexey Budankov event->header.type = PERF_RECORD_COMPRESSED; 9255d7f4116SAlexey Budankov event->header.size = size; 9265d7f4116SAlexey Budankov 9275d7f4116SAlexey Budankov return size; 9285d7f4116SAlexey Budankov } 9295d7f4116SAlexey Budankov 9305d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 9315d7f4116SAlexey Budankov void *src, size_t src_size) 9325d7f4116SAlexey Budankov { 9335d7f4116SAlexey Budankov size_t compressed; 93472932371SJiri Olsa size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1; 9355d7f4116SAlexey Budankov 9365d7f4116SAlexey Budankov compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size, 9375d7f4116SAlexey Budankov max_record_size, process_comp_header); 9385d7f4116SAlexey Budankov 9395d7f4116SAlexey Budankov session->bytes_transferred += src_size; 9405d7f4116SAlexey Budankov session->bytes_compressed += compressed; 9415d7f4116SAlexey Budankov 9425d7f4116SAlexey Budankov return compressed; 9435d7f4116SAlexey Budankov } 9445d7f4116SAlexey Budankov 94563503dbaSJiri Olsa static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist, 946470530bbSAlexey Budankov bool overwrite, bool synch) 94798402807SFrederic Weisbecker { 948dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 9490e2e63ddSPeter Zijlstra int i; 9508d3eca20SDavid Ahern int rc = 0; 951a4ea0ec4SWang Nan struct perf_mmap *maps; 952d3d1af6fSAlexey Budankov int trace_fd = rec->data.file.fd; 953ef781128SAlexey Budankov off_t off = 0; 95498402807SFrederic Weisbecker 955cb21686bSWang Nan if (!evlist) 956cb21686bSWang Nan return 0; 957ef149c25SAdrian Hunter 9580b72d69aSWang Nan maps = overwrite ? evlist->overwrite_mmap : evlist->mmap; 959a4ea0ec4SWang Nan if (!maps) 960a4ea0ec4SWang Nan return 0; 961cb21686bSWang Nan 9620b72d69aSWang Nan if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 96354cc54deSWang Nan return 0; 96454cc54deSWang Nan 965d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 966d3d1af6fSAlexey Budankov off = record__aio_get_pos(trace_fd); 967d3d1af6fSAlexey Budankov 968a4ea0ec4SWang Nan for (i = 0; i < evlist->nr_mmaps; i++) { 969470530bbSAlexey Budankov u64 flush = 0; 970e035f4caSJiri Olsa struct perf_mmap *map = &maps[i]; 971a4ea0ec4SWang Nan 972e035f4caSJiri Olsa if (map->base) { 973f13de660SAlexey Budankov record__adjust_affinity(rec, map); 974470530bbSAlexey Budankov if (synch) { 975470530bbSAlexey Budankov flush = map->flush; 976470530bbSAlexey Budankov map->flush = 1; 977470530bbSAlexey Budankov } 978d3d1af6fSAlexey Budankov if (!record__aio_enabled(rec)) { 979ef781128SAlexey Budankov if (perf_mmap__push(map, rec, record__pushfn) < 0) { 980470530bbSAlexey Budankov if (synch) 981470530bbSAlexey Budankov map->flush = flush; 9828d3eca20SDavid Ahern rc = -1; 9838d3eca20SDavid Ahern goto out; 9848d3eca20SDavid Ahern } 985d3d1af6fSAlexey Budankov } else { 986ef781128SAlexey Budankov if (record__aio_push(rec, map, &off) < 0) { 987d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 988470530bbSAlexey Budankov if (synch) 989470530bbSAlexey Budankov map->flush = flush; 990d3d1af6fSAlexey Budankov rc = -1; 991d3d1af6fSAlexey Budankov goto out; 992d3d1af6fSAlexey Budankov } 993d3d1af6fSAlexey Budankov } 994470530bbSAlexey Budankov if (synch) 995470530bbSAlexey Budankov map->flush = flush; 9968d3eca20SDavid Ahern } 997ef149c25SAdrian Hunter 998e035f4caSJiri Olsa if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode && 999e035f4caSJiri Olsa record__auxtrace_mmap_read(rec, map) != 0) { 1000ef149c25SAdrian Hunter rc = -1; 1001ef149c25SAdrian Hunter goto out; 1002ef149c25SAdrian Hunter } 100398402807SFrederic Weisbecker } 100498402807SFrederic Weisbecker 1005d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 1006d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 1007d3d1af6fSAlexey Budankov 1008dcabb507SJiri Olsa /* 1009dcabb507SJiri Olsa * Mark the round finished in case we wrote 1010dcabb507SJiri Olsa * at least one event. 1011dcabb507SJiri Olsa */ 1012dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 1013ded2b8feSJiri Olsa rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event)); 10148d3eca20SDavid Ahern 10150b72d69aSWang Nan if (overwrite) 101654cc54deSWang Nan perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 10178d3eca20SDavid Ahern out: 10188d3eca20SDavid Ahern return rc; 101998402807SFrederic Weisbecker } 102098402807SFrederic Weisbecker 1021470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch) 1022cb21686bSWang Nan { 1023cb21686bSWang Nan int err; 1024cb21686bSWang Nan 1025470530bbSAlexey Budankov err = record__mmap_read_evlist(rec, rec->evlist, false, synch); 1026cb21686bSWang Nan if (err) 1027cb21686bSWang Nan return err; 1028cb21686bSWang Nan 1029470530bbSAlexey Budankov return record__mmap_read_evlist(rec, rec->evlist, true, synch); 1030cb21686bSWang Nan } 1031cb21686bSWang Nan 10328c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 103357706abcSDavid Ahern { 103457706abcSDavid Ahern struct perf_session *session = rec->session; 103557706abcSDavid Ahern int feat; 103657706abcSDavid Ahern 103757706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 103857706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 103957706abcSDavid Ahern 104057706abcSDavid Ahern if (rec->no_buildid) 104157706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 104257706abcSDavid Ahern 1043ce9036a6SJiri Olsa if (!have_tracepoints(&rec->evlist->core.entries)) 104457706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 104557706abcSDavid Ahern 104657706abcSDavid Ahern if (!rec->opts.branch_stack) 104757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 1048ef149c25SAdrian Hunter 1049ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 1050ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 1051ffa517adSJiri Olsa 1052cf790516SAlexey Budankov if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 1053cf790516SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_CLOCKID); 1054cf790516SAlexey Budankov 1055258031c0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); 105642e1fd80SAlexey Budankov if (!record__comp_enabled(rec)) 105742e1fd80SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_COMPRESSED); 1058258031c0SJiri Olsa 1059ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 106057706abcSDavid Ahern } 106157706abcSDavid Ahern 1062e1ab48baSWang Nan static void 1063e1ab48baSWang Nan record__finish_output(struct record *rec) 1064e1ab48baSWang Nan { 10658ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 10668ceb41d7SJiri Olsa int fd = perf_data__fd(data); 1067e1ab48baSWang Nan 10688ceb41d7SJiri Olsa if (data->is_pipe) 1069e1ab48baSWang Nan return; 1070e1ab48baSWang Nan 1071e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 107245112e89SJiri Olsa data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR); 1073e1ab48baSWang Nan 1074e1ab48baSWang Nan if (!rec->no_buildid) { 1075e1ab48baSWang Nan process_buildids(rec); 1076e1ab48baSWang Nan 1077e1ab48baSWang Nan if (rec->buildid_all) 1078e1ab48baSWang Nan dsos__hit_all(rec->session); 1079e1ab48baSWang Nan } 1080e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 1081e1ab48baSWang Nan 1082e1ab48baSWang Nan return; 1083e1ab48baSWang Nan } 1084e1ab48baSWang Nan 10854ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 1086be7b0c9eSWang Nan { 10879d6aae72SArnaldo Carvalho de Melo int err; 10889749b90eSJiri Olsa struct perf_thread_map *thread_map; 1089be7b0c9eSWang Nan 10904ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 10914ea648aeSWang Nan return 0; 10924ea648aeSWang Nan 10939d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 10949d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL) 10959d6aae72SArnaldo Carvalho de Melo return -1; 10969d6aae72SArnaldo Carvalho de Melo 10979d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 1098be7b0c9eSWang Nan process_synthesized_event, 1099be7b0c9eSWang Nan &rec->session->machines.host, 11003fcb10e4SMark Drayton rec->opts.sample_address); 11017836e52eSJiri Olsa perf_thread_map__put(thread_map); 11029d6aae72SArnaldo Carvalho de Melo return err; 1103be7b0c9eSWang Nan } 1104be7b0c9eSWang Nan 11054ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 11063c1cb7e3SWang Nan 1107ecfd7a9cSWang Nan static int 1108ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 1109ecfd7a9cSWang Nan { 11108ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1111ecfd7a9cSWang Nan int fd, err; 111203724b2eSAndi Kleen char *new_filename; 1113ecfd7a9cSWang Nan 1114ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 1115ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 1116ecfd7a9cSWang Nan 1117d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 1118d3d1af6fSAlexey Budankov 11194ea648aeSWang Nan record__synthesize(rec, true); 11204ea648aeSWang Nan if (target__none(&rec->opts.target)) 11214ea648aeSWang Nan record__synthesize_workload(rec, true); 11224ea648aeSWang Nan 1123ecfd7a9cSWang Nan rec->samples = 0; 1124ecfd7a9cSWang Nan record__finish_output(rec); 1125ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 1126ecfd7a9cSWang Nan if (err) { 1127ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 1128ecfd7a9cSWang Nan return -EINVAL; 1129ecfd7a9cSWang Nan } 1130ecfd7a9cSWang Nan 11318ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp, 1132ecfd7a9cSWang Nan rec->session->header.data_offset, 113303724b2eSAndi Kleen at_exit, &new_filename); 1134ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 1135ecfd7a9cSWang Nan rec->bytes_written = 0; 1136ecfd7a9cSWang Nan rec->session->header.data_size = 0; 1137ecfd7a9cSWang Nan } 1138ecfd7a9cSWang Nan 1139ecfd7a9cSWang Nan if (!quiet) 1140ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 11412d4f2799SJiri Olsa data->path, timestamp); 11423c1cb7e3SWang Nan 114303724b2eSAndi Kleen if (rec->switch_output.num_files) { 114403724b2eSAndi Kleen int n = rec->switch_output.cur_file + 1; 114503724b2eSAndi Kleen 114603724b2eSAndi Kleen if (n >= rec->switch_output.num_files) 114703724b2eSAndi Kleen n = 0; 114803724b2eSAndi Kleen rec->switch_output.cur_file = n; 114903724b2eSAndi Kleen if (rec->switch_output.filenames[n]) { 115003724b2eSAndi Kleen remove(rec->switch_output.filenames[n]); 1151d8f9da24SArnaldo Carvalho de Melo zfree(&rec->switch_output.filenames[n]); 115203724b2eSAndi Kleen } 115303724b2eSAndi Kleen rec->switch_output.filenames[n] = new_filename; 115403724b2eSAndi Kleen } else { 115503724b2eSAndi Kleen free(new_filename); 115603724b2eSAndi Kleen } 115703724b2eSAndi Kleen 11583c1cb7e3SWang Nan /* Output tracking events */ 1159be7b0c9eSWang Nan if (!at_exit) { 11604ea648aeSWang Nan record__synthesize(rec, false); 11613c1cb7e3SWang Nan 1162be7b0c9eSWang Nan /* 1163be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 1164be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 1165be7b0c9eSWang Nan * generate tracking events because there's no thread_map 1166be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 1167be7b0c9eSWang Nan * contain map and comm information. 1168be7b0c9eSWang Nan * Create a fake thread_map and directly call 1169be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 1170be7b0c9eSWang Nan */ 1171be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 11724ea648aeSWang Nan record__synthesize_workload(rec, false); 1173be7b0c9eSWang Nan } 1174ecfd7a9cSWang Nan return fd; 1175ecfd7a9cSWang Nan } 1176ecfd7a9cSWang Nan 1177f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 1178f33cbe72SArnaldo Carvalho de Melo 1179f33cbe72SArnaldo Carvalho de Melo /* 1180f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 1181f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 1182f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 1183f33cbe72SArnaldo Carvalho de Melo */ 118445604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 118545604710SNamhyung Kim siginfo_t *info, 1186f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 1187f33cbe72SArnaldo Carvalho de Melo { 1188f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 1189f33cbe72SArnaldo Carvalho de Melo done = 1; 1190f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 1191f33cbe72SArnaldo Carvalho de Melo } 1192f33cbe72SArnaldo Carvalho de Melo 11932dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 1194bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig); 11952dd6d8a1SAdrian Hunter 1196ee667f94SWang Nan static const struct perf_event_mmap_page * 119763503dbaSJiri Olsa perf_evlist__pick_pc(struct evlist *evlist) 1198ee667f94SWang Nan { 1199b2cb615dSWang Nan if (evlist) { 1200b2cb615dSWang Nan if (evlist->mmap && evlist->mmap[0].base) 1201ee667f94SWang Nan return evlist->mmap[0].base; 12020b72d69aSWang Nan if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].base) 12030b72d69aSWang Nan return evlist->overwrite_mmap[0].base; 1204b2cb615dSWang Nan } 1205ee667f94SWang Nan return NULL; 1206ee667f94SWang Nan } 1207ee667f94SWang Nan 1208c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 1209c45628b0SWang Nan { 1210ee667f94SWang Nan const struct perf_event_mmap_page *pc; 1211ee667f94SWang Nan 1212ee667f94SWang Nan pc = perf_evlist__pick_pc(rec->evlist); 1213ee667f94SWang Nan if (pc) 1214ee667f94SWang Nan return pc; 1215c45628b0SWang Nan return NULL; 1216c45628b0SWang Nan } 1217c45628b0SWang Nan 12184ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 1219c45c86ebSWang Nan { 1220c45c86ebSWang Nan struct perf_session *session = rec->session; 1221c45c86ebSWang Nan struct machine *machine = &session->machines.host; 12228ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1223c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 1224c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 12258ceb41d7SJiri Olsa int fd = perf_data__fd(data); 1226c45c86ebSWang Nan int err = 0; 1227c45c86ebSWang Nan 12284ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 12294ea648aeSWang Nan return 0; 12304ea648aeSWang Nan 12318ceb41d7SJiri Olsa if (data->is_pipe) { 1232a2015516SJiri Olsa /* 1233a2015516SJiri Olsa * We need to synthesize events first, because some 1234a2015516SJiri Olsa * features works on top of them (on report side). 1235a2015516SJiri Olsa */ 1236318ec184SJiri Olsa err = perf_event__synthesize_attrs(tool, rec->evlist, 1237c45c86ebSWang Nan process_synthesized_event); 1238c45c86ebSWang Nan if (err < 0) { 1239c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 1240c45c86ebSWang Nan goto out; 1241c45c86ebSWang Nan } 1242c45c86ebSWang Nan 1243a2015516SJiri Olsa err = perf_event__synthesize_features(tool, session, rec->evlist, 1244a2015516SJiri Olsa process_synthesized_event); 1245a2015516SJiri Olsa if (err < 0) { 1246a2015516SJiri Olsa pr_err("Couldn't synthesize features.\n"); 1247a2015516SJiri Olsa return err; 1248a2015516SJiri Olsa } 1249a2015516SJiri Olsa 1250ce9036a6SJiri Olsa if (have_tracepoints(&rec->evlist->core.entries)) { 1251c45c86ebSWang Nan /* 1252c45c86ebSWang Nan * FIXME err <= 0 here actually means that 1253c45c86ebSWang Nan * there were no tracepoints so its not really 1254c45c86ebSWang Nan * an error, just that we don't need to 1255c45c86ebSWang Nan * synthesize anything. We really have to 1256c45c86ebSWang Nan * return this more properly and also 1257c45c86ebSWang Nan * propagate errors that now are calling die() 1258c45c86ebSWang Nan */ 1259c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 1260c45c86ebSWang Nan process_synthesized_event); 1261c45c86ebSWang Nan if (err <= 0) { 1262c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 1263c45c86ebSWang Nan goto out; 1264c45c86ebSWang Nan } 1265c45c86ebSWang Nan rec->bytes_written += err; 1266c45c86ebSWang Nan } 1267c45c86ebSWang Nan } 1268c45c86ebSWang Nan 1269c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 127046bc29b9SAdrian Hunter process_synthesized_event, machine); 127146bc29b9SAdrian Hunter if (err) 127246bc29b9SAdrian Hunter goto out; 127346bc29b9SAdrian Hunter 1274c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 1275c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 1276c45c86ebSWang Nan session, process_synthesized_event); 1277c45c86ebSWang Nan if (err) 1278c45c86ebSWang Nan goto out; 1279c45c86ebSWang Nan } 1280c45c86ebSWang Nan 12816c443954SArnaldo Carvalho de Melo if (!perf_evlist__exclude_kernel(rec->evlist)) { 1282c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 1283c45c86ebSWang Nan machine); 1284c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 1285c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1286c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 1287c45c86ebSWang Nan 1288c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 1289c45c86ebSWang Nan machine); 1290c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 1291c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1292c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 12936c443954SArnaldo Carvalho de Melo } 1294c45c86ebSWang Nan 1295c45c86ebSWang Nan if (perf_guest) { 1296c45c86ebSWang Nan machines__process_guests(&session->machines, 1297c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 1298c45c86ebSWang Nan } 1299c45c86ebSWang Nan 1300bfd8f72cSAndi Kleen err = perf_event__synthesize_extra_attr(&rec->tool, 1301bfd8f72cSAndi Kleen rec->evlist, 1302bfd8f72cSAndi Kleen process_synthesized_event, 1303bfd8f72cSAndi Kleen data->is_pipe); 1304bfd8f72cSAndi Kleen if (err) 1305bfd8f72cSAndi Kleen goto out; 1306bfd8f72cSAndi Kleen 130703617c22SJiri Olsa err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads, 1308373565d2SAndi Kleen process_synthesized_event, 1309373565d2SAndi Kleen NULL); 1310373565d2SAndi Kleen if (err < 0) { 1311373565d2SAndi Kleen pr_err("Couldn't synthesize thread map.\n"); 1312373565d2SAndi Kleen return err; 1313373565d2SAndi Kleen } 1314373565d2SAndi Kleen 1315f72f901dSJiri Olsa err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus, 1316373565d2SAndi Kleen process_synthesized_event, NULL); 1317373565d2SAndi Kleen if (err < 0) { 1318373565d2SAndi Kleen pr_err("Couldn't synthesize cpu map.\n"); 1319373565d2SAndi Kleen return err; 1320373565d2SAndi Kleen } 1321373565d2SAndi Kleen 1322e5416950SSong Liu err = perf_event__synthesize_bpf_events(session, process_synthesized_event, 13237b612e29SSong Liu machine, opts); 13247b612e29SSong Liu if (err < 0) 13257b612e29SSong Liu pr_warning("Couldn't synthesize bpf events.\n"); 13267b612e29SSong Liu 132703617c22SJiri Olsa err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->core.threads, 1328c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 13293fcb10e4SMark Drayton 1); 1330c45c86ebSWang Nan out: 1331c45c86ebSWang Nan return err; 1332c45c86ebSWang Nan } 1333c45c86ebSWang Nan 13348c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 133586470930SIngo Molnar { 133657706abcSDavid Ahern int err; 133745604710SNamhyung Kim int status = 0; 13388b412664SPeter Zijlstra unsigned long waking = 0; 133946be604bSZhang, Yanmin const bool forks = argc > 0; 134045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 1341b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 13428ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1343d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 13446dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 134563503dbaSJiri Olsa struct evlist *sb_evlist = NULL; 134642aa276fSNamhyung Kim int fd; 1347d3c8c08eSAlexey Budankov float ratio = 0; 134886470930SIngo Molnar 134945604710SNamhyung Kim atexit(record__sig_exit); 1350f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 1351f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 1352804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 1353a074865eSWang Nan signal(SIGSEGV, sigsegv_handler); 1354c0bdc1c4SWang Nan 1355f3b3614aSHari Bathini if (rec->opts.record_namespaces) 1356f3b3614aSHari Bathini tool->namespace_events = true; 1357f3b3614aSHari Bathini 1358dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 13592dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 13603c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 13615f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 1362dc0c6127SJiri Olsa if (rec->switch_output.enabled) 13633c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 1364c0bdc1c4SWang Nan } else { 13652dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 1366c0bdc1c4SWang Nan } 1367f5970550SPeter Zijlstra 13688ceb41d7SJiri Olsa session = perf_session__new(data, false, tool); 13696ef81c55SMamatha Inamdar if (IS_ERR(session)) { 1370ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 13716ef81c55SMamatha Inamdar return PTR_ERR(session); 1372a9a70bbcSArnaldo Carvalho de Melo } 1373a9a70bbcSArnaldo Carvalho de Melo 13748ceb41d7SJiri Olsa fd = perf_data__fd(data); 1375d20deb64SArnaldo Carvalho de Melo rec->session = session; 1376d20deb64SArnaldo Carvalho de Melo 13775d7f4116SAlexey Budankov if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) { 13785d7f4116SAlexey Budankov pr_err("Compression initialization failed.\n"); 13795d7f4116SAlexey Budankov return -1; 13805d7f4116SAlexey Budankov } 13815d7f4116SAlexey Budankov 13825d7f4116SAlexey Budankov session->header.env.comp_type = PERF_COMP_ZSTD; 13835d7f4116SAlexey Budankov session->header.env.comp_level = rec->opts.comp_level; 13845d7f4116SAlexey Budankov 13858c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 1386330aa675SStephane Eranian 1387cf790516SAlexey Budankov if (rec->opts.use_clockid && rec->opts.clockid_res_ns) 1388cf790516SAlexey Budankov session->header.env.clockid_res_ns = rec->opts.clockid_res_ns; 1389cf790516SAlexey Budankov 1390d4db3f16SArnaldo Carvalho de Melo if (forks) { 13913e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 13928ceb41d7SJiri Olsa argv, data->is_pipe, 1393735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 139435b9d88eSArnaldo Carvalho de Melo if (err < 0) { 139535b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 139645604710SNamhyung Kim status = err; 139735b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 1398856e9660SPeter Zijlstra } 1399856e9660SPeter Zijlstra } 1400856e9660SPeter Zijlstra 1401ad46e48cSJiri Olsa /* 1402ad46e48cSJiri Olsa * If we have just single event and are sending data 1403ad46e48cSJiri Olsa * through pipe, we need to force the ids allocation, 1404ad46e48cSJiri Olsa * because we synthesize event name through the pipe 1405ad46e48cSJiri Olsa * and need the id for that. 1406ad46e48cSJiri Olsa */ 14076484d2f9SJiri Olsa if (data->is_pipe && rec->evlist->core.nr_entries == 1) 1408ad46e48cSJiri Olsa rec->opts.sample_id = true; 1409ad46e48cSJiri Olsa 14108c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 14118d3eca20SDavid Ahern err = -1; 141245604710SNamhyung Kim goto out_child; 14138d3eca20SDavid Ahern } 141442e1fd80SAlexey Budankov session->header.env.comp_mmap_len = session->evlist->mmap_len; 141586470930SIngo Molnar 14168690a2a7SWang Nan err = bpf__apply_obj_config(); 14178690a2a7SWang Nan if (err) { 14188690a2a7SWang Nan char errbuf[BUFSIZ]; 14198690a2a7SWang Nan 14208690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 14218690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 14228690a2a7SWang Nan errbuf); 14238690a2a7SWang Nan goto out_child; 14248690a2a7SWang Nan } 14258690a2a7SWang Nan 1426cca8482cSAdrian Hunter /* 1427cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 1428cca8482cSAdrian Hunter * evlist. 1429cca8482cSAdrian Hunter */ 1430cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 1431cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 1432cca8482cSAdrian Hunter rec->tool.ordered_events = false; 1433cca8482cSAdrian Hunter } 1434cca8482cSAdrian Hunter 14353e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 1436a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 1437a8bb559bSNamhyung Kim 14388ceb41d7SJiri Olsa if (data->is_pipe) { 143942aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 1440529870e3STom Zanussi if (err < 0) 144145604710SNamhyung Kim goto out_child; 1442563aecb2SJiri Olsa } else { 144342aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 1444d5eed904SArnaldo Carvalho de Melo if (err < 0) 144545604710SNamhyung Kim goto out_child; 1446d5eed904SArnaldo Carvalho de Melo } 14477c6a1c65SPeter Zijlstra 1448d3665498SDavid Ahern if (!rec->no_buildid 1449e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 1450d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 1451e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 14528d3eca20SDavid Ahern err = -1; 145345604710SNamhyung Kim goto out_child; 1454e20960c0SRobert Richter } 1455e20960c0SRobert Richter 1456d56354dcSSong Liu if (!opts->no_bpf_event) 1457d56354dcSSong Liu bpf_event__add_sb_event(&sb_evlist, &session->header.env); 1458d56354dcSSong Liu 1459657ee553SSong Liu if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) { 1460657ee553SSong Liu pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); 1461657ee553SSong Liu opts->no_bpf_event = true; 1462657ee553SSong Liu } 1463657ee553SSong Liu 14644ea648aeSWang Nan err = record__synthesize(rec, false); 1465c45c86ebSWang Nan if (err < 0) 146645604710SNamhyung Kim goto out_child; 14678d3eca20SDavid Ahern 1468d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 146986470930SIngo Molnar struct sched_param param; 147086470930SIngo Molnar 1471d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 147286470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 14736beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 14748d3eca20SDavid Ahern err = -1; 147545604710SNamhyung Kim goto out_child; 147686470930SIngo Molnar } 147786470930SIngo Molnar } 147886470930SIngo Molnar 1479774cb499SJiri Olsa /* 1480774cb499SJiri Olsa * When perf is starting the traced process, all the events 1481774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 1482774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 1483774cb499SJiri Olsa */ 14846619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 14851c87f165SJiri Olsa evlist__enable(rec->evlist); 1486764e16a3SDavid Ahern 1487856e9660SPeter Zijlstra /* 1488856e9660SPeter Zijlstra * Let the child rip 1489856e9660SPeter Zijlstra */ 1490e803cf97SNamhyung Kim if (forks) { 149120a8a3cfSJiri Olsa struct machine *machine = &session->machines.host; 1492e5bed564SNamhyung Kim union perf_event *event; 1493e907caf3SHari Bathini pid_t tgid; 1494e5bed564SNamhyung Kim 1495e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 1496e5bed564SNamhyung Kim if (event == NULL) { 1497e5bed564SNamhyung Kim err = -ENOMEM; 1498e5bed564SNamhyung Kim goto out_child; 1499e5bed564SNamhyung Kim } 1500e5bed564SNamhyung Kim 1501e803cf97SNamhyung Kim /* 1502e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 1503e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 1504e803cf97SNamhyung Kim * cannot see a correct process name for those events. 1505e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 1506e803cf97SNamhyung Kim */ 1507e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event, 1508e803cf97SNamhyung Kim rec->evlist->workload.pid, 1509e803cf97SNamhyung Kim process_synthesized_event, 1510e803cf97SNamhyung Kim machine); 1511e5bed564SNamhyung Kim free(event); 1512e803cf97SNamhyung Kim 1513e907caf3SHari Bathini if (tgid == -1) 1514e907caf3SHari Bathini goto out_child; 1515e907caf3SHari Bathini 1516e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) + 1517e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 1518e907caf3SHari Bathini machine->id_hdr_size); 1519e907caf3SHari Bathini if (event == NULL) { 1520e907caf3SHari Bathini err = -ENOMEM; 1521e907caf3SHari Bathini goto out_child; 1522e907caf3SHari Bathini } 1523e907caf3SHari Bathini 1524e907caf3SHari Bathini /* 1525e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified. 1526e907caf3SHari Bathini */ 1527e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event, 1528e907caf3SHari Bathini rec->evlist->workload.pid, 1529e907caf3SHari Bathini tgid, process_synthesized_event, 1530e907caf3SHari Bathini machine); 1531e907caf3SHari Bathini free(event); 1532e907caf3SHari Bathini 15333e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 1534e803cf97SNamhyung Kim } 1535856e9660SPeter Zijlstra 15366619a53eSAndi Kleen if (opts->initial_delay) { 15370693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 15381c87f165SJiri Olsa evlist__enable(rec->evlist); 15396619a53eSAndi Kleen } 15406619a53eSAndi Kleen 15415f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 15423c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 1543a074865eSWang Nan perf_hooks__invoke_record_start(); 1544649c48a9SPeter Zijlstra for (;;) { 15459f065194SYang Shi unsigned long long hits = rec->samples; 154686470930SIngo Molnar 154705737464SWang Nan /* 154805737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 154905737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 155005737464SWang Nan * hits != rec->samples in previous round. 155105737464SWang Nan * 155205737464SWang Nan * perf_evlist__toggle_bkw_mmap ensure we never 155305737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 155405737464SWang Nan */ 155505737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 155605737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 155705737464SWang Nan 1558470530bbSAlexey Budankov if (record__mmap_read_all(rec, false) < 0) { 15595f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 15603c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 15618d3eca20SDavid Ahern err = -1; 156245604710SNamhyung Kim goto out_child; 15638d3eca20SDavid Ahern } 156486470930SIngo Molnar 15652dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 15662dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 15675f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 1568ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, false); 15695f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 15702dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 15712dd6d8a1SAdrian Hunter err = -1; 15722dd6d8a1SAdrian Hunter goto out_child; 15732dd6d8a1SAdrian Hunter } 15742dd6d8a1SAdrian Hunter } 15752dd6d8a1SAdrian Hunter 15763c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 157705737464SWang Nan /* 157805737464SWang Nan * If switch_output_trigger is hit, the data in 157905737464SWang Nan * overwritable ring buffer should have been collected, 158005737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 158105737464SWang Nan * 158205737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 158305737464SWang Nan * record__mmap_read_all() didn't collect data from 158405737464SWang Nan * overwritable ring buffer. Read again. 158505737464SWang Nan */ 158605737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 158705737464SWang Nan continue; 15883c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 15893c1cb7e3SWang Nan 159005737464SWang Nan /* 159105737464SWang Nan * Reenable events in overwrite ring buffer after 159205737464SWang Nan * record__mmap_read_all(): we should have collected 159305737464SWang Nan * data from it. 159405737464SWang Nan */ 159505737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 159605737464SWang Nan 15973c1cb7e3SWang Nan if (!quiet) 15983c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 15993c1cb7e3SWang Nan waking); 16003c1cb7e3SWang Nan waking = 0; 16013c1cb7e3SWang Nan fd = record__switch_output(rec, false); 16023c1cb7e3SWang Nan if (fd < 0) { 16033c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 16043c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 16053c1cb7e3SWang Nan err = fd; 16063c1cb7e3SWang Nan goto out_child; 16073c1cb7e3SWang Nan } 1608bfacbe3bSJiri Olsa 1609bfacbe3bSJiri Olsa /* re-arm the alarm */ 1610bfacbe3bSJiri Olsa if (rec->switch_output.time) 1611bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 16123c1cb7e3SWang Nan } 16133c1cb7e3SWang Nan 1614d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 16156dcf45efSArnaldo Carvalho de Melo if (done || draining) 1616649c48a9SPeter Zijlstra break; 1617f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 1618a515114fSJiri Olsa /* 1619a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1620a515114fSJiri Olsa * number of returned events and interrupt error. 1621a515114fSJiri Olsa */ 1622a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 162345604710SNamhyung Kim err = 0; 16248b412664SPeter Zijlstra waking++; 16256dcf45efSArnaldo Carvalho de Melo 16266dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 16276dcf45efSArnaldo Carvalho de Melo draining = true; 16288b412664SPeter Zijlstra } 16298b412664SPeter Zijlstra 1630774cb499SJiri Olsa /* 1631774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1632774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1633774cb499SJiri Olsa * disable events in this case. 1634774cb499SJiri Olsa */ 1635602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 16365f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 1637e74676deSJiri Olsa evlist__disable(rec->evlist); 16382711926aSJiri Olsa disabled = true; 16392711926aSJiri Olsa } 16408b412664SPeter Zijlstra } 1641ce7b0e42SAlexander Shishkin 16425f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 16433c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 16448b412664SPeter Zijlstra 1645ce7b0e42SAlexander Shishkin if (opts->auxtrace_snapshot_on_exit) 1646ce7b0e42SAlexander Shishkin record__auxtrace_snapshot_exit(rec); 1647ce7b0e42SAlexander Shishkin 1648f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 164935550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 1650c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 1651f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 1652f33cbe72SArnaldo Carvalho de Melo err = -1; 165345604710SNamhyung Kim goto out_child; 1654f33cbe72SArnaldo Carvalho de Melo } 1655f33cbe72SArnaldo Carvalho de Melo 1656e3d59112SNamhyung Kim if (!quiet) 16578b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 165886470930SIngo Molnar 16594ea648aeSWang Nan if (target__none(&rec->opts.target)) 16604ea648aeSWang Nan record__synthesize_workload(rec, true); 16614ea648aeSWang Nan 166245604710SNamhyung Kim out_child: 1663470530bbSAlexey Budankov record__mmap_read_all(rec, true); 1664d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 1665d3d1af6fSAlexey Budankov 1666d3c8c08eSAlexey Budankov if (rec->session->bytes_transferred && rec->session->bytes_compressed) { 1667d3c8c08eSAlexey Budankov ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed; 1668d3c8c08eSAlexey Budankov session->header.env.comp_ratio = ratio + 0.5; 1669d3c8c08eSAlexey Budankov } 1670d3c8c08eSAlexey Budankov 167145604710SNamhyung Kim if (forks) { 167245604710SNamhyung Kim int exit_status; 167345604710SNamhyung Kim 167445604710SNamhyung Kim if (!child_finished) 167545604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 167645604710SNamhyung Kim 167745604710SNamhyung Kim wait(&exit_status); 167845604710SNamhyung Kim 167945604710SNamhyung Kim if (err < 0) 168045604710SNamhyung Kim status = err; 168145604710SNamhyung Kim else if (WIFEXITED(exit_status)) 168245604710SNamhyung Kim status = WEXITSTATUS(exit_status); 168345604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 168445604710SNamhyung Kim signr = WTERMSIG(exit_status); 168545604710SNamhyung Kim } else 168645604710SNamhyung Kim status = err; 168745604710SNamhyung Kim 16884ea648aeSWang Nan record__synthesize(rec, true); 1689e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 1690e3d59112SNamhyung Kim rec->samples = 0; 1691e3d59112SNamhyung Kim 1692ecfd7a9cSWang Nan if (!err) { 1693ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 1694e1ab48baSWang Nan record__finish_output(rec); 1695ecfd7a9cSWang Nan } else { 1696ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1697ecfd7a9cSWang Nan if (fd < 0) { 1698ecfd7a9cSWang Nan status = fd; 1699ecfd7a9cSWang Nan goto out_delete_session; 1700ecfd7a9cSWang Nan } 1701ecfd7a9cSWang Nan } 1702ecfd7a9cSWang Nan } 170339d17dacSArnaldo Carvalho de Melo 1704a074865eSWang Nan perf_hooks__invoke_record_end(); 1705a074865eSWang Nan 1706e3d59112SNamhyung Kim if (!err && !quiet) { 1707e3d59112SNamhyung Kim char samples[128]; 1708ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1709ecfd7a9cSWang Nan ".<timestamp>" : ""; 1710e3d59112SNamhyung Kim 1711ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1712e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1713e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1714e3d59112SNamhyung Kim else 1715e3d59112SNamhyung Kim samples[0] = '\0'; 1716e3d59112SNamhyung Kim 1717d3c8c08eSAlexey Budankov fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s", 17188ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0, 17192d4f2799SJiri Olsa data->path, postfix, samples); 1720d3c8c08eSAlexey Budankov if (ratio) { 1721d3c8c08eSAlexey Budankov fprintf(stderr, ", compressed (original %.3f MB, ratio is %.3f)", 1722d3c8c08eSAlexey Budankov rec->session->bytes_transferred / 1024.0 / 1024.0, 1723d3c8c08eSAlexey Budankov ratio); 1724d3c8c08eSAlexey Budankov } 1725d3c8c08eSAlexey Budankov fprintf(stderr, " ]\n"); 1726e3d59112SNamhyung Kim } 1727e3d59112SNamhyung Kim 172839d17dacSArnaldo Carvalho de Melo out_delete_session: 17295d7f4116SAlexey Budankov zstd_fini(&session->zstd_data); 173039d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 1731657ee553SSong Liu 1732657ee553SSong Liu if (!opts->no_bpf_event) 1733657ee553SSong Liu perf_evlist__stop_sb_thread(sb_evlist); 173445604710SNamhyung Kim return status; 173586470930SIngo Molnar } 173686470930SIngo Molnar 17370883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 173809b0fd45SJiri Olsa { 1739aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1740a601fdffSJiri Olsa 17410883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 174226d33022SJiri Olsa 17430883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 174409b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 17450883e820SArnaldo Carvalho de Melo callchain->dump_size); 17460883e820SArnaldo Carvalho de Melo } 17470883e820SArnaldo Carvalho de Melo 17480883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 17490883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 17500883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 17510883e820SArnaldo Carvalho de Melo { 17520883e820SArnaldo Carvalho de Melo int ret; 17530883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 17540883e820SArnaldo Carvalho de Melo 17550883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 17560883e820SArnaldo Carvalho de Melo if (unset) { 17570883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 17580883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 17590883e820SArnaldo Carvalho de Melo return 0; 17600883e820SArnaldo Carvalho de Melo } 17610883e820SArnaldo Carvalho de Melo 17620883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 17630883e820SArnaldo Carvalho de Melo if (!ret) { 17640883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 17650883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 17660883e820SArnaldo Carvalho de Melo record->sample_address = true; 17670883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 17680883e820SArnaldo Carvalho de Melo } 17690883e820SArnaldo Carvalho de Melo 17700883e820SArnaldo Carvalho de Melo return ret; 177109b0fd45SJiri Olsa } 177209b0fd45SJiri Olsa 1773c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 177409b0fd45SJiri Olsa const char *arg, 177509b0fd45SJiri Olsa int unset) 177609b0fd45SJiri Olsa { 17770883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 177826d33022SJiri Olsa } 177926d33022SJiri Olsa 1780c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 178109b0fd45SJiri Olsa const char *arg __maybe_unused, 178209b0fd45SJiri Olsa int unset __maybe_unused) 178309b0fd45SJiri Olsa { 17842ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1785c421e80bSKan Liang 17862ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 178709b0fd45SJiri Olsa 17882ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 17892ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1790eb853e80SJiri Olsa 17912ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 179209b0fd45SJiri Olsa return 0; 179309b0fd45SJiri Olsa } 179409b0fd45SJiri Olsa 1795eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1796eb853e80SJiri Olsa { 17977a29c087SNamhyung Kim struct record *rec = cb; 17987a29c087SNamhyung Kim 17997a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 18007a29c087SNamhyung Kim if (!strcmp(value, "cache")) 18017a29c087SNamhyung Kim rec->no_buildid_cache = false; 18027a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 18037a29c087SNamhyung Kim rec->no_buildid_cache = true; 18047a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 18057a29c087SNamhyung Kim rec->no_buildid = true; 18067a29c087SNamhyung Kim else 18077a29c087SNamhyung Kim return -1; 18087a29c087SNamhyung Kim return 0; 18097a29c087SNamhyung Kim } 1810cff17205SYisheng Xie if (!strcmp(var, "record.call-graph")) { 1811cff17205SYisheng Xie var = "call-graph.record-mode"; 1812eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1813eb853e80SJiri Olsa } 181493f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 181593f20c0fSAlexey Budankov if (!strcmp(var, "record.aio")) { 181693f20c0fSAlexey Budankov rec->opts.nr_cblocks = strtol(value, NULL, 0); 181793f20c0fSAlexey Budankov if (!rec->opts.nr_cblocks) 181893f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_default; 181993f20c0fSAlexey Budankov } 182093f20c0fSAlexey Budankov #endif 1821eb853e80SJiri Olsa 1822cff17205SYisheng Xie return 0; 1823cff17205SYisheng Xie } 1824cff17205SYisheng Xie 1825814c8c38SPeter Zijlstra struct clockid_map { 1826814c8c38SPeter Zijlstra const char *name; 1827814c8c38SPeter Zijlstra int clockid; 1828814c8c38SPeter Zijlstra }; 1829814c8c38SPeter Zijlstra 1830814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1831814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1832814c8c38SPeter Zijlstra 1833814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1834814c8c38SPeter Zijlstra 1835814c8c38SPeter Zijlstra 1836814c8c38SPeter Zijlstra /* 1837814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1838814c8c38SPeter Zijlstra */ 1839814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1840814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1841814c8c38SPeter Zijlstra #endif 1842814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1843814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1844814c8c38SPeter Zijlstra #endif 1845814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1846814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1847814c8c38SPeter Zijlstra #endif 1848814c8c38SPeter Zijlstra 1849814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1850814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1851814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1852814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1853814c8c38SPeter Zijlstra 1854814c8c38SPeter Zijlstra /* available for some events */ 1855814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1856814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1857814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1858814c8c38SPeter Zijlstra 1859814c8c38SPeter Zijlstra /* available for the lazy */ 1860814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1861814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1862814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1863814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1864814c8c38SPeter Zijlstra 1865814c8c38SPeter Zijlstra CLOCKID_END, 1866814c8c38SPeter Zijlstra }; 1867814c8c38SPeter Zijlstra 1868cf790516SAlexey Budankov static int get_clockid_res(clockid_t clk_id, u64 *res_ns) 1869cf790516SAlexey Budankov { 1870cf790516SAlexey Budankov struct timespec res; 1871cf790516SAlexey Budankov 1872cf790516SAlexey Budankov *res_ns = 0; 1873cf790516SAlexey Budankov if (!clock_getres(clk_id, &res)) 1874cf790516SAlexey Budankov *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC; 1875cf790516SAlexey Budankov else 1876cf790516SAlexey Budankov pr_warning("WARNING: Failed to determine specified clock resolution.\n"); 1877cf790516SAlexey Budankov 1878cf790516SAlexey Budankov return 0; 1879cf790516SAlexey Budankov } 1880cf790516SAlexey Budankov 1881814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1882814c8c38SPeter Zijlstra { 1883814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1884814c8c38SPeter Zijlstra const struct clockid_map *cm; 1885814c8c38SPeter Zijlstra const char *ostr = str; 1886814c8c38SPeter Zijlstra 1887814c8c38SPeter Zijlstra if (unset) { 1888814c8c38SPeter Zijlstra opts->use_clockid = 0; 1889814c8c38SPeter Zijlstra return 0; 1890814c8c38SPeter Zijlstra } 1891814c8c38SPeter Zijlstra 1892814c8c38SPeter Zijlstra /* no arg passed */ 1893814c8c38SPeter Zijlstra if (!str) 1894814c8c38SPeter Zijlstra return 0; 1895814c8c38SPeter Zijlstra 1896814c8c38SPeter Zijlstra /* no setting it twice */ 1897814c8c38SPeter Zijlstra if (opts->use_clockid) 1898814c8c38SPeter Zijlstra return -1; 1899814c8c38SPeter Zijlstra 1900814c8c38SPeter Zijlstra opts->use_clockid = true; 1901814c8c38SPeter Zijlstra 1902814c8c38SPeter Zijlstra /* if its a number, we're done */ 1903814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1904cf790516SAlexey Budankov return get_clockid_res(opts->clockid, &opts->clockid_res_ns); 1905814c8c38SPeter Zijlstra 1906814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1907814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1908814c8c38SPeter Zijlstra str += 6; 1909814c8c38SPeter Zijlstra 1910814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1911814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1912814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1913cf790516SAlexey Budankov return get_clockid_res(opts->clockid, 1914cf790516SAlexey Budankov &opts->clockid_res_ns); 1915814c8c38SPeter Zijlstra } 1916814c8c38SPeter Zijlstra } 1917814c8c38SPeter Zijlstra 1918814c8c38SPeter Zijlstra opts->use_clockid = false; 1919814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1920814c8c38SPeter Zijlstra return -1; 1921814c8c38SPeter Zijlstra } 1922814c8c38SPeter Zijlstra 1923f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset) 1924f4fe11b7SAlexey Budankov { 1925f4fe11b7SAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 1926f4fe11b7SAlexey Budankov 1927f4fe11b7SAlexey Budankov if (unset || !str) 1928f4fe11b7SAlexey Budankov return 0; 1929f4fe11b7SAlexey Budankov 1930f4fe11b7SAlexey Budankov if (!strcasecmp(str, "node")) 1931f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_NODE; 1932f4fe11b7SAlexey Budankov else if (!strcasecmp(str, "cpu")) 1933f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_CPU; 1934f4fe11b7SAlexey Budankov 1935f4fe11b7SAlexey Budankov return 0; 1936f4fe11b7SAlexey Budankov } 1937f4fe11b7SAlexey Budankov 1938e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1939e9db1310SAdrian Hunter const char *str, 1940e9db1310SAdrian Hunter int unset __maybe_unused) 1941e9db1310SAdrian Hunter { 1942e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1943e9db1310SAdrian Hunter char *s, *p; 1944e9db1310SAdrian Hunter unsigned int mmap_pages; 1945e9db1310SAdrian Hunter int ret; 1946e9db1310SAdrian Hunter 1947e9db1310SAdrian Hunter if (!str) 1948e9db1310SAdrian Hunter return -EINVAL; 1949e9db1310SAdrian Hunter 1950e9db1310SAdrian Hunter s = strdup(str); 1951e9db1310SAdrian Hunter if (!s) 1952e9db1310SAdrian Hunter return -ENOMEM; 1953e9db1310SAdrian Hunter 1954e9db1310SAdrian Hunter p = strchr(s, ','); 1955e9db1310SAdrian Hunter if (p) 1956e9db1310SAdrian Hunter *p = '\0'; 1957e9db1310SAdrian Hunter 1958e9db1310SAdrian Hunter if (*s) { 1959e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1960e9db1310SAdrian Hunter if (ret) 1961e9db1310SAdrian Hunter goto out_free; 1962e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1963e9db1310SAdrian Hunter } 1964e9db1310SAdrian Hunter 1965e9db1310SAdrian Hunter if (!p) { 1966e9db1310SAdrian Hunter ret = 0; 1967e9db1310SAdrian Hunter goto out_free; 1968e9db1310SAdrian Hunter } 1969e9db1310SAdrian Hunter 1970e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1971e9db1310SAdrian Hunter if (ret) 1972e9db1310SAdrian Hunter goto out_free; 1973e9db1310SAdrian Hunter 1974e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1975e9db1310SAdrian Hunter 1976e9db1310SAdrian Hunter out_free: 1977e9db1310SAdrian Hunter free(s); 1978e9db1310SAdrian Hunter return ret; 1979e9db1310SAdrian Hunter } 1980e9db1310SAdrian Hunter 19810c582449SJiri Olsa static void switch_output_size_warn(struct record *rec) 19820c582449SJiri Olsa { 19830c582449SJiri Olsa u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages); 19840c582449SJiri Olsa struct switch_output *s = &rec->switch_output; 19850c582449SJiri Olsa 19860c582449SJiri Olsa wakeup_size /= 2; 19870c582449SJiri Olsa 19880c582449SJiri Olsa if (s->size < wakeup_size) { 19890c582449SJiri Olsa char buf[100]; 19900c582449SJiri Olsa 19910c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 19920c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than " 19930c582449SJiri Olsa "wakeup kernel buffer size (%s) " 19940c582449SJiri Olsa "expect bigger perf.data sizes\n", buf); 19950c582449SJiri Olsa } 19960c582449SJiri Olsa } 19970c582449SJiri Olsa 1998cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec) 1999cb4e1ebbSJiri Olsa { 2000cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output; 2001dc0c6127SJiri Olsa static struct parse_tag tags_size[] = { 2002dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 }, 2003dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 2004dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 2005dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 2006dc0c6127SJiri Olsa { .tag = 0 }, 2007dc0c6127SJiri Olsa }; 2008bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = { 2009bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 }, 2010bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 }, 2011bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 }, 2012bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 }, 2013bfacbe3bSJiri Olsa { .tag = 0 }, 2014bfacbe3bSJiri Olsa }; 2015dc0c6127SJiri Olsa unsigned long val; 2016cb4e1ebbSJiri Olsa 2017cb4e1ebbSJiri Olsa if (!s->set) 2018cb4e1ebbSJiri Olsa return 0; 2019cb4e1ebbSJiri Olsa 2020cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) { 2021cb4e1ebbSJiri Olsa s->signal = true; 2022cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n"); 2023dc0c6127SJiri Olsa goto enabled; 2024dc0c6127SJiri Olsa } 2025dc0c6127SJiri Olsa 2026dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size); 2027dc0c6127SJiri Olsa if (val != (unsigned long) -1) { 2028dc0c6127SJiri Olsa s->size = val; 2029dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str); 2030dc0c6127SJiri Olsa goto enabled; 2031cb4e1ebbSJiri Olsa } 2032cb4e1ebbSJiri Olsa 2033bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time); 2034bfacbe3bSJiri Olsa if (val != (unsigned long) -1) { 2035bfacbe3bSJiri Olsa s->time = val; 2036bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n", 2037bfacbe3bSJiri Olsa s->str, s->time); 2038bfacbe3bSJiri Olsa goto enabled; 2039bfacbe3bSJiri Olsa } 2040bfacbe3bSJiri Olsa 2041cb4e1ebbSJiri Olsa return -1; 2042dc0c6127SJiri Olsa 2043dc0c6127SJiri Olsa enabled: 2044dc0c6127SJiri Olsa rec->timestamp_filename = true; 2045dc0c6127SJiri Olsa s->enabled = true; 20460c582449SJiri Olsa 20470c582449SJiri Olsa if (s->size && !rec->opts.no_buffering) 20480c582449SJiri Olsa switch_output_size_warn(rec); 20490c582449SJiri Olsa 2050dc0c6127SJiri Olsa return 0; 2051cb4e1ebbSJiri Olsa } 2052cb4e1ebbSJiri Olsa 2053e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 205486470930SIngo Molnar "perf record [<options>] [<command>]", 205586470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 205686470930SIngo Molnar NULL 205786470930SIngo Molnar }; 2058e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 205986470930SIngo Molnar 2060d20deb64SArnaldo Carvalho de Melo /* 20618c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 20628c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 2063d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 2064d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 2065d20deb64SArnaldo Carvalho de Melo * 2066d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 2067d20deb64SArnaldo Carvalho de Melo * 2068d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 2069d20deb64SArnaldo Carvalho de Melo */ 20708c6f45a7SArnaldo Carvalho de Melo static struct record record = { 2071d20deb64SArnaldo Carvalho de Melo .opts = { 20728affc2b8SAndi Kleen .sample_time = true, 2073d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 2074d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 2075d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 2076447a6013SArnaldo Carvalho de Melo .freq = 4000, 2077d1cb9fceSNamhyung Kim .target = { 2078d1cb9fceSNamhyung Kim .uses_mmap = true, 20793aa5939dSAdrian Hunter .default_per_cpu = true, 2080d1cb9fceSNamhyung Kim }, 2081470530bbSAlexey Budankov .mmap_flush = MMAP_FLUSH_DEFAULT, 2082d20deb64SArnaldo Carvalho de Melo }, 2083e3d59112SNamhyung Kim .tool = { 2084e3d59112SNamhyung Kim .sample = process_sample_event, 2085e3d59112SNamhyung Kim .fork = perf_event__process_fork, 2086cca8482cSAdrian Hunter .exit = perf_event__process_exit, 2087e3d59112SNamhyung Kim .comm = perf_event__process_comm, 2088f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces, 2089e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 2090e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 2091cca8482cSAdrian Hunter .ordered_events = true, 2092e3d59112SNamhyung Kim }, 2093d20deb64SArnaldo Carvalho de Melo }; 20947865e817SFrederic Weisbecker 209576a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 209676a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 209761eaa3beSArnaldo Carvalho de Melo 20980aab2136SWang Nan static bool dry_run; 20990aab2136SWang Nan 2100d20deb64SArnaldo Carvalho de Melo /* 2101d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 2102d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 2103b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 2104d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 2105d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 2106d20deb64SArnaldo Carvalho de Melo */ 2107efd21307SJiri Olsa static struct option __record_options[] = { 2108d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 210986470930SIngo Molnar "event selector. use 'perf list' to list available events", 2110f120f9d5SJiri Olsa parse_events_option), 2111d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 2112c171b552SLi Zefan "event filter", parse_filter), 21134ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 21144ba1faa1SWang Nan NULL, "don't record events from perf itself", 21154ba1faa1SWang Nan exclude_perf), 2116bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 2117d6d901c2SZhang, Yanmin "record events on existing process id"), 2118bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 2119d6d901c2SZhang, Yanmin "record events on existing thread id"), 2120d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 212186470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 2122509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 2123acac03faSKirill Smelkov "collect data without buffering"), 2124d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 2125daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 2126bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 212786470930SIngo Molnar "system-wide collection from all CPUs"), 2128bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 2129c45c6ea2SStephane Eranian "list of cpus to monitor"), 2130d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 21312d4f2799SJiri Olsa OPT_STRING('o', "output", &record.data.path, "file", 213286470930SIngo Molnar "output file name"), 213369e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 213469e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 21352e6cdf99SStephane Eranian "child tasks do not inherit counters"), 21364ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 21374ea648aeSWang Nan "synthesize non-sample events at the end of output"), 2138626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 213971184c6aSSong Liu OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"), 2140b09c2364SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 2141b09c2364SArnaldo Carvalho de Melo "Fail if the specified frequency can't be used"), 214267230479SArnaldo Carvalho de Melo OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 214367230479SArnaldo Carvalho de Melo "profile at this frequency", 214467230479SArnaldo Carvalho de Melo record__parse_freq), 2145e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 2146e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 2147e9db1310SAdrian Hunter record__parse_mmap_pages), 2148470530bbSAlexey Budankov OPT_CALLBACK(0, "mmap-flush", &record.opts, "number", 2149470530bbSAlexey Budankov "Minimal number of bytes that is extracted from mmap data pages (default: 1)", 2150470530bbSAlexey Budankov record__mmap_flush_parse), 2151d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 215243bece79SLin Ming "put the counters into a counter group"), 21532ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 215409b0fd45SJiri Olsa NULL, "enables call-graph recording" , 215509b0fd45SJiri Olsa &record_callchain_opt), 215609b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 215776a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 215809b0fd45SJiri Olsa &record_parse_callchain_opt), 2159c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 21603da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 2161b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 2162d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 2163649c48a9SPeter Zijlstra "per thread counts"), 216456100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 21653b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 21663b0a5daaSKan Liang "Record the sample physical addresses"), 2167b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 21683abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 21693abebc55SAdrian Hunter &record.opts.sample_time_set, 21703abebc55SAdrian Hunter "Record the sample timestamps"), 2171f290aa1fSJiri Olsa OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set, 2172f290aa1fSJiri Olsa "Record the sample period"), 2173d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 2174649c48a9SPeter Zijlstra "don't sample"), 2175d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 2176d2db9a98SWang Nan &record.no_buildid_cache_set, 2177a1ac1d3cSStephane Eranian "do not update the buildid cache"), 2178d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 2179d2db9a98SWang Nan &record.no_buildid_set, 2180baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 2181d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 2182023695d9SStephane Eranian "monitor event in cgroup name only", 2183023695d9SStephane Eranian parse_cgroups), 2184a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 21856619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 2186bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 2187bea03405SNamhyung Kim "user to profile"), 2188a5aabdacSStephane Eranian 2189a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 2190a5aabdacSStephane Eranian "branch any", "sample any taken branches", 2191a5aabdacSStephane Eranian parse_branch_stack), 2192a5aabdacSStephane Eranian 2193a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 2194a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 2195bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 219605484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 219705484298SAndi Kleen "sample by weight (on special events only)"), 2198475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 2199475eeab9SAndi Kleen "sample transaction flags (special events only)"), 22003aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 22013aa5939dSAdrian Hunter "use per-thread mmaps"), 2202bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 2203bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 2204aeea9062SKan Liang " use '-I?' to list register names", parse_intr_regs), 220584c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 220684c41742SAndi Kleen "sample selected machine registers on interrupt," 2207aeea9062SKan Liang " use '--user-regs=?' to list register names", parse_user_regs), 220885c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 220985c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 2210814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 2211814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 2212814c8c38SPeter Zijlstra parse_clockid), 22132dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 22142dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 22153fcb10e4SMark Drayton OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout, 22169d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 2217f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 2218f3b3614aSHari Bathini "Record namespaces events"), 2219b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 2220b757bb09SAdrian Hunter "Record context switch events"), 222185723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 222285723885SJiri Olsa "Configure all used events to run in kernel space.", 222385723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 222485723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 222585723885SJiri Olsa "Configure all used events to run in user space.", 222685723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 222753651b28Syuzhoujian OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains, 222853651b28Syuzhoujian "collect kernel callchains"), 222953651b28Syuzhoujian OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains, 223053651b28Syuzhoujian "collect user callchains"), 223171dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 223271dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 223371dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 223471dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 22357efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 22367efe0e03SHe Kuang "file", "vmlinux pathname"), 22376156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 22386156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 2239ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 2240ecfd7a9cSWang Nan "append timestamp to output filename"), 224168588bafSJin Yao OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 224268588bafSJin Yao "Record timestamp boundary (time of first/last samples)"), 2243cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 2244c38dab7dSAndi Kleen &record.switch_output.set, "signal or size[BKMG] or time[smhd]", 2245c38dab7dSAndi Kleen "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold", 2246dc0c6127SJiri Olsa "signal"), 224703724b2eSAndi Kleen OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, 224803724b2eSAndi Kleen "Limit number of switch output generated files"), 22490aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 22500aab2136SWang Nan "Parse options then exit"), 2251d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 225293f20c0fSAlexey Budankov OPT_CALLBACK_OPTARG(0, "aio", &record.opts, 225393f20c0fSAlexey Budankov &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)", 2254d3d1af6fSAlexey Budankov record__aio_parse), 2255d3d1af6fSAlexey Budankov #endif 2256f4fe11b7SAlexey Budankov OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", 2257f4fe11b7SAlexey Budankov "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", 2258f4fe11b7SAlexey Budankov record__parse_affinity), 2259504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT 2260504c1ad1SAlexey Budankov OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default, 2261504c1ad1SAlexey Budankov "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)", 2262504c1ad1SAlexey Budankov record__parse_comp_level), 2263504c1ad1SAlexey Budankov #endif 226486470930SIngo Molnar OPT_END() 226586470930SIngo Molnar }; 226686470930SIngo Molnar 2267e5b2c207SNamhyung Kim struct option *record_options = __record_options; 2268e5b2c207SNamhyung Kim 2269b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv) 227086470930SIngo Molnar { 2271ef149c25SAdrian Hunter int err; 22728c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 227316ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 227486470930SIngo Molnar 227567230479SArnaldo Carvalho de Melo setlocale(LC_ALL, ""); 227667230479SArnaldo Carvalho de Melo 227748e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 227848e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 227948e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 228048e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 228148e1cab1SWang Nan # undef set_nobuild 228248e1cab1SWang Nan #endif 228348e1cab1SWang Nan 22847efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 22857efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 22867efe0e03SHe Kuang # define REASON "NO_DWARF=1" 22877efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 22887efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 22897efe0e03SHe Kuang # else 22907efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 22917efe0e03SHe Kuang # endif 22927efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 22937efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 22947efe0e03SHe Kuang # undef set_nobuild 22957efe0e03SHe Kuang # undef REASON 22967efe0e03SHe Kuang #endif 22977efe0e03SHe Kuang 22989d2ed645SAlexey Budankov CPU_ZERO(&rec->affinity_mask); 22999d2ed645SAlexey Budankov rec->opts.affinity = PERF_AFFINITY_SYS; 23009d2ed645SAlexey Budankov 23010f98b11cSJiri Olsa rec->evlist = evlist__new(); 23023e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 2303361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 2304361c99a6SArnaldo Carvalho de Melo 2305ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec); 2306ecc4c561SArnaldo Carvalho de Melo if (err) 2307ecc4c561SArnaldo Carvalho de Melo return err; 2308eb853e80SJiri Olsa 2309bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 2310a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 231168ba3235SNamhyung Kim if (quiet) 231268ba3235SNamhyung Kim perf_quiet_option(); 2313483635a9SJiri Olsa 2314483635a9SJiri Olsa /* Make system wide (-a) the default target. */ 2315602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 2316483635a9SJiri Olsa rec->opts.target.system_wide = true; 231786470930SIngo Molnar 2318bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 2319c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 2320c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 2321c7118369SNamhyung Kim 2322023695d9SStephane Eranian } 2323504c1ad1SAlexey Budankov 2324504c1ad1SAlexey Budankov if (rec->opts.comp_level != 0) { 2325504c1ad1SAlexey Budankov pr_debug("Compression enabled, disabling build id collection at the end of the session.\n"); 2326504c1ad1SAlexey Budankov rec->no_buildid = true; 2327504c1ad1SAlexey Budankov } 2328504c1ad1SAlexey Budankov 2329b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 2330b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 2331c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 2332c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 2333c7118369SNamhyung Kim return -EINVAL; 2334b757bb09SAdrian Hunter } 2335023695d9SStephane Eranian 2336cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) { 2337cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0); 2338cb4e1ebbSJiri Olsa return -EINVAL; 2339cb4e1ebbSJiri Olsa } 2340cb4e1ebbSJiri Olsa 2341bfacbe3bSJiri Olsa if (rec->switch_output.time) { 2342bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler); 2343bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 2344bfacbe3bSJiri Olsa } 2345bfacbe3bSJiri Olsa 234603724b2eSAndi Kleen if (rec->switch_output.num_files) { 234703724b2eSAndi Kleen rec->switch_output.filenames = calloc(sizeof(char *), 234803724b2eSAndi Kleen rec->switch_output.num_files); 234903724b2eSAndi Kleen if (!rec->switch_output.filenames) 235003724b2eSAndi Kleen return -EINVAL; 235103724b2eSAndi Kleen } 235203724b2eSAndi Kleen 23531b36c03eSAdrian Hunter /* 23541b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address 23551b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters(). 23561b36c03eSAdrian Hunter */ 23571b36c03eSAdrian Hunter symbol_conf.allow_aliases = true; 23581b36c03eSAdrian Hunter 23591b36c03eSAdrian Hunter symbol__init(NULL); 23601b36c03eSAdrian Hunter 23614b5ea3bdSAdrian Hunter err = record__auxtrace_init(rec); 23621b36c03eSAdrian Hunter if (err) 23631b36c03eSAdrian Hunter goto out; 23641b36c03eSAdrian Hunter 23650aab2136SWang Nan if (dry_run) 23665c01ad60SAdrian Hunter goto out; 23670aab2136SWang Nan 2368d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 2369d7888573SWang Nan if (err) { 2370d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 2371d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 2372d7888573SWang Nan errbuf); 23735c01ad60SAdrian Hunter goto out; 2374d7888573SWang Nan } 2375d7888573SWang Nan 2376ef149c25SAdrian Hunter err = -ENOMEM; 2377ef149c25SAdrian Hunter 23780c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 2379a1ac1d3cSStephane Eranian disable_buildid_cache(); 2380dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) { 23810c1d46a8SWang Nan /* 23820c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 23830c1d46a8SWang Nan * generation by default to reduce data file switching 23840c1d46a8SWang Nan * overhead. Still generate buildid if they are required 23850c1d46a8SWang Nan * explicitly using 23860c1d46a8SWang Nan * 238760437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \ 23880c1d46a8SWang Nan * --no-no-buildid-cache 23890c1d46a8SWang Nan * 23900c1d46a8SWang Nan * Following code equals to: 23910c1d46a8SWang Nan * 23920c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 23930c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 23940c1d46a8SWang Nan * disable_buildid_cache(); 23950c1d46a8SWang Nan */ 23960c1d46a8SWang Nan bool disable = true; 23970c1d46a8SWang Nan 23980c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 23990c1d46a8SWang Nan disable = false; 24000c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 24010c1d46a8SWang Nan disable = false; 24020c1d46a8SWang Nan if (disable) { 24030c1d46a8SWang Nan rec->no_buildid = true; 24040c1d46a8SWang Nan rec->no_buildid_cache = true; 24050c1d46a8SWang Nan disable_buildid_cache(); 24060c1d46a8SWang Nan } 24070c1d46a8SWang Nan } 2408655000e7SArnaldo Carvalho de Melo 24094ea648aeSWang Nan if (record.opts.overwrite) 24104ea648aeSWang Nan record.opts.tail_synthesize = true; 24114ea648aeSWang Nan 24126484d2f9SJiri Olsa if (rec->evlist->core.nr_entries == 0 && 24134b4cd503SArnaldo Carvalho de Melo __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { 241469aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 2415394c01edSAdrian Hunter goto out; 2416bbd36e5eSPeter Zijlstra } 241786470930SIngo Molnar 241869e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 241969e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 242069e7e5b0SAdrian Hunter 2421602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 242216ad2ffbSNamhyung Kim if (err) { 2423602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 2424c3dec27bSJiri Olsa ui__warning("%s\n", errbuf); 242516ad2ffbSNamhyung Kim } 24264bd0f2d2SNamhyung Kim 2427602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 242816ad2ffbSNamhyung Kim if (err) { 242916ad2ffbSNamhyung Kim int saved_errno = errno; 243016ad2ffbSNamhyung Kim 2431602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 24323780f488SNamhyung Kim ui__error("%s", errbuf); 243316ad2ffbSNamhyung Kim 243416ad2ffbSNamhyung Kim err = -saved_errno; 2435394c01edSAdrian Hunter goto out; 243616ad2ffbSNamhyung Kim } 24370d37aa34SArnaldo Carvalho de Melo 2438ca800068SMengting Zhang /* Enable ignoring missing threads when -u/-p option is defined. */ 2439ca800068SMengting Zhang rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; 244023dc4f15SJiri Olsa 244116ad2ffbSNamhyung Kim err = -ENOMEM; 24423e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 2443dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 244469aad6f1SArnaldo Carvalho de Melo 2445ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 2446ef149c25SAdrian Hunter if (err) 2447394c01edSAdrian Hunter goto out; 2448ef149c25SAdrian Hunter 24496156681bSNamhyung Kim /* 24506156681bSNamhyung Kim * We take all buildids when the file contains 24516156681bSNamhyung Kim * AUX area tracing data because we do not decode the 24526156681bSNamhyung Kim * trace because it would take too long. 24536156681bSNamhyung Kim */ 24546156681bSNamhyung Kim if (rec->opts.full_auxtrace) 24556156681bSNamhyung Kim rec->buildid_all = true; 24566156681bSNamhyung Kim 2457b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 245839d17dacSArnaldo Carvalho de Melo err = -EINVAL; 2459394c01edSAdrian Hunter goto out; 24607e4ff9e3SMike Galbraith } 24617e4ff9e3SMike Galbraith 246293f20c0fSAlexey Budankov if (rec->opts.nr_cblocks > nr_cblocks_max) 246393f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_max; 24645d7f4116SAlexey Budankov pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks); 2465d3d1af6fSAlexey Budankov 24669d2ed645SAlexey Budankov pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); 2467470530bbSAlexey Budankov pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); 24689d2ed645SAlexey Budankov 246951255a8aSAlexey Budankov if (rec->opts.comp_level > comp_level_max) 247051255a8aSAlexey Budankov rec->opts.comp_level = comp_level_max; 247151255a8aSAlexey Budankov pr_debug("comp level: %d\n", rec->opts.comp_level); 247251255a8aSAlexey Budankov 2473d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 2474394c01edSAdrian Hunter out: 2475c12995a5SJiri Olsa evlist__delete(rec->evlist); 2476d65a458bSArnaldo Carvalho de Melo symbol__exit(); 2477ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 247839d17dacSArnaldo Carvalho de Melo return err; 247986470930SIngo Molnar } 24802dd6d8a1SAdrian Hunter 24812dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 24822dd6d8a1SAdrian Hunter { 2483dc0c6127SJiri Olsa struct record *rec = &record; 2484dc0c6127SJiri Olsa 24855f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 24865f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 24872dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 24885f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 24895f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 24905f9cf599SWang Nan } 24913c1cb7e3SWang Nan 2492dc0c6127SJiri Olsa if (switch_output_signal(rec)) 24933c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 24942dd6d8a1SAdrian Hunter } 2495bfacbe3bSJiri Olsa 2496bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused) 2497bfacbe3bSJiri Olsa { 2498bfacbe3bSJiri Olsa struct record *rec = &record; 2499bfacbe3bSJiri Olsa 2500bfacbe3bSJiri Olsa if (switch_output_time(rec)) 2501bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger); 2502bfacbe3bSJiri Olsa } 2503