186470930SIngo Molnar /* 286470930SIngo Molnar * builtin-record.c 386470930SIngo Molnar * 486470930SIngo Molnar * Builtin record command: Record the profile of a workload 586470930SIngo Molnar * (or a CPU, or a PID) into the perf.data output file - for 686470930SIngo Molnar * later analysis via perf report. 786470930SIngo Molnar */ 886470930SIngo Molnar #include "builtin.h" 986470930SIngo Molnar 1086470930SIngo Molnar #include "perf.h" 1186470930SIngo Molnar 126122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 1386470930SIngo Molnar #include "util/util.h" 144b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1586470930SIngo Molnar #include "util/parse-events.h" 1686470930SIngo Molnar 178f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 18f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 197c6a1c65SPeter Zijlstra #include "util/header.h" 2066e274f3SFrederic Weisbecker #include "util/event.h" 21361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2269aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 238f28827aSFrederic Weisbecker #include "util/debug.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" 27a12b51c4SPaul Mackerras #include "util/cpumap.h" 28fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 29f5fc1412SJiri Olsa #include "util/data.h" 30bcc84ec6SStephane Eranian #include "util/perf_regs.h" 31ef149c25SAdrian Hunter #include "util/auxtrace.h" 32*46bc29b9SAdrian Hunter #include "util/tsc.h" 33f00898f4SAndi Kleen #include "util/parse-branch-options.h" 34bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3571dc2326SWang Nan #include "util/llvm-utils.h" 368690a2a7SWang Nan #include "util/bpf-loader.h" 37d8871ea7SWang Nan #include "asm/bug.h" 387c6a1c65SPeter Zijlstra 3986470930SIngo Molnar #include <unistd.h> 4086470930SIngo Molnar #include <sched.h> 41a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 4286470930SIngo Molnar 4378da39faSBernhard Rosenkraenzer 448c6f45a7SArnaldo Carvalho de Melo struct record { 4545694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 46b4006796SArnaldo Carvalho de Melo struct record_opts opts; 47d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 48f5fc1412SJiri Olsa struct perf_data_file file; 49ef149c25SAdrian Hunter struct auxtrace_record *itr; 50d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 51d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 52d20deb64SArnaldo Carvalho de Melo const char *progname; 53d20deb64SArnaldo Carvalho de Melo int realtime_prio; 54d20deb64SArnaldo Carvalho de Melo bool no_buildid; 55d2db9a98SWang Nan bool no_buildid_set; 56d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 57d2db9a98SWang Nan bool no_buildid_cache_set; 586156681bSNamhyung Kim bool buildid_all; 599f065194SYang Shi unsigned long long samples; 600f82ebc4SArnaldo Carvalho de Melo }; 6186470930SIngo Molnar 628c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 63f5970550SPeter Zijlstra { 64cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 654f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 668d3eca20SDavid Ahern return -1; 678d3eca20SDavid Ahern } 68f5970550SPeter Zijlstra 69cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 708d3eca20SDavid Ahern return 0; 71f5970550SPeter Zijlstra } 72f5970550SPeter Zijlstra 7345694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 74d20deb64SArnaldo Carvalho de Melo union perf_event *event, 751d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 761d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 77234fbbf5SArnaldo Carvalho de Melo { 788c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 798c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 80234fbbf5SArnaldo Carvalho de Melo } 81234fbbf5SArnaldo Carvalho de Melo 82e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 8386470930SIngo Molnar { 84e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 857b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 867b8283b5SDavid Ahern u64 old = md->prev; 87918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8886470930SIngo Molnar unsigned long size; 8986470930SIngo Molnar void *buf; 908d3eca20SDavid Ahern int rc = 0; 9186470930SIngo Molnar 92dc82009aSArnaldo Carvalho de Melo if (old == head) 938d3eca20SDavid Ahern return 0; 9486470930SIngo Molnar 95d20deb64SArnaldo Carvalho de Melo rec->samples++; 9686470930SIngo Molnar 9786470930SIngo Molnar size = head - old; 9886470930SIngo Molnar 9986470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 10086470930SIngo Molnar buf = &data[old & md->mask]; 10186470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 10286470930SIngo Molnar old += size; 10386470930SIngo Molnar 1048c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1058d3eca20SDavid Ahern rc = -1; 1068d3eca20SDavid Ahern goto out; 1078d3eca20SDavid Ahern } 10886470930SIngo Molnar } 10986470930SIngo Molnar 11086470930SIngo Molnar buf = &data[old & md->mask]; 11186470930SIngo Molnar size = head - old; 11286470930SIngo Molnar old += size; 11386470930SIngo Molnar 1148c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1158d3eca20SDavid Ahern rc = -1; 1168d3eca20SDavid Ahern goto out; 1178d3eca20SDavid Ahern } 11886470930SIngo Molnar 11986470930SIngo Molnar md->prev = old; 120e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1218d3eca20SDavid Ahern out: 1228d3eca20SDavid Ahern return rc; 12386470930SIngo Molnar } 12486470930SIngo Molnar 1252dd6d8a1SAdrian Hunter static volatile int done; 1262dd6d8a1SAdrian Hunter static volatile int signr = -1; 1272dd6d8a1SAdrian Hunter static volatile int child_finished; 1282dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1292dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1302dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1312dd6d8a1SAdrian Hunter 1322dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1332dd6d8a1SAdrian Hunter { 1342dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1352dd6d8a1SAdrian Hunter child_finished = 1; 1362dd6d8a1SAdrian Hunter else 1372dd6d8a1SAdrian Hunter signr = sig; 1382dd6d8a1SAdrian Hunter 1392dd6d8a1SAdrian Hunter done = 1; 1402dd6d8a1SAdrian Hunter } 1412dd6d8a1SAdrian Hunter 1422dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1432dd6d8a1SAdrian Hunter { 1442dd6d8a1SAdrian Hunter if (signr == -1) 1452dd6d8a1SAdrian Hunter return; 1462dd6d8a1SAdrian Hunter 1472dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1482dd6d8a1SAdrian Hunter raise(signr); 1492dd6d8a1SAdrian Hunter } 1502dd6d8a1SAdrian Hunter 151e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 152e31f0d01SAdrian Hunter 153ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 154ef149c25SAdrian Hunter union perf_event *event, void *data1, 155ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 156ef149c25SAdrian Hunter { 157ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 15899fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 159ef149c25SAdrian Hunter size_t padding; 160ef149c25SAdrian Hunter u8 pad[8] = {0}; 161ef149c25SAdrian Hunter 16299fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 16399fa2984SAdrian Hunter off_t file_offset; 16499fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 16599fa2984SAdrian Hunter int err; 16699fa2984SAdrian Hunter 16799fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 16899fa2984SAdrian Hunter if (file_offset == -1) 16999fa2984SAdrian Hunter return -1; 17099fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 17199fa2984SAdrian Hunter event, file_offset); 17299fa2984SAdrian Hunter if (err) 17399fa2984SAdrian Hunter return err; 17499fa2984SAdrian Hunter } 17599fa2984SAdrian Hunter 176ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 177ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 178ef149c25SAdrian Hunter if (padding) 179ef149c25SAdrian Hunter padding = 8 - padding; 180ef149c25SAdrian Hunter 181ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 182ef149c25SAdrian Hunter record__write(rec, data1, len1); 183ef149c25SAdrian Hunter if (len2) 184ef149c25SAdrian Hunter record__write(rec, data2, len2); 185ef149c25SAdrian Hunter record__write(rec, &pad, padding); 186ef149c25SAdrian Hunter 187ef149c25SAdrian Hunter return 0; 188ef149c25SAdrian Hunter } 189ef149c25SAdrian Hunter 190ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 191ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 192ef149c25SAdrian Hunter { 193ef149c25SAdrian Hunter int ret; 194ef149c25SAdrian Hunter 195ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 196ef149c25SAdrian Hunter record__process_auxtrace); 197ef149c25SAdrian Hunter if (ret < 0) 198ef149c25SAdrian Hunter return ret; 199ef149c25SAdrian Hunter 200ef149c25SAdrian Hunter if (ret) 201ef149c25SAdrian Hunter rec->samples++; 202ef149c25SAdrian Hunter 203ef149c25SAdrian Hunter return 0; 204ef149c25SAdrian Hunter } 205ef149c25SAdrian Hunter 2062dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2072dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2082dd6d8a1SAdrian Hunter { 2092dd6d8a1SAdrian Hunter int ret; 2102dd6d8a1SAdrian Hunter 2112dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2122dd6d8a1SAdrian Hunter record__process_auxtrace, 2132dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2142dd6d8a1SAdrian Hunter if (ret < 0) 2152dd6d8a1SAdrian Hunter return ret; 2162dd6d8a1SAdrian Hunter 2172dd6d8a1SAdrian Hunter if (ret) 2182dd6d8a1SAdrian Hunter rec->samples++; 2192dd6d8a1SAdrian Hunter 2202dd6d8a1SAdrian Hunter return 0; 2212dd6d8a1SAdrian Hunter } 2222dd6d8a1SAdrian Hunter 2232dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2242dd6d8a1SAdrian Hunter { 2252dd6d8a1SAdrian Hunter int i; 2262dd6d8a1SAdrian Hunter int rc = 0; 2272dd6d8a1SAdrian Hunter 2282dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2292dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2302dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2312dd6d8a1SAdrian Hunter 2322dd6d8a1SAdrian Hunter if (!mm->base) 2332dd6d8a1SAdrian Hunter continue; 2342dd6d8a1SAdrian Hunter 2352dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2362dd6d8a1SAdrian Hunter rc = -1; 2372dd6d8a1SAdrian Hunter goto out; 2382dd6d8a1SAdrian Hunter } 2392dd6d8a1SAdrian Hunter } 2402dd6d8a1SAdrian Hunter out: 2412dd6d8a1SAdrian Hunter return rc; 2422dd6d8a1SAdrian Hunter } 2432dd6d8a1SAdrian Hunter 2442dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2452dd6d8a1SAdrian Hunter { 2462dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2472dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2482dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2492dd6d8a1SAdrian Hunter } else { 2502dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2512dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2522dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2532dd6d8a1SAdrian Hunter } 2542dd6d8a1SAdrian Hunter } 2552dd6d8a1SAdrian Hunter 256e31f0d01SAdrian Hunter #else 257e31f0d01SAdrian Hunter 258e31f0d01SAdrian Hunter static inline 259e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 260e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 261e31f0d01SAdrian Hunter { 262e31f0d01SAdrian Hunter return 0; 263e31f0d01SAdrian Hunter } 264e31f0d01SAdrian Hunter 2652dd6d8a1SAdrian Hunter static inline 2662dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2672dd6d8a1SAdrian Hunter { 2682dd6d8a1SAdrian Hunter } 2692dd6d8a1SAdrian Hunter 2702dd6d8a1SAdrian Hunter static inline 2712dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2722dd6d8a1SAdrian Hunter { 2732dd6d8a1SAdrian Hunter return 0; 2742dd6d8a1SAdrian Hunter } 2752dd6d8a1SAdrian Hunter 276e31f0d01SAdrian Hunter #endif 277e31f0d01SAdrian Hunter 2788c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 279dd7927f4SArnaldo Carvalho de Melo { 28056e52e85SArnaldo Carvalho de Melo char msg[512]; 2816a4bb04cSJiri Olsa struct perf_evsel *pos; 282d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 283d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 284b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2858d3eca20SDavid Ahern int rc = 0; 286dd7927f4SArnaldo Carvalho de Melo 287f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 288cac21425SJiri Olsa 2890050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2903da297a6SIngo Molnar try_again: 291d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 29256e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2933da297a6SIngo Molnar if (verbose) 294c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2953da297a6SIngo Molnar goto try_again; 2963da297a6SIngo Molnar } 297ca6a4258SDavid Ahern 29856e52e85SArnaldo Carvalho de Melo rc = -errno; 29956e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 30056e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 30156e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3028d3eca20SDavid Ahern goto out; 3037c6a1c65SPeter Zijlstra } 3047c6a1c65SPeter Zijlstra } 3057c6a1c65SPeter Zijlstra 30623d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 30723d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 30823d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30935550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3108d3eca20SDavid Ahern rc = -1; 3118d3eca20SDavid Ahern goto out; 3120a102479SFrederic Weisbecker } 3130a102479SFrederic Weisbecker 314ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3152dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3162dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3178d3eca20SDavid Ahern if (errno == EPERM) { 3188d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31918e60939SNelson Elhage "Consider increasing " 32018e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 32118e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 322ef149c25SAdrian Hunter "(current value: %u,%u)\n", 323ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3248d3eca20SDavid Ahern rc = -errno; 3258d3eca20SDavid Ahern } else { 32635550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 32735550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 32895c36561SWang Nan if (errno) 3298d3eca20SDavid Ahern rc = -errno; 33095c36561SWang Nan else 33195c36561SWang Nan rc = -EINVAL; 3328d3eca20SDavid Ahern } 3338d3eca20SDavid Ahern goto out; 33418e60939SNelson Elhage } 3350a27d7f9SArnaldo Carvalho de Melo 336a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3377b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3388d3eca20SDavid Ahern out: 3398d3eca20SDavid Ahern return rc; 340a91e5431SArnaldo Carvalho de Melo } 341a91e5431SArnaldo Carvalho de Melo 342e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 343e3d59112SNamhyung Kim union perf_event *event, 344e3d59112SNamhyung Kim struct perf_sample *sample, 345e3d59112SNamhyung Kim struct perf_evsel *evsel, 346e3d59112SNamhyung Kim struct machine *machine) 347e3d59112SNamhyung Kim { 348e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 349e3d59112SNamhyung Kim 350e3d59112SNamhyung Kim rec->samples++; 351e3d59112SNamhyung Kim 352e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 353e3d59112SNamhyung Kim } 354e3d59112SNamhyung Kim 3558c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3566122e4e4SArnaldo Carvalho de Melo { 357f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 358f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3596122e4e4SArnaldo Carvalho de Melo 360457ae94aSHe Kuang if (file->size == 0) 3619f591fd7SArnaldo Carvalho de Melo return 0; 3629f591fd7SArnaldo Carvalho de Melo 36300dc8657SNamhyung Kim /* 36400dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 36500dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 36600dc8657SNamhyung Kim * we prefer the vmlinux path like 36700dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 36800dc8657SNamhyung Kim * 36900dc8657SNamhyung Kim * rather than build-id path (in debug directory). 37000dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 37100dc8657SNamhyung Kim */ 37200dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 37300dc8657SNamhyung Kim 3746156681bSNamhyung Kim /* 3756156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 3766156681bSNamhyung Kim * so no need to process samples. 3776156681bSNamhyung Kim */ 3786156681bSNamhyung Kim if (rec->buildid_all) 3796156681bSNamhyung Kim rec->tool.sample = NULL; 3806156681bSNamhyung Kim 381b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3826122e4e4SArnaldo Carvalho de Melo } 3836122e4e4SArnaldo Carvalho de Melo 3848115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 385a1645ce1SZhang, Yanmin { 386a1645ce1SZhang, Yanmin int err; 38745694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 388a1645ce1SZhang, Yanmin /* 389a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 390a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 391a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 392a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 393a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 394a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 395a1645ce1SZhang, Yanmin */ 39645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 397743eb868SArnaldo Carvalho de Melo machine); 398a1645ce1SZhang, Yanmin if (err < 0) 399a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 40023346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 401a1645ce1SZhang, Yanmin 402a1645ce1SZhang, Yanmin /* 403a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 404a1645ce1SZhang, Yanmin * have no _text sometimes. 405a1645ce1SZhang, Yanmin */ 40645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4070ae617beSAdrian Hunter machine); 408a1645ce1SZhang, Yanmin if (err < 0) 409a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 41023346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 411a1645ce1SZhang, Yanmin } 412a1645ce1SZhang, Yanmin 41398402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 41498402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 41598402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 41698402807SFrederic Weisbecker }; 41798402807SFrederic Weisbecker 4188c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 41998402807SFrederic Weisbecker { 420dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4210e2e63ddSPeter Zijlstra int i; 4228d3eca20SDavid Ahern int rc = 0; 42398402807SFrederic Weisbecker 424d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 425ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 426ef149c25SAdrian Hunter 4278d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 428e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4298d3eca20SDavid Ahern rc = -1; 4308d3eca20SDavid Ahern goto out; 4318d3eca20SDavid Ahern } 4328d3eca20SDavid Ahern } 433ef149c25SAdrian Hunter 4342dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 435ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 436ef149c25SAdrian Hunter rc = -1; 437ef149c25SAdrian Hunter goto out; 438ef149c25SAdrian Hunter } 43998402807SFrederic Weisbecker } 44098402807SFrederic Weisbecker 441dcabb507SJiri Olsa /* 442dcabb507SJiri Olsa * Mark the round finished in case we wrote 443dcabb507SJiri Olsa * at least one event. 444dcabb507SJiri Olsa */ 445dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4468c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4478d3eca20SDavid Ahern 4488d3eca20SDavid Ahern out: 4498d3eca20SDavid Ahern return rc; 45098402807SFrederic Weisbecker } 45198402807SFrederic Weisbecker 4528c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 45357706abcSDavid Ahern { 45457706abcSDavid Ahern struct perf_session *session = rec->session; 45557706abcSDavid Ahern int feat; 45657706abcSDavid Ahern 45757706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 45857706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 45957706abcSDavid Ahern 46057706abcSDavid Ahern if (rec->no_buildid) 46157706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 46257706abcSDavid Ahern 4633e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 46457706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 46557706abcSDavid Ahern 46657706abcSDavid Ahern if (!rec->opts.branch_stack) 46757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 468ef149c25SAdrian Hunter 469ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 470ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 471ffa517adSJiri Olsa 472ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 47357706abcSDavid Ahern } 47457706abcSDavid Ahern 475e1ab48baSWang Nan static void 476e1ab48baSWang Nan record__finish_output(struct record *rec) 477e1ab48baSWang Nan { 478e1ab48baSWang Nan struct perf_data_file *file = &rec->file; 479e1ab48baSWang Nan int fd = perf_data_file__fd(file); 480e1ab48baSWang Nan 481e1ab48baSWang Nan if (file->is_pipe) 482e1ab48baSWang Nan return; 483e1ab48baSWang Nan 484e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 485e1ab48baSWang Nan file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 486e1ab48baSWang Nan 487e1ab48baSWang Nan if (!rec->no_buildid) { 488e1ab48baSWang Nan process_buildids(rec); 489e1ab48baSWang Nan 490e1ab48baSWang Nan if (rec->buildid_all) 491e1ab48baSWang Nan dsos__hit_all(rec->session); 492e1ab48baSWang Nan } 493e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 494e1ab48baSWang Nan 495e1ab48baSWang Nan return; 496e1ab48baSWang Nan } 497e1ab48baSWang Nan 498f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 499f33cbe72SArnaldo Carvalho de Melo 500f33cbe72SArnaldo Carvalho de Melo /* 501f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 502f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 503f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 504f33cbe72SArnaldo Carvalho de Melo */ 50545604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 50645604710SNamhyung Kim siginfo_t *info, 507f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 508f33cbe72SArnaldo Carvalho de Melo { 509f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 510f33cbe72SArnaldo Carvalho de Melo done = 1; 511f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 512f33cbe72SArnaldo Carvalho de Melo } 513f33cbe72SArnaldo Carvalho de Melo 5142dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 5152dd6d8a1SAdrian Hunter 516*46bc29b9SAdrian Hunter int __weak 517*46bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 518*46bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 519*46bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 520*46bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 521*46bc29b9SAdrian Hunter { 522*46bc29b9SAdrian Hunter return 0; 523*46bc29b9SAdrian Hunter } 524*46bc29b9SAdrian Hunter 525c45c86ebSWang Nan static int record__synthesize(struct record *rec) 526c45c86ebSWang Nan { 527c45c86ebSWang Nan struct perf_session *session = rec->session; 528c45c86ebSWang Nan struct machine *machine = &session->machines.host; 529c45c86ebSWang Nan struct perf_data_file *file = &rec->file; 530c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 531c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 532c45c86ebSWang Nan int fd = perf_data_file__fd(file); 533c45c86ebSWang Nan int err = 0; 534c45c86ebSWang Nan 535c45c86ebSWang Nan if (file->is_pipe) { 536c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 537c45c86ebSWang Nan process_synthesized_event); 538c45c86ebSWang Nan if (err < 0) { 539c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 540c45c86ebSWang Nan goto out; 541c45c86ebSWang Nan } 542c45c86ebSWang Nan 543c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 544c45c86ebSWang Nan /* 545c45c86ebSWang Nan * FIXME err <= 0 here actually means that 546c45c86ebSWang Nan * there were no tracepoints so its not really 547c45c86ebSWang Nan * an error, just that we don't need to 548c45c86ebSWang Nan * synthesize anything. We really have to 549c45c86ebSWang Nan * return this more properly and also 550c45c86ebSWang Nan * propagate errors that now are calling die() 551c45c86ebSWang Nan */ 552c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 553c45c86ebSWang Nan process_synthesized_event); 554c45c86ebSWang Nan if (err <= 0) { 555c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 556c45c86ebSWang Nan goto out; 557c45c86ebSWang Nan } 558c45c86ebSWang Nan rec->bytes_written += err; 559c45c86ebSWang Nan } 560c45c86ebSWang Nan } 561c45c86ebSWang Nan 562*46bc29b9SAdrian Hunter err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool, 563*46bc29b9SAdrian Hunter process_synthesized_event, machine); 564*46bc29b9SAdrian Hunter if (err) 565*46bc29b9SAdrian Hunter goto out; 566*46bc29b9SAdrian Hunter 567c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 568c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 569c45c86ebSWang Nan session, process_synthesized_event); 570c45c86ebSWang Nan if (err) 571c45c86ebSWang Nan goto out; 572c45c86ebSWang Nan } 573c45c86ebSWang Nan 574c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 575c45c86ebSWang Nan machine); 576c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 577c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 578c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 579c45c86ebSWang Nan 580c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 581c45c86ebSWang Nan machine); 582c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 583c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 584c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 585c45c86ebSWang Nan 586c45c86ebSWang Nan if (perf_guest) { 587c45c86ebSWang Nan machines__process_guests(&session->machines, 588c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 589c45c86ebSWang Nan } 590c45c86ebSWang Nan 591c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 592c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 593c45c86ebSWang Nan opts->proc_map_timeout); 594c45c86ebSWang Nan out: 595c45c86ebSWang Nan return err; 596c45c86ebSWang Nan } 597c45c86ebSWang Nan 5988c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 59986470930SIngo Molnar { 60057706abcSDavid Ahern int err; 60145604710SNamhyung Kim int status = 0; 6028b412664SPeter Zijlstra unsigned long waking = 0; 60346be604bSZhang, Yanmin const bool forks = argc > 0; 60423346f21SArnaldo Carvalho de Melo struct machine *machine; 60545694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 606b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 607f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 608d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 6096dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 61042aa276fSNamhyung Kim int fd; 61186470930SIngo Molnar 612d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 61333e49ea7SAndi Kleen 61445604710SNamhyung Kim atexit(record__sig_exit); 615f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 616f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 617804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 6182dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 6192dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 6202dd6d8a1SAdrian Hunter else 6212dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 622f5970550SPeter Zijlstra 623b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 62494c744b6SArnaldo Carvalho de Melo if (session == NULL) { 625ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 626a9a70bbcSArnaldo Carvalho de Melo return -1; 627a9a70bbcSArnaldo Carvalho de Melo } 628a9a70bbcSArnaldo Carvalho de Melo 62942aa276fSNamhyung Kim fd = perf_data_file__fd(file); 630d20deb64SArnaldo Carvalho de Melo rec->session = session; 631d20deb64SArnaldo Carvalho de Melo 6328c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 633330aa675SStephane Eranian 634d4db3f16SArnaldo Carvalho de Melo if (forks) { 6353e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 636f5fc1412SJiri Olsa argv, file->is_pipe, 637735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 63835b9d88eSArnaldo Carvalho de Melo if (err < 0) { 63935b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 64045604710SNamhyung Kim status = err; 64135b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 642856e9660SPeter Zijlstra } 643856e9660SPeter Zijlstra } 644856e9660SPeter Zijlstra 6458c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 6468d3eca20SDavid Ahern err = -1; 64745604710SNamhyung Kim goto out_child; 6488d3eca20SDavid Ahern } 64986470930SIngo Molnar 6508690a2a7SWang Nan err = bpf__apply_obj_config(); 6518690a2a7SWang Nan if (err) { 6528690a2a7SWang Nan char errbuf[BUFSIZ]; 6538690a2a7SWang Nan 6548690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 6558690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 6568690a2a7SWang Nan errbuf); 6578690a2a7SWang Nan goto out_child; 6588690a2a7SWang Nan } 6598690a2a7SWang Nan 660cca8482cSAdrian Hunter /* 661cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 662cca8482cSAdrian Hunter * evlist. 663cca8482cSAdrian Hunter */ 664cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 665cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 666cca8482cSAdrian Hunter rec->tool.ordered_events = false; 667cca8482cSAdrian Hunter } 668cca8482cSAdrian Hunter 6693e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 670a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 671a8bb559bSNamhyung Kim 672f5fc1412SJiri Olsa if (file->is_pipe) { 67342aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 674529870e3STom Zanussi if (err < 0) 67545604710SNamhyung Kim goto out_child; 676563aecb2SJiri Olsa } else { 67742aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 678d5eed904SArnaldo Carvalho de Melo if (err < 0) 67945604710SNamhyung Kim goto out_child; 680d5eed904SArnaldo Carvalho de Melo } 6817c6a1c65SPeter Zijlstra 682d3665498SDavid Ahern if (!rec->no_buildid 683e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 684d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 685e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 6868d3eca20SDavid Ahern err = -1; 68745604710SNamhyung Kim goto out_child; 688e20960c0SRobert Richter } 689e20960c0SRobert Richter 69034ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 691743eb868SArnaldo Carvalho de Melo 692c45c86ebSWang Nan err = record__synthesize(rec); 693c45c86ebSWang Nan if (err < 0) 69445604710SNamhyung Kim goto out_child; 6958d3eca20SDavid Ahern 696d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 69786470930SIngo Molnar struct sched_param param; 69886470930SIngo Molnar 699d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 70086470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 7016beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 7028d3eca20SDavid Ahern err = -1; 70345604710SNamhyung Kim goto out_child; 70486470930SIngo Molnar } 70586470930SIngo Molnar } 70686470930SIngo Molnar 707774cb499SJiri Olsa /* 708774cb499SJiri Olsa * When perf is starting the traced process, all the events 709774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 710774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 711774cb499SJiri Olsa */ 7126619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 7133e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 714764e16a3SDavid Ahern 715856e9660SPeter Zijlstra /* 716856e9660SPeter Zijlstra * Let the child rip 717856e9660SPeter Zijlstra */ 718e803cf97SNamhyung Kim if (forks) { 719e5bed564SNamhyung Kim union perf_event *event; 720e5bed564SNamhyung Kim 721e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 722e5bed564SNamhyung Kim if (event == NULL) { 723e5bed564SNamhyung Kim err = -ENOMEM; 724e5bed564SNamhyung Kim goto out_child; 725e5bed564SNamhyung Kim } 726e5bed564SNamhyung Kim 727e803cf97SNamhyung Kim /* 728e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 729e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 730e803cf97SNamhyung Kim * cannot see a correct process name for those events. 731e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 732e803cf97SNamhyung Kim */ 733e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 734e803cf97SNamhyung Kim rec->evlist->workload.pid, 735e803cf97SNamhyung Kim process_synthesized_event, 736e803cf97SNamhyung Kim machine); 737e5bed564SNamhyung Kim free(event); 738e803cf97SNamhyung Kim 7393e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 740e803cf97SNamhyung Kim } 741856e9660SPeter Zijlstra 7426619a53eSAndi Kleen if (opts->initial_delay) { 7436619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 7446619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 7456619a53eSAndi Kleen } 7466619a53eSAndi Kleen 7472dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 748649c48a9SPeter Zijlstra for (;;) { 7499f065194SYang Shi unsigned long long hits = rec->samples; 75086470930SIngo Molnar 7518c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 7522dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7538d3eca20SDavid Ahern err = -1; 75445604710SNamhyung Kim goto out_child; 7558d3eca20SDavid Ahern } 75686470930SIngo Molnar 7572dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 7582dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 7592dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 7602dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 7612dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 7622dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 7632dd6d8a1SAdrian Hunter err = -1; 7642dd6d8a1SAdrian Hunter goto out_child; 7652dd6d8a1SAdrian Hunter } 7662dd6d8a1SAdrian Hunter } 7672dd6d8a1SAdrian Hunter 768d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 7696dcf45efSArnaldo Carvalho de Melo if (done || draining) 770649c48a9SPeter Zijlstra break; 771f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 772a515114fSJiri Olsa /* 773a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 774a515114fSJiri Olsa * number of returned events and interrupt error. 775a515114fSJiri Olsa */ 776a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 77745604710SNamhyung Kim err = 0; 7788b412664SPeter Zijlstra waking++; 7796dcf45efSArnaldo Carvalho de Melo 7806dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 7816dcf45efSArnaldo Carvalho de Melo draining = true; 7828b412664SPeter Zijlstra } 7838b412664SPeter Zijlstra 784774cb499SJiri Olsa /* 785774cb499SJiri Olsa * When perf is starting the traced process, at the end events 786774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 787774cb499SJiri Olsa * disable events in this case. 788774cb499SJiri Olsa */ 789602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 7902dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7913e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 7922711926aSJiri Olsa disabled = true; 7932711926aSJiri Olsa } 7948b412664SPeter Zijlstra } 7952dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7968b412664SPeter Zijlstra 797f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 79835550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 799f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 800f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 801f33cbe72SArnaldo Carvalho de Melo err = -1; 80245604710SNamhyung Kim goto out_child; 803f33cbe72SArnaldo Carvalho de Melo } 804f33cbe72SArnaldo Carvalho de Melo 805e3d59112SNamhyung Kim if (!quiet) 8068b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 80786470930SIngo Molnar 80845604710SNamhyung Kim out_child: 80945604710SNamhyung Kim if (forks) { 81045604710SNamhyung Kim int exit_status; 81145604710SNamhyung Kim 81245604710SNamhyung Kim if (!child_finished) 81345604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 81445604710SNamhyung Kim 81545604710SNamhyung Kim wait(&exit_status); 81645604710SNamhyung Kim 81745604710SNamhyung Kim if (err < 0) 81845604710SNamhyung Kim status = err; 81945604710SNamhyung Kim else if (WIFEXITED(exit_status)) 82045604710SNamhyung Kim status = WEXITSTATUS(exit_status); 82145604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 82245604710SNamhyung Kim signr = WTERMSIG(exit_status); 82345604710SNamhyung Kim } else 82445604710SNamhyung Kim status = err; 82545604710SNamhyung Kim 826e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 827e3d59112SNamhyung Kim rec->samples = 0; 828e3d59112SNamhyung Kim 829e1ab48baSWang Nan if (!err) 830e1ab48baSWang Nan record__finish_output(rec); 83139d17dacSArnaldo Carvalho de Melo 832e3d59112SNamhyung Kim if (!err && !quiet) { 833e3d59112SNamhyung Kim char samples[128]; 834e3d59112SNamhyung Kim 835ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 836e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 837e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 838e3d59112SNamhyung Kim else 839e3d59112SNamhyung Kim samples[0] = '\0'; 840e3d59112SNamhyung Kim 841e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 842e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 843e3d59112SNamhyung Kim file->path, samples); 844e3d59112SNamhyung Kim } 845e3d59112SNamhyung Kim 84639d17dacSArnaldo Carvalho de Melo out_delete_session: 84739d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 84845604710SNamhyung Kim return status; 84986470930SIngo Molnar } 85086470930SIngo Molnar 85172a128aaSNamhyung Kim static void callchain_debug(void) 85209b0fd45SJiri Olsa { 853aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 854a601fdffSJiri Olsa 85572a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 85626d33022SJiri Olsa 85772a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 85809b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 85972a128aaSNamhyung Kim callchain_param.dump_size); 86009b0fd45SJiri Olsa } 86109b0fd45SJiri Olsa 862c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 86309b0fd45SJiri Olsa const char *arg, 86409b0fd45SJiri Olsa int unset) 86509b0fd45SJiri Olsa { 86609b0fd45SJiri Olsa int ret; 867c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 86809b0fd45SJiri Olsa 869c421e80bSKan Liang record->callgraph_set = true; 87072a128aaSNamhyung Kim callchain_param.enabled = !unset; 871eb853e80SJiri Olsa 87209b0fd45SJiri Olsa /* --no-call-graph */ 87309b0fd45SJiri Olsa if (unset) { 87472a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 87509b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 87609b0fd45SJiri Olsa return 0; 87709b0fd45SJiri Olsa } 87809b0fd45SJiri Olsa 879c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 8805c0cf224SJiri Olsa if (!ret) { 8815c0cf224SJiri Olsa /* Enable data address sampling for DWARF unwind. */ 8825c0cf224SJiri Olsa if (callchain_param.record_mode == CALLCHAIN_DWARF) 8835c0cf224SJiri Olsa record->sample_address = true; 88472a128aaSNamhyung Kim callchain_debug(); 8855c0cf224SJiri Olsa } 88609b0fd45SJiri Olsa 88726d33022SJiri Olsa return ret; 88826d33022SJiri Olsa } 88926d33022SJiri Olsa 890c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 89109b0fd45SJiri Olsa const char *arg __maybe_unused, 89209b0fd45SJiri Olsa int unset __maybe_unused) 89309b0fd45SJiri Olsa { 894c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 895c421e80bSKan Liang 896c421e80bSKan Liang record->callgraph_set = true; 89772a128aaSNamhyung Kim callchain_param.enabled = true; 89809b0fd45SJiri Olsa 89972a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 90072a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 901eb853e80SJiri Olsa 90272a128aaSNamhyung Kim callchain_debug(); 90309b0fd45SJiri Olsa return 0; 90409b0fd45SJiri Olsa } 90509b0fd45SJiri Olsa 906eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 907eb853e80SJiri Olsa { 9087a29c087SNamhyung Kim struct record *rec = cb; 9097a29c087SNamhyung Kim 9107a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 9117a29c087SNamhyung Kim if (!strcmp(value, "cache")) 9127a29c087SNamhyung Kim rec->no_buildid_cache = false; 9137a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 9147a29c087SNamhyung Kim rec->no_buildid_cache = true; 9157a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 9167a29c087SNamhyung Kim rec->no_buildid = true; 9177a29c087SNamhyung Kim else 9187a29c087SNamhyung Kim return -1; 9197a29c087SNamhyung Kim return 0; 9207a29c087SNamhyung Kim } 921eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 9225a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 923eb853e80SJiri Olsa 924eb853e80SJiri Olsa return perf_default_config(var, value, cb); 925eb853e80SJiri Olsa } 926eb853e80SJiri Olsa 927814c8c38SPeter Zijlstra struct clockid_map { 928814c8c38SPeter Zijlstra const char *name; 929814c8c38SPeter Zijlstra int clockid; 930814c8c38SPeter Zijlstra }; 931814c8c38SPeter Zijlstra 932814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 933814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 934814c8c38SPeter Zijlstra 935814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 936814c8c38SPeter Zijlstra 937814c8c38SPeter Zijlstra 938814c8c38SPeter Zijlstra /* 939814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 940814c8c38SPeter Zijlstra */ 941814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 942814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 943814c8c38SPeter Zijlstra #endif 944814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 945814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 946814c8c38SPeter Zijlstra #endif 947814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 948814c8c38SPeter Zijlstra #define CLOCK_TAI 11 949814c8c38SPeter Zijlstra #endif 950814c8c38SPeter Zijlstra 951814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 952814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 953814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 954814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 955814c8c38SPeter Zijlstra 956814c8c38SPeter Zijlstra /* available for some events */ 957814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 958814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 959814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 960814c8c38SPeter Zijlstra 961814c8c38SPeter Zijlstra /* available for the lazy */ 962814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 963814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 964814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 965814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 966814c8c38SPeter Zijlstra 967814c8c38SPeter Zijlstra CLOCKID_END, 968814c8c38SPeter Zijlstra }; 969814c8c38SPeter Zijlstra 970814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 971814c8c38SPeter Zijlstra { 972814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 973814c8c38SPeter Zijlstra const struct clockid_map *cm; 974814c8c38SPeter Zijlstra const char *ostr = str; 975814c8c38SPeter Zijlstra 976814c8c38SPeter Zijlstra if (unset) { 977814c8c38SPeter Zijlstra opts->use_clockid = 0; 978814c8c38SPeter Zijlstra return 0; 979814c8c38SPeter Zijlstra } 980814c8c38SPeter Zijlstra 981814c8c38SPeter Zijlstra /* no arg passed */ 982814c8c38SPeter Zijlstra if (!str) 983814c8c38SPeter Zijlstra return 0; 984814c8c38SPeter Zijlstra 985814c8c38SPeter Zijlstra /* no setting it twice */ 986814c8c38SPeter Zijlstra if (opts->use_clockid) 987814c8c38SPeter Zijlstra return -1; 988814c8c38SPeter Zijlstra 989814c8c38SPeter Zijlstra opts->use_clockid = true; 990814c8c38SPeter Zijlstra 991814c8c38SPeter Zijlstra /* if its a number, we're done */ 992814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 993814c8c38SPeter Zijlstra return 0; 994814c8c38SPeter Zijlstra 995814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 996814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 997814c8c38SPeter Zijlstra str += 6; 998814c8c38SPeter Zijlstra 999814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1000814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1001814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1002814c8c38SPeter Zijlstra return 0; 1003814c8c38SPeter Zijlstra } 1004814c8c38SPeter Zijlstra } 1005814c8c38SPeter Zijlstra 1006814c8c38SPeter Zijlstra opts->use_clockid = false; 1007814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1008814c8c38SPeter Zijlstra return -1; 1009814c8c38SPeter Zijlstra } 1010814c8c38SPeter Zijlstra 1011e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1012e9db1310SAdrian Hunter const char *str, 1013e9db1310SAdrian Hunter int unset __maybe_unused) 1014e9db1310SAdrian Hunter { 1015e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1016e9db1310SAdrian Hunter char *s, *p; 1017e9db1310SAdrian Hunter unsigned int mmap_pages; 1018e9db1310SAdrian Hunter int ret; 1019e9db1310SAdrian Hunter 1020e9db1310SAdrian Hunter if (!str) 1021e9db1310SAdrian Hunter return -EINVAL; 1022e9db1310SAdrian Hunter 1023e9db1310SAdrian Hunter s = strdup(str); 1024e9db1310SAdrian Hunter if (!s) 1025e9db1310SAdrian Hunter return -ENOMEM; 1026e9db1310SAdrian Hunter 1027e9db1310SAdrian Hunter p = strchr(s, ','); 1028e9db1310SAdrian Hunter if (p) 1029e9db1310SAdrian Hunter *p = '\0'; 1030e9db1310SAdrian Hunter 1031e9db1310SAdrian Hunter if (*s) { 1032e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1033e9db1310SAdrian Hunter if (ret) 1034e9db1310SAdrian Hunter goto out_free; 1035e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1036e9db1310SAdrian Hunter } 1037e9db1310SAdrian Hunter 1038e9db1310SAdrian Hunter if (!p) { 1039e9db1310SAdrian Hunter ret = 0; 1040e9db1310SAdrian Hunter goto out_free; 1041e9db1310SAdrian Hunter } 1042e9db1310SAdrian Hunter 1043e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1044e9db1310SAdrian Hunter if (ret) 1045e9db1310SAdrian Hunter goto out_free; 1046e9db1310SAdrian Hunter 1047e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1048e9db1310SAdrian Hunter 1049e9db1310SAdrian Hunter out_free: 1050e9db1310SAdrian Hunter free(s); 1051e9db1310SAdrian Hunter return ret; 1052e9db1310SAdrian Hunter } 1053e9db1310SAdrian Hunter 1054e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 105586470930SIngo Molnar "perf record [<options>] [<command>]", 105686470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 105786470930SIngo Molnar NULL 105886470930SIngo Molnar }; 1059e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 106086470930SIngo Molnar 1061d20deb64SArnaldo Carvalho de Melo /* 10628c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 10638c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1064d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1065d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1066d20deb64SArnaldo Carvalho de Melo * 1067d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1068d20deb64SArnaldo Carvalho de Melo * 1069d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1070d20deb64SArnaldo Carvalho de Melo */ 10718c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1072d20deb64SArnaldo Carvalho de Melo .opts = { 10738affc2b8SAndi Kleen .sample_time = true, 1074d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1075d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1076d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1077447a6013SArnaldo Carvalho de Melo .freq = 4000, 1078d1cb9fceSNamhyung Kim .target = { 1079d1cb9fceSNamhyung Kim .uses_mmap = true, 10803aa5939dSAdrian Hunter .default_per_cpu = true, 1081d1cb9fceSNamhyung Kim }, 10829d9cad76SKan Liang .proc_map_timeout = 500, 1083d20deb64SArnaldo Carvalho de Melo }, 1084e3d59112SNamhyung Kim .tool = { 1085e3d59112SNamhyung Kim .sample = process_sample_event, 1086e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1087cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1088e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1089e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1090e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1091cca8482cSAdrian Hunter .ordered_events = true, 1092e3d59112SNamhyung Kim }, 1093d20deb64SArnaldo Carvalho de Melo }; 10947865e817SFrederic Weisbecker 109576a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 109676a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 109761eaa3beSArnaldo Carvalho de Melo 1098d20deb64SArnaldo Carvalho de Melo /* 1099d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1100d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1101b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1102d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1103d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1104d20deb64SArnaldo Carvalho de Melo */ 1105e5b2c207SNamhyung Kim struct option __record_options[] = { 1106d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 110786470930SIngo Molnar "event selector. use 'perf list' to list available events", 1108f120f9d5SJiri Olsa parse_events_option), 1109d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1110c171b552SLi Zefan "event filter", parse_filter), 11114ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 11124ba1faa1SWang Nan NULL, "don't record events from perf itself", 11134ba1faa1SWang Nan exclude_perf), 1114bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1115d6d901c2SZhang, Yanmin "record events on existing process id"), 1116bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1117d6d901c2SZhang, Yanmin "record events on existing thread id"), 1118d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 111986470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1120509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1121acac03faSKirill Smelkov "collect data without buffering"), 1122d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1123daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1124bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 112586470930SIngo Molnar "system-wide collection from all CPUs"), 1126bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1127c45c6ea2SStephane Eranian "list of cpus to monitor"), 1128d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1129f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 113086470930SIngo Molnar "output file name"), 113169e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 113269e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 11332e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1134d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1135e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1136e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1137e9db1310SAdrian Hunter record__parse_mmap_pages), 1138d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 113943bece79SLin Ming "put the counters into a counter group"), 114009b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 114109b0fd45SJiri Olsa NULL, "enables call-graph recording" , 114209b0fd45SJiri Olsa &record_callchain_opt), 114309b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 114476a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 114509b0fd45SJiri Olsa &record_parse_callchain_opt), 1146c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 11473da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1148b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1149d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1150649c48a9SPeter Zijlstra "per thread counts"), 115156100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 11523abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 11533abebc55SAdrian Hunter &record.opts.sample_time_set, 11543abebc55SAdrian Hunter "Record the sample timestamps"), 115556100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1156d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1157649c48a9SPeter Zijlstra "don't sample"), 1158d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1159d2db9a98SWang Nan &record.no_buildid_cache_set, 1160a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1161d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1162d2db9a98SWang Nan &record.no_buildid_set, 1163baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1164d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1165023695d9SStephane Eranian "monitor event in cgroup name only", 1166023695d9SStephane Eranian parse_cgroups), 1167a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 11686619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1169bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1170bea03405SNamhyung Kim "user to profile"), 1171a5aabdacSStephane Eranian 1172a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1173a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1174a5aabdacSStephane Eranian parse_branch_stack), 1175a5aabdacSStephane Eranian 1176a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1177a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1178bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 117905484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 118005484298SAndi Kleen "sample by weight (on special events only)"), 1181475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1182475eeab9SAndi Kleen "sample transaction flags (special events only)"), 11833aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 11843aa5939dSAdrian Hunter "use per-thread mmaps"), 1185bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1186bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1187bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 118885c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 118985c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1190814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1191814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1192814c8c38SPeter Zijlstra parse_clockid), 11932dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 11942dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 11959d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 11969d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1197b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1198b757bb09SAdrian Hunter "Record context switch events"), 119985723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 120085723885SJiri Olsa "Configure all used events to run in kernel space.", 120185723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 120285723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 120385723885SJiri Olsa "Configure all used events to run in user space.", 120485723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 120571dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 120671dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 120771dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 120871dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 12097efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 12107efe0e03SHe Kuang "file", "vmlinux pathname"), 12116156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 12126156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 121386470930SIngo Molnar OPT_END() 121486470930SIngo Molnar }; 121586470930SIngo Molnar 1216e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1217e5b2c207SNamhyung Kim 12181d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 121986470930SIngo Molnar { 1220ef149c25SAdrian Hunter int err; 12218c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 122216ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 122386470930SIngo Molnar 122448e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 122548e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 122648e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 122748e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 122848e1cab1SWang Nan # undef set_nobuild 122948e1cab1SWang Nan #endif 123048e1cab1SWang Nan 12317efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 12327efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 12337efe0e03SHe Kuang # define REASON "NO_DWARF=1" 12347efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 12357efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 12367efe0e03SHe Kuang # else 12377efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 12387efe0e03SHe Kuang # endif 12397efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 12407efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 12417efe0e03SHe Kuang # undef set_nobuild 12427efe0e03SHe Kuang # undef REASON 12437efe0e03SHe Kuang #endif 12447efe0e03SHe Kuang 12453e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 12463e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1247361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1248361c99a6SArnaldo Carvalho de Melo 1249eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1250eb853e80SJiri Olsa 1251bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1252a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1253602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1254bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 125586470930SIngo Molnar 1256bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1257c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1258c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1259c7118369SNamhyung Kim 1260023695d9SStephane Eranian } 1261b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1262b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1263c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1264c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1265c7118369SNamhyung Kim return -EINVAL; 1266b757bb09SAdrian Hunter } 1267023695d9SStephane Eranian 1268ef149c25SAdrian Hunter if (!rec->itr) { 1269ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1270ef149c25SAdrian Hunter if (err) 1271ef149c25SAdrian Hunter return err; 1272ef149c25SAdrian Hunter } 1273ef149c25SAdrian Hunter 12742dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 12752dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 12762dd6d8a1SAdrian Hunter if (err) 12772dd6d8a1SAdrian Hunter return err; 12782dd6d8a1SAdrian Hunter 1279ef149c25SAdrian Hunter err = -ENOMEM; 1280ef149c25SAdrian Hunter 12810a7e6d1bSNamhyung Kim symbol__init(NULL); 1282baa2f6ceSArnaldo Carvalho de Melo 1283ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1284646aaea6SArnaldo Carvalho de Melo pr_warning( 1285646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1286ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1287646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1288646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1289646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1290646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1291646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1292ec80fde7SArnaldo Carvalho de Melo 1293d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1294a1ac1d3cSStephane Eranian disable_buildid_cache(); 1295655000e7SArnaldo Carvalho de Melo 12963e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 12973e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 129869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 129969aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1300bbd36e5eSPeter Zijlstra } 130186470930SIngo Molnar 130269e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 130369e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 130469e7e5b0SAdrian Hunter 1305602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 130616ad2ffbSNamhyung Kim if (err) { 1307602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 130816ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 130916ad2ffbSNamhyung Kim } 13104bd0f2d2SNamhyung Kim 1311602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 131216ad2ffbSNamhyung Kim if (err) { 131316ad2ffbSNamhyung Kim int saved_errno = errno; 131416ad2ffbSNamhyung Kim 1315602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 13163780f488SNamhyung Kim ui__error("%s", errbuf); 131716ad2ffbSNamhyung Kim 131816ad2ffbSNamhyung Kim err = -saved_errno; 13198fa60e1fSNamhyung Kim goto out_symbol_exit; 132016ad2ffbSNamhyung Kim } 13210d37aa34SArnaldo Carvalho de Melo 132216ad2ffbSNamhyung Kim err = -ENOMEM; 13233e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1324dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 132569aad6f1SArnaldo Carvalho de Melo 1326ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1327ef149c25SAdrian Hunter if (err) 1328ef149c25SAdrian Hunter goto out_symbol_exit; 1329ef149c25SAdrian Hunter 13306156681bSNamhyung Kim /* 13316156681bSNamhyung Kim * We take all buildids when the file contains 13326156681bSNamhyung Kim * AUX area tracing data because we do not decode the 13336156681bSNamhyung Kim * trace because it would take too long. 13346156681bSNamhyung Kim */ 13356156681bSNamhyung Kim if (rec->opts.full_auxtrace) 13366156681bSNamhyung Kim rec->buildid_all = true; 13376156681bSNamhyung Kim 1338b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 133939d17dacSArnaldo Carvalho de Melo err = -EINVAL; 134003ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 13417e4ff9e3SMike Galbraith } 13427e4ff9e3SMike Galbraith 1343d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1344d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 134545604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1346d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1347ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 134839d17dacSArnaldo Carvalho de Melo return err; 134986470930SIngo Molnar } 13502dd6d8a1SAdrian Hunter 13512dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 13522dd6d8a1SAdrian Hunter { 13532dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 13542dd6d8a1SAdrian Hunter return; 13552dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 13562dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 13572dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 13582dd6d8a1SAdrian Hunter } 1359