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" 32f00898f4SAndi Kleen #include "util/parse-branch-options.h" 33bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3471dc2326SWang Nan #include "util/llvm-utils.h" 358690a2a7SWang Nan #include "util/bpf-loader.h" 36d8871ea7SWang Nan #include "asm/bug.h" 377c6a1c65SPeter Zijlstra 3886470930SIngo Molnar #include <unistd.h> 3986470930SIngo Molnar #include <sched.h> 40a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 4186470930SIngo Molnar 4278da39faSBernhard Rosenkraenzer 438c6f45a7SArnaldo Carvalho de Melo struct record { 4445694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 45b4006796SArnaldo Carvalho de Melo struct record_opts opts; 46d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 47f5fc1412SJiri Olsa struct perf_data_file file; 48ef149c25SAdrian Hunter struct auxtrace_record *itr; 49d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 50d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 51d20deb64SArnaldo Carvalho de Melo const char *progname; 52d20deb64SArnaldo Carvalho de Melo int realtime_prio; 53d20deb64SArnaldo Carvalho de Melo bool no_buildid; 54d2db9a98SWang Nan bool no_buildid_set; 55d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 56d2db9a98SWang Nan bool no_buildid_cache_set; 576156681bSNamhyung Kim bool buildid_all; 589f065194SYang Shi unsigned long long samples; 590f82ebc4SArnaldo Carvalho de Melo }; 6086470930SIngo Molnar 618c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 62f5970550SPeter Zijlstra { 63cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 644f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 658d3eca20SDavid Ahern return -1; 668d3eca20SDavid Ahern } 67f5970550SPeter Zijlstra 68cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 698d3eca20SDavid Ahern return 0; 70f5970550SPeter Zijlstra } 71f5970550SPeter Zijlstra 7245694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 73d20deb64SArnaldo Carvalho de Melo union perf_event *event, 741d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 751d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 76234fbbf5SArnaldo Carvalho de Melo { 778c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 788c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 79234fbbf5SArnaldo Carvalho de Melo } 80234fbbf5SArnaldo Carvalho de Melo 81e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 8286470930SIngo Molnar { 83e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 847b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 857b8283b5SDavid Ahern u64 old = md->prev; 86918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8786470930SIngo Molnar unsigned long size; 8886470930SIngo Molnar void *buf; 898d3eca20SDavid Ahern int rc = 0; 9086470930SIngo Molnar 91dc82009aSArnaldo Carvalho de Melo if (old == head) 928d3eca20SDavid Ahern return 0; 9386470930SIngo Molnar 94d20deb64SArnaldo Carvalho de Melo rec->samples++; 9586470930SIngo Molnar 9686470930SIngo Molnar size = head - old; 9786470930SIngo Molnar 9886470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9986470930SIngo Molnar buf = &data[old & md->mask]; 10086470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 10186470930SIngo Molnar old += size; 10286470930SIngo Molnar 1038c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1048d3eca20SDavid Ahern rc = -1; 1058d3eca20SDavid Ahern goto out; 1068d3eca20SDavid Ahern } 10786470930SIngo Molnar } 10886470930SIngo Molnar 10986470930SIngo Molnar buf = &data[old & md->mask]; 11086470930SIngo Molnar size = head - old; 11186470930SIngo Molnar old += size; 11286470930SIngo Molnar 1138c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1148d3eca20SDavid Ahern rc = -1; 1158d3eca20SDavid Ahern goto out; 1168d3eca20SDavid Ahern } 11786470930SIngo Molnar 11886470930SIngo Molnar md->prev = old; 119e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1208d3eca20SDavid Ahern out: 1218d3eca20SDavid Ahern return rc; 12286470930SIngo Molnar } 12386470930SIngo Molnar 1242dd6d8a1SAdrian Hunter static volatile int done; 1252dd6d8a1SAdrian Hunter static volatile int signr = -1; 1262dd6d8a1SAdrian Hunter static volatile int child_finished; 1272dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1282dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1292dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1302dd6d8a1SAdrian Hunter 1312dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1322dd6d8a1SAdrian Hunter { 1332dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1342dd6d8a1SAdrian Hunter child_finished = 1; 1352dd6d8a1SAdrian Hunter else 1362dd6d8a1SAdrian Hunter signr = sig; 1372dd6d8a1SAdrian Hunter 1382dd6d8a1SAdrian Hunter done = 1; 1392dd6d8a1SAdrian Hunter } 1402dd6d8a1SAdrian Hunter 1412dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1422dd6d8a1SAdrian Hunter { 1432dd6d8a1SAdrian Hunter if (signr == -1) 1442dd6d8a1SAdrian Hunter return; 1452dd6d8a1SAdrian Hunter 1462dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1472dd6d8a1SAdrian Hunter raise(signr); 1482dd6d8a1SAdrian Hunter } 1492dd6d8a1SAdrian Hunter 150e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 151e31f0d01SAdrian Hunter 152ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 153ef149c25SAdrian Hunter union perf_event *event, void *data1, 154ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 155ef149c25SAdrian Hunter { 156ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 15799fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 158ef149c25SAdrian Hunter size_t padding; 159ef149c25SAdrian Hunter u8 pad[8] = {0}; 160ef149c25SAdrian Hunter 16199fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 16299fa2984SAdrian Hunter off_t file_offset; 16399fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 16499fa2984SAdrian Hunter int err; 16599fa2984SAdrian Hunter 16699fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 16799fa2984SAdrian Hunter if (file_offset == -1) 16899fa2984SAdrian Hunter return -1; 16999fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 17099fa2984SAdrian Hunter event, file_offset); 17199fa2984SAdrian Hunter if (err) 17299fa2984SAdrian Hunter return err; 17399fa2984SAdrian Hunter } 17499fa2984SAdrian Hunter 175ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 176ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 177ef149c25SAdrian Hunter if (padding) 178ef149c25SAdrian Hunter padding = 8 - padding; 179ef149c25SAdrian Hunter 180ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 181ef149c25SAdrian Hunter record__write(rec, data1, len1); 182ef149c25SAdrian Hunter if (len2) 183ef149c25SAdrian Hunter record__write(rec, data2, len2); 184ef149c25SAdrian Hunter record__write(rec, &pad, padding); 185ef149c25SAdrian Hunter 186ef149c25SAdrian Hunter return 0; 187ef149c25SAdrian Hunter } 188ef149c25SAdrian Hunter 189ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 190ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 191ef149c25SAdrian Hunter { 192ef149c25SAdrian Hunter int ret; 193ef149c25SAdrian Hunter 194ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 195ef149c25SAdrian Hunter record__process_auxtrace); 196ef149c25SAdrian Hunter if (ret < 0) 197ef149c25SAdrian Hunter return ret; 198ef149c25SAdrian Hunter 199ef149c25SAdrian Hunter if (ret) 200ef149c25SAdrian Hunter rec->samples++; 201ef149c25SAdrian Hunter 202ef149c25SAdrian Hunter return 0; 203ef149c25SAdrian Hunter } 204ef149c25SAdrian Hunter 2052dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2062dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2072dd6d8a1SAdrian Hunter { 2082dd6d8a1SAdrian Hunter int ret; 2092dd6d8a1SAdrian Hunter 2102dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2112dd6d8a1SAdrian Hunter record__process_auxtrace, 2122dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2132dd6d8a1SAdrian Hunter if (ret < 0) 2142dd6d8a1SAdrian Hunter return ret; 2152dd6d8a1SAdrian Hunter 2162dd6d8a1SAdrian Hunter if (ret) 2172dd6d8a1SAdrian Hunter rec->samples++; 2182dd6d8a1SAdrian Hunter 2192dd6d8a1SAdrian Hunter return 0; 2202dd6d8a1SAdrian Hunter } 2212dd6d8a1SAdrian Hunter 2222dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2232dd6d8a1SAdrian Hunter { 2242dd6d8a1SAdrian Hunter int i; 2252dd6d8a1SAdrian Hunter int rc = 0; 2262dd6d8a1SAdrian Hunter 2272dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2282dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2292dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2302dd6d8a1SAdrian Hunter 2312dd6d8a1SAdrian Hunter if (!mm->base) 2322dd6d8a1SAdrian Hunter continue; 2332dd6d8a1SAdrian Hunter 2342dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2352dd6d8a1SAdrian Hunter rc = -1; 2362dd6d8a1SAdrian Hunter goto out; 2372dd6d8a1SAdrian Hunter } 2382dd6d8a1SAdrian Hunter } 2392dd6d8a1SAdrian Hunter out: 2402dd6d8a1SAdrian Hunter return rc; 2412dd6d8a1SAdrian Hunter } 2422dd6d8a1SAdrian Hunter 2432dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2442dd6d8a1SAdrian Hunter { 2452dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2462dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2472dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2482dd6d8a1SAdrian Hunter } else { 2492dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2502dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2512dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2522dd6d8a1SAdrian Hunter } 2532dd6d8a1SAdrian Hunter } 2542dd6d8a1SAdrian Hunter 255e31f0d01SAdrian Hunter #else 256e31f0d01SAdrian Hunter 257e31f0d01SAdrian Hunter static inline 258e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 259e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 260e31f0d01SAdrian Hunter { 261e31f0d01SAdrian Hunter return 0; 262e31f0d01SAdrian Hunter } 263e31f0d01SAdrian Hunter 2642dd6d8a1SAdrian Hunter static inline 2652dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2662dd6d8a1SAdrian Hunter { 2672dd6d8a1SAdrian Hunter } 2682dd6d8a1SAdrian Hunter 2692dd6d8a1SAdrian Hunter static inline 2702dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2712dd6d8a1SAdrian Hunter { 2722dd6d8a1SAdrian Hunter return 0; 2732dd6d8a1SAdrian Hunter } 2742dd6d8a1SAdrian Hunter 275e31f0d01SAdrian Hunter #endif 276e31f0d01SAdrian Hunter 2778c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 278dd7927f4SArnaldo Carvalho de Melo { 27956e52e85SArnaldo Carvalho de Melo char msg[512]; 2806a4bb04cSJiri Olsa struct perf_evsel *pos; 281d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 282d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 283b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2848d3eca20SDavid Ahern int rc = 0; 285dd7927f4SArnaldo Carvalho de Melo 286f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 287cac21425SJiri Olsa 2880050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2893da297a6SIngo Molnar try_again: 290d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 29156e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2923da297a6SIngo Molnar if (verbose) 293c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2943da297a6SIngo Molnar goto try_again; 2953da297a6SIngo Molnar } 296ca6a4258SDavid Ahern 29756e52e85SArnaldo Carvalho de Melo rc = -errno; 29856e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 29956e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 30056e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3018d3eca20SDavid Ahern goto out; 3027c6a1c65SPeter Zijlstra } 3037c6a1c65SPeter Zijlstra } 3047c6a1c65SPeter Zijlstra 30523d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 30623d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 30723d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30835550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3098d3eca20SDavid Ahern rc = -1; 3108d3eca20SDavid Ahern goto out; 3110a102479SFrederic Weisbecker } 3120a102479SFrederic Weisbecker 313ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3142dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3152dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3168d3eca20SDavid Ahern if (errno == EPERM) { 3178d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31818e60939SNelson Elhage "Consider increasing " 31918e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 32018e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 321ef149c25SAdrian Hunter "(current value: %u,%u)\n", 322ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3238d3eca20SDavid Ahern rc = -errno; 3248d3eca20SDavid Ahern } else { 32535550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 32635550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 327*95c36561SWang Nan if (errno) 3288d3eca20SDavid Ahern rc = -errno; 329*95c36561SWang Nan else 330*95c36561SWang Nan rc = -EINVAL; 3318d3eca20SDavid Ahern } 3328d3eca20SDavid Ahern goto out; 33318e60939SNelson Elhage } 3340a27d7f9SArnaldo Carvalho de Melo 335a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3367b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3378d3eca20SDavid Ahern out: 3388d3eca20SDavid Ahern return rc; 339a91e5431SArnaldo Carvalho de Melo } 340a91e5431SArnaldo Carvalho de Melo 341e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 342e3d59112SNamhyung Kim union perf_event *event, 343e3d59112SNamhyung Kim struct perf_sample *sample, 344e3d59112SNamhyung Kim struct perf_evsel *evsel, 345e3d59112SNamhyung Kim struct machine *machine) 346e3d59112SNamhyung Kim { 347e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 348e3d59112SNamhyung Kim 349e3d59112SNamhyung Kim rec->samples++; 350e3d59112SNamhyung Kim 351e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 352e3d59112SNamhyung Kim } 353e3d59112SNamhyung Kim 3548c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3556122e4e4SArnaldo Carvalho de Melo { 356f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 357f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3586122e4e4SArnaldo Carvalho de Melo 359457ae94aSHe Kuang if (file->size == 0) 3609f591fd7SArnaldo Carvalho de Melo return 0; 3619f591fd7SArnaldo Carvalho de Melo 36200dc8657SNamhyung Kim /* 36300dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 36400dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 36500dc8657SNamhyung Kim * we prefer the vmlinux path like 36600dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 36700dc8657SNamhyung Kim * 36800dc8657SNamhyung Kim * rather than build-id path (in debug directory). 36900dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 37000dc8657SNamhyung Kim */ 37100dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 37200dc8657SNamhyung Kim 3736156681bSNamhyung Kim /* 3746156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 3756156681bSNamhyung Kim * so no need to process samples. 3766156681bSNamhyung Kim */ 3776156681bSNamhyung Kim if (rec->buildid_all) 3786156681bSNamhyung Kim rec->tool.sample = NULL; 3796156681bSNamhyung Kim 380b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3816122e4e4SArnaldo Carvalho de Melo } 3826122e4e4SArnaldo Carvalho de Melo 3838115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 384a1645ce1SZhang, Yanmin { 385a1645ce1SZhang, Yanmin int err; 38645694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 387a1645ce1SZhang, Yanmin /* 388a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 389a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 390a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 391a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 392a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 393a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 394a1645ce1SZhang, Yanmin */ 39545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 396743eb868SArnaldo Carvalho de Melo machine); 397a1645ce1SZhang, Yanmin if (err < 0) 398a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 39923346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 400a1645ce1SZhang, Yanmin 401a1645ce1SZhang, Yanmin /* 402a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 403a1645ce1SZhang, Yanmin * have no _text sometimes. 404a1645ce1SZhang, Yanmin */ 40545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4060ae617beSAdrian Hunter machine); 407a1645ce1SZhang, Yanmin if (err < 0) 408a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 40923346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 410a1645ce1SZhang, Yanmin } 411a1645ce1SZhang, Yanmin 41298402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 41398402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 41498402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 41598402807SFrederic Weisbecker }; 41698402807SFrederic Weisbecker 4178c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 41898402807SFrederic Weisbecker { 419dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4200e2e63ddSPeter Zijlstra int i; 4218d3eca20SDavid Ahern int rc = 0; 42298402807SFrederic Weisbecker 423d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 424ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 425ef149c25SAdrian Hunter 4268d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 427e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4288d3eca20SDavid Ahern rc = -1; 4298d3eca20SDavid Ahern goto out; 4308d3eca20SDavid Ahern } 4318d3eca20SDavid Ahern } 432ef149c25SAdrian Hunter 4332dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 434ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 435ef149c25SAdrian Hunter rc = -1; 436ef149c25SAdrian Hunter goto out; 437ef149c25SAdrian Hunter } 43898402807SFrederic Weisbecker } 43998402807SFrederic Weisbecker 440dcabb507SJiri Olsa /* 441dcabb507SJiri Olsa * Mark the round finished in case we wrote 442dcabb507SJiri Olsa * at least one event. 443dcabb507SJiri Olsa */ 444dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4458c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4468d3eca20SDavid Ahern 4478d3eca20SDavid Ahern out: 4488d3eca20SDavid Ahern return rc; 44998402807SFrederic Weisbecker } 45098402807SFrederic Weisbecker 4518c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 45257706abcSDavid Ahern { 45357706abcSDavid Ahern struct perf_session *session = rec->session; 45457706abcSDavid Ahern int feat; 45557706abcSDavid Ahern 45657706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 45757706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 45857706abcSDavid Ahern 45957706abcSDavid Ahern if (rec->no_buildid) 46057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 46157706abcSDavid Ahern 4623e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 46357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 46457706abcSDavid Ahern 46557706abcSDavid Ahern if (!rec->opts.branch_stack) 46657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 467ef149c25SAdrian Hunter 468ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 469ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 470ffa517adSJiri Olsa 471ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 47257706abcSDavid Ahern } 47357706abcSDavid Ahern 474e1ab48baSWang Nan static void 475e1ab48baSWang Nan record__finish_output(struct record *rec) 476e1ab48baSWang Nan { 477e1ab48baSWang Nan struct perf_data_file *file = &rec->file; 478e1ab48baSWang Nan int fd = perf_data_file__fd(file); 479e1ab48baSWang Nan 480e1ab48baSWang Nan if (file->is_pipe) 481e1ab48baSWang Nan return; 482e1ab48baSWang Nan 483e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 484e1ab48baSWang Nan file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 485e1ab48baSWang Nan 486e1ab48baSWang Nan if (!rec->no_buildid) { 487e1ab48baSWang Nan process_buildids(rec); 488e1ab48baSWang Nan 489e1ab48baSWang Nan if (rec->buildid_all) 490e1ab48baSWang Nan dsos__hit_all(rec->session); 491e1ab48baSWang Nan } 492e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 493e1ab48baSWang Nan 494e1ab48baSWang Nan return; 495e1ab48baSWang Nan } 496e1ab48baSWang Nan 497f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 498f33cbe72SArnaldo Carvalho de Melo 499f33cbe72SArnaldo Carvalho de Melo /* 500f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 501f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 502f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 503f33cbe72SArnaldo Carvalho de Melo */ 50445604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 50545604710SNamhyung Kim siginfo_t *info, 506f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 507f33cbe72SArnaldo Carvalho de Melo { 508f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 509f33cbe72SArnaldo Carvalho de Melo done = 1; 510f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 511f33cbe72SArnaldo Carvalho de Melo } 512f33cbe72SArnaldo Carvalho de Melo 5132dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 5142dd6d8a1SAdrian Hunter 515c45c86ebSWang Nan static int record__synthesize(struct record *rec) 516c45c86ebSWang Nan { 517c45c86ebSWang Nan struct perf_session *session = rec->session; 518c45c86ebSWang Nan struct machine *machine = &session->machines.host; 519c45c86ebSWang Nan struct perf_data_file *file = &rec->file; 520c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 521c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 522c45c86ebSWang Nan int fd = perf_data_file__fd(file); 523c45c86ebSWang Nan int err = 0; 524c45c86ebSWang Nan 525c45c86ebSWang Nan if (file->is_pipe) { 526c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 527c45c86ebSWang Nan process_synthesized_event); 528c45c86ebSWang Nan if (err < 0) { 529c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 530c45c86ebSWang Nan goto out; 531c45c86ebSWang Nan } 532c45c86ebSWang Nan 533c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 534c45c86ebSWang Nan /* 535c45c86ebSWang Nan * FIXME err <= 0 here actually means that 536c45c86ebSWang Nan * there were no tracepoints so its not really 537c45c86ebSWang Nan * an error, just that we don't need to 538c45c86ebSWang Nan * synthesize anything. We really have to 539c45c86ebSWang Nan * return this more properly and also 540c45c86ebSWang Nan * propagate errors that now are calling die() 541c45c86ebSWang Nan */ 542c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 543c45c86ebSWang Nan process_synthesized_event); 544c45c86ebSWang Nan if (err <= 0) { 545c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 546c45c86ebSWang Nan goto out; 547c45c86ebSWang Nan } 548c45c86ebSWang Nan rec->bytes_written += err; 549c45c86ebSWang Nan } 550c45c86ebSWang Nan } 551c45c86ebSWang Nan 552c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 553c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 554c45c86ebSWang Nan session, process_synthesized_event); 555c45c86ebSWang Nan if (err) 556c45c86ebSWang Nan goto out; 557c45c86ebSWang Nan } 558c45c86ebSWang Nan 559c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 560c45c86ebSWang Nan machine); 561c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 562c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 563c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 564c45c86ebSWang Nan 565c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 566c45c86ebSWang Nan machine); 567c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 568c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 569c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 570c45c86ebSWang Nan 571c45c86ebSWang Nan if (perf_guest) { 572c45c86ebSWang Nan machines__process_guests(&session->machines, 573c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 574c45c86ebSWang Nan } 575c45c86ebSWang Nan 576c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 577c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 578c45c86ebSWang Nan opts->proc_map_timeout); 579c45c86ebSWang Nan out: 580c45c86ebSWang Nan return err; 581c45c86ebSWang Nan } 582c45c86ebSWang Nan 5838c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 58486470930SIngo Molnar { 58557706abcSDavid Ahern int err; 58645604710SNamhyung Kim int status = 0; 5878b412664SPeter Zijlstra unsigned long waking = 0; 58846be604bSZhang, Yanmin const bool forks = argc > 0; 58923346f21SArnaldo Carvalho de Melo struct machine *machine; 59045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 591b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 592f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 593d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 5946dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 59542aa276fSNamhyung Kim int fd; 59686470930SIngo Molnar 597d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 59833e49ea7SAndi Kleen 59945604710SNamhyung Kim atexit(record__sig_exit); 600f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 601f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 602804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 6032dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 6042dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 6052dd6d8a1SAdrian Hunter else 6062dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 607f5970550SPeter Zijlstra 608b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 60994c744b6SArnaldo Carvalho de Melo if (session == NULL) { 610ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 611a9a70bbcSArnaldo Carvalho de Melo return -1; 612a9a70bbcSArnaldo Carvalho de Melo } 613a9a70bbcSArnaldo Carvalho de Melo 61442aa276fSNamhyung Kim fd = perf_data_file__fd(file); 615d20deb64SArnaldo Carvalho de Melo rec->session = session; 616d20deb64SArnaldo Carvalho de Melo 6178c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 618330aa675SStephane Eranian 619d4db3f16SArnaldo Carvalho de Melo if (forks) { 6203e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 621f5fc1412SJiri Olsa argv, file->is_pipe, 622735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 62335b9d88eSArnaldo Carvalho de Melo if (err < 0) { 62435b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 62545604710SNamhyung Kim status = err; 62635b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 627856e9660SPeter Zijlstra } 628856e9660SPeter Zijlstra } 629856e9660SPeter Zijlstra 6308c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 6318d3eca20SDavid Ahern err = -1; 63245604710SNamhyung Kim goto out_child; 6338d3eca20SDavid Ahern } 63486470930SIngo Molnar 6358690a2a7SWang Nan err = bpf__apply_obj_config(); 6368690a2a7SWang Nan if (err) { 6378690a2a7SWang Nan char errbuf[BUFSIZ]; 6388690a2a7SWang Nan 6398690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 6408690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 6418690a2a7SWang Nan errbuf); 6428690a2a7SWang Nan goto out_child; 6438690a2a7SWang Nan } 6448690a2a7SWang Nan 645cca8482cSAdrian Hunter /* 646cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 647cca8482cSAdrian Hunter * evlist. 648cca8482cSAdrian Hunter */ 649cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 650cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 651cca8482cSAdrian Hunter rec->tool.ordered_events = false; 652cca8482cSAdrian Hunter } 653cca8482cSAdrian Hunter 6543e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 655a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 656a8bb559bSNamhyung Kim 657f5fc1412SJiri Olsa if (file->is_pipe) { 65842aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 659529870e3STom Zanussi if (err < 0) 66045604710SNamhyung Kim goto out_child; 661563aecb2SJiri Olsa } else { 66242aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 663d5eed904SArnaldo Carvalho de Melo if (err < 0) 66445604710SNamhyung Kim goto out_child; 665d5eed904SArnaldo Carvalho de Melo } 6667c6a1c65SPeter Zijlstra 667d3665498SDavid Ahern if (!rec->no_buildid 668e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 669d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 670e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 6718d3eca20SDavid Ahern err = -1; 67245604710SNamhyung Kim goto out_child; 673e20960c0SRobert Richter } 674e20960c0SRobert Richter 67534ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 676743eb868SArnaldo Carvalho de Melo 677c45c86ebSWang Nan err = record__synthesize(rec); 678c45c86ebSWang Nan if (err < 0) 67945604710SNamhyung Kim goto out_child; 6808d3eca20SDavid Ahern 681d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 68286470930SIngo Molnar struct sched_param param; 68386470930SIngo Molnar 684d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 68586470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6866beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6878d3eca20SDavid Ahern err = -1; 68845604710SNamhyung Kim goto out_child; 68986470930SIngo Molnar } 69086470930SIngo Molnar } 69186470930SIngo Molnar 692774cb499SJiri Olsa /* 693774cb499SJiri Olsa * When perf is starting the traced process, all the events 694774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 695774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 696774cb499SJiri Olsa */ 6976619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 6983e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 699764e16a3SDavid Ahern 700856e9660SPeter Zijlstra /* 701856e9660SPeter Zijlstra * Let the child rip 702856e9660SPeter Zijlstra */ 703e803cf97SNamhyung Kim if (forks) { 704e5bed564SNamhyung Kim union perf_event *event; 705e5bed564SNamhyung Kim 706e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 707e5bed564SNamhyung Kim if (event == NULL) { 708e5bed564SNamhyung Kim err = -ENOMEM; 709e5bed564SNamhyung Kim goto out_child; 710e5bed564SNamhyung Kim } 711e5bed564SNamhyung Kim 712e803cf97SNamhyung Kim /* 713e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 714e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 715e803cf97SNamhyung Kim * cannot see a correct process name for those events. 716e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 717e803cf97SNamhyung Kim */ 718e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 719e803cf97SNamhyung Kim rec->evlist->workload.pid, 720e803cf97SNamhyung Kim process_synthesized_event, 721e803cf97SNamhyung Kim machine); 722e5bed564SNamhyung Kim free(event); 723e803cf97SNamhyung Kim 7243e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 725e803cf97SNamhyung Kim } 726856e9660SPeter Zijlstra 7276619a53eSAndi Kleen if (opts->initial_delay) { 7286619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 7296619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 7306619a53eSAndi Kleen } 7316619a53eSAndi Kleen 7322dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 733649c48a9SPeter Zijlstra for (;;) { 7349f065194SYang Shi unsigned long long hits = rec->samples; 73586470930SIngo Molnar 7368c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 7372dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7388d3eca20SDavid Ahern err = -1; 73945604710SNamhyung Kim goto out_child; 7408d3eca20SDavid Ahern } 74186470930SIngo Molnar 7422dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 7432dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 7442dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 7452dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 7462dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 7472dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 7482dd6d8a1SAdrian Hunter err = -1; 7492dd6d8a1SAdrian Hunter goto out_child; 7502dd6d8a1SAdrian Hunter } 7512dd6d8a1SAdrian Hunter } 7522dd6d8a1SAdrian Hunter 753d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 7546dcf45efSArnaldo Carvalho de Melo if (done || draining) 755649c48a9SPeter Zijlstra break; 756f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 757a515114fSJiri Olsa /* 758a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 759a515114fSJiri Olsa * number of returned events and interrupt error. 760a515114fSJiri Olsa */ 761a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 76245604710SNamhyung Kim err = 0; 7638b412664SPeter Zijlstra waking++; 7646dcf45efSArnaldo Carvalho de Melo 7656dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 7666dcf45efSArnaldo Carvalho de Melo draining = true; 7678b412664SPeter Zijlstra } 7688b412664SPeter Zijlstra 769774cb499SJiri Olsa /* 770774cb499SJiri Olsa * When perf is starting the traced process, at the end events 771774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 772774cb499SJiri Olsa * disable events in this case. 773774cb499SJiri Olsa */ 774602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 7752dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7763e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 7772711926aSJiri Olsa disabled = true; 7782711926aSJiri Olsa } 7798b412664SPeter Zijlstra } 7802dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7818b412664SPeter Zijlstra 782f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 78335550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 784f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 785f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 786f33cbe72SArnaldo Carvalho de Melo err = -1; 78745604710SNamhyung Kim goto out_child; 788f33cbe72SArnaldo Carvalho de Melo } 789f33cbe72SArnaldo Carvalho de Melo 790e3d59112SNamhyung Kim if (!quiet) 7918b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 79286470930SIngo Molnar 79345604710SNamhyung Kim out_child: 79445604710SNamhyung Kim if (forks) { 79545604710SNamhyung Kim int exit_status; 79645604710SNamhyung Kim 79745604710SNamhyung Kim if (!child_finished) 79845604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 79945604710SNamhyung Kim 80045604710SNamhyung Kim wait(&exit_status); 80145604710SNamhyung Kim 80245604710SNamhyung Kim if (err < 0) 80345604710SNamhyung Kim status = err; 80445604710SNamhyung Kim else if (WIFEXITED(exit_status)) 80545604710SNamhyung Kim status = WEXITSTATUS(exit_status); 80645604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 80745604710SNamhyung Kim signr = WTERMSIG(exit_status); 80845604710SNamhyung Kim } else 80945604710SNamhyung Kim status = err; 81045604710SNamhyung Kim 811e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 812e3d59112SNamhyung Kim rec->samples = 0; 813e3d59112SNamhyung Kim 814e1ab48baSWang Nan if (!err) 815e1ab48baSWang Nan record__finish_output(rec); 81639d17dacSArnaldo Carvalho de Melo 817e3d59112SNamhyung Kim if (!err && !quiet) { 818e3d59112SNamhyung Kim char samples[128]; 819e3d59112SNamhyung Kim 820ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 821e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 822e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 823e3d59112SNamhyung Kim else 824e3d59112SNamhyung Kim samples[0] = '\0'; 825e3d59112SNamhyung Kim 826e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 827e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 828e3d59112SNamhyung Kim file->path, samples); 829e3d59112SNamhyung Kim } 830e3d59112SNamhyung Kim 83139d17dacSArnaldo Carvalho de Melo out_delete_session: 83239d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 83345604710SNamhyung Kim return status; 83486470930SIngo Molnar } 83586470930SIngo Molnar 83672a128aaSNamhyung Kim static void callchain_debug(void) 83709b0fd45SJiri Olsa { 838aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 839a601fdffSJiri Olsa 84072a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 84126d33022SJiri Olsa 84272a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 84309b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 84472a128aaSNamhyung Kim callchain_param.dump_size); 84509b0fd45SJiri Olsa } 84609b0fd45SJiri Olsa 847c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 84809b0fd45SJiri Olsa const char *arg, 84909b0fd45SJiri Olsa int unset) 85009b0fd45SJiri Olsa { 85109b0fd45SJiri Olsa int ret; 852c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 85309b0fd45SJiri Olsa 854c421e80bSKan Liang record->callgraph_set = true; 85572a128aaSNamhyung Kim callchain_param.enabled = !unset; 856eb853e80SJiri Olsa 85709b0fd45SJiri Olsa /* --no-call-graph */ 85809b0fd45SJiri Olsa if (unset) { 85972a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 86009b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 86109b0fd45SJiri Olsa return 0; 86209b0fd45SJiri Olsa } 86309b0fd45SJiri Olsa 864c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 8655c0cf224SJiri Olsa if (!ret) { 8665c0cf224SJiri Olsa /* Enable data address sampling for DWARF unwind. */ 8675c0cf224SJiri Olsa if (callchain_param.record_mode == CALLCHAIN_DWARF) 8685c0cf224SJiri Olsa record->sample_address = true; 86972a128aaSNamhyung Kim callchain_debug(); 8705c0cf224SJiri Olsa } 87109b0fd45SJiri Olsa 87226d33022SJiri Olsa return ret; 87326d33022SJiri Olsa } 87426d33022SJiri Olsa 875c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 87609b0fd45SJiri Olsa const char *arg __maybe_unused, 87709b0fd45SJiri Olsa int unset __maybe_unused) 87809b0fd45SJiri Olsa { 879c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 880c421e80bSKan Liang 881c421e80bSKan Liang record->callgraph_set = true; 88272a128aaSNamhyung Kim callchain_param.enabled = true; 88309b0fd45SJiri Olsa 88472a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 88572a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 886eb853e80SJiri Olsa 88772a128aaSNamhyung Kim callchain_debug(); 88809b0fd45SJiri Olsa return 0; 88909b0fd45SJiri Olsa } 89009b0fd45SJiri Olsa 891eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 892eb853e80SJiri Olsa { 8937a29c087SNamhyung Kim struct record *rec = cb; 8947a29c087SNamhyung Kim 8957a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 8967a29c087SNamhyung Kim if (!strcmp(value, "cache")) 8977a29c087SNamhyung Kim rec->no_buildid_cache = false; 8987a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 8997a29c087SNamhyung Kim rec->no_buildid_cache = true; 9007a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 9017a29c087SNamhyung Kim rec->no_buildid = true; 9027a29c087SNamhyung Kim else 9037a29c087SNamhyung Kim return -1; 9047a29c087SNamhyung Kim return 0; 9057a29c087SNamhyung Kim } 906eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 9075a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 908eb853e80SJiri Olsa 909eb853e80SJiri Olsa return perf_default_config(var, value, cb); 910eb853e80SJiri Olsa } 911eb853e80SJiri Olsa 912814c8c38SPeter Zijlstra struct clockid_map { 913814c8c38SPeter Zijlstra const char *name; 914814c8c38SPeter Zijlstra int clockid; 915814c8c38SPeter Zijlstra }; 916814c8c38SPeter Zijlstra 917814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 918814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 919814c8c38SPeter Zijlstra 920814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 921814c8c38SPeter Zijlstra 922814c8c38SPeter Zijlstra 923814c8c38SPeter Zijlstra /* 924814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 925814c8c38SPeter Zijlstra */ 926814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 927814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 928814c8c38SPeter Zijlstra #endif 929814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 930814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 931814c8c38SPeter Zijlstra #endif 932814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 933814c8c38SPeter Zijlstra #define CLOCK_TAI 11 934814c8c38SPeter Zijlstra #endif 935814c8c38SPeter Zijlstra 936814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 937814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 938814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 939814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 940814c8c38SPeter Zijlstra 941814c8c38SPeter Zijlstra /* available for some events */ 942814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 943814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 944814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 945814c8c38SPeter Zijlstra 946814c8c38SPeter Zijlstra /* available for the lazy */ 947814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 948814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 949814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 950814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 951814c8c38SPeter Zijlstra 952814c8c38SPeter Zijlstra CLOCKID_END, 953814c8c38SPeter Zijlstra }; 954814c8c38SPeter Zijlstra 955814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 956814c8c38SPeter Zijlstra { 957814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 958814c8c38SPeter Zijlstra const struct clockid_map *cm; 959814c8c38SPeter Zijlstra const char *ostr = str; 960814c8c38SPeter Zijlstra 961814c8c38SPeter Zijlstra if (unset) { 962814c8c38SPeter Zijlstra opts->use_clockid = 0; 963814c8c38SPeter Zijlstra return 0; 964814c8c38SPeter Zijlstra } 965814c8c38SPeter Zijlstra 966814c8c38SPeter Zijlstra /* no arg passed */ 967814c8c38SPeter Zijlstra if (!str) 968814c8c38SPeter Zijlstra return 0; 969814c8c38SPeter Zijlstra 970814c8c38SPeter Zijlstra /* no setting it twice */ 971814c8c38SPeter Zijlstra if (opts->use_clockid) 972814c8c38SPeter Zijlstra return -1; 973814c8c38SPeter Zijlstra 974814c8c38SPeter Zijlstra opts->use_clockid = true; 975814c8c38SPeter Zijlstra 976814c8c38SPeter Zijlstra /* if its a number, we're done */ 977814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 978814c8c38SPeter Zijlstra return 0; 979814c8c38SPeter Zijlstra 980814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 981814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 982814c8c38SPeter Zijlstra str += 6; 983814c8c38SPeter Zijlstra 984814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 985814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 986814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 987814c8c38SPeter Zijlstra return 0; 988814c8c38SPeter Zijlstra } 989814c8c38SPeter Zijlstra } 990814c8c38SPeter Zijlstra 991814c8c38SPeter Zijlstra opts->use_clockid = false; 992814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 993814c8c38SPeter Zijlstra return -1; 994814c8c38SPeter Zijlstra } 995814c8c38SPeter Zijlstra 996e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 997e9db1310SAdrian Hunter const char *str, 998e9db1310SAdrian Hunter int unset __maybe_unused) 999e9db1310SAdrian Hunter { 1000e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1001e9db1310SAdrian Hunter char *s, *p; 1002e9db1310SAdrian Hunter unsigned int mmap_pages; 1003e9db1310SAdrian Hunter int ret; 1004e9db1310SAdrian Hunter 1005e9db1310SAdrian Hunter if (!str) 1006e9db1310SAdrian Hunter return -EINVAL; 1007e9db1310SAdrian Hunter 1008e9db1310SAdrian Hunter s = strdup(str); 1009e9db1310SAdrian Hunter if (!s) 1010e9db1310SAdrian Hunter return -ENOMEM; 1011e9db1310SAdrian Hunter 1012e9db1310SAdrian Hunter p = strchr(s, ','); 1013e9db1310SAdrian Hunter if (p) 1014e9db1310SAdrian Hunter *p = '\0'; 1015e9db1310SAdrian Hunter 1016e9db1310SAdrian Hunter if (*s) { 1017e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1018e9db1310SAdrian Hunter if (ret) 1019e9db1310SAdrian Hunter goto out_free; 1020e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1021e9db1310SAdrian Hunter } 1022e9db1310SAdrian Hunter 1023e9db1310SAdrian Hunter if (!p) { 1024e9db1310SAdrian Hunter ret = 0; 1025e9db1310SAdrian Hunter goto out_free; 1026e9db1310SAdrian Hunter } 1027e9db1310SAdrian Hunter 1028e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1029e9db1310SAdrian Hunter if (ret) 1030e9db1310SAdrian Hunter goto out_free; 1031e9db1310SAdrian Hunter 1032e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1033e9db1310SAdrian Hunter 1034e9db1310SAdrian Hunter out_free: 1035e9db1310SAdrian Hunter free(s); 1036e9db1310SAdrian Hunter return ret; 1037e9db1310SAdrian Hunter } 1038e9db1310SAdrian Hunter 1039e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 104086470930SIngo Molnar "perf record [<options>] [<command>]", 104186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 104286470930SIngo Molnar NULL 104386470930SIngo Molnar }; 1044e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 104586470930SIngo Molnar 1046d20deb64SArnaldo Carvalho de Melo /* 10478c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 10488c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1049d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1050d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1051d20deb64SArnaldo Carvalho de Melo * 1052d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1053d20deb64SArnaldo Carvalho de Melo * 1054d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1055d20deb64SArnaldo Carvalho de Melo */ 10568c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1057d20deb64SArnaldo Carvalho de Melo .opts = { 10588affc2b8SAndi Kleen .sample_time = true, 1059d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1060d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1061d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1062447a6013SArnaldo Carvalho de Melo .freq = 4000, 1063d1cb9fceSNamhyung Kim .target = { 1064d1cb9fceSNamhyung Kim .uses_mmap = true, 10653aa5939dSAdrian Hunter .default_per_cpu = true, 1066d1cb9fceSNamhyung Kim }, 10679d9cad76SKan Liang .proc_map_timeout = 500, 1068d20deb64SArnaldo Carvalho de Melo }, 1069e3d59112SNamhyung Kim .tool = { 1070e3d59112SNamhyung Kim .sample = process_sample_event, 1071e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1072cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1073e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1074e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1075e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1076cca8482cSAdrian Hunter .ordered_events = true, 1077e3d59112SNamhyung Kim }, 1078d20deb64SArnaldo Carvalho de Melo }; 10797865e817SFrederic Weisbecker 108076a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 108176a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 108261eaa3beSArnaldo Carvalho de Melo 1083d20deb64SArnaldo Carvalho de Melo /* 1084d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1085d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1086b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1087d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1088d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1089d20deb64SArnaldo Carvalho de Melo */ 1090e5b2c207SNamhyung Kim struct option __record_options[] = { 1091d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 109286470930SIngo Molnar "event selector. use 'perf list' to list available events", 1093f120f9d5SJiri Olsa parse_events_option), 1094d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1095c171b552SLi Zefan "event filter", parse_filter), 10964ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 10974ba1faa1SWang Nan NULL, "don't record events from perf itself", 10984ba1faa1SWang Nan exclude_perf), 1099bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1100d6d901c2SZhang, Yanmin "record events on existing process id"), 1101bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1102d6d901c2SZhang, Yanmin "record events on existing thread id"), 1103d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 110486470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1105509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1106acac03faSKirill Smelkov "collect data without buffering"), 1107d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1108daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1109bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 111086470930SIngo Molnar "system-wide collection from all CPUs"), 1111bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1112c45c6ea2SStephane Eranian "list of cpus to monitor"), 1113d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1114f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 111586470930SIngo Molnar "output file name"), 111669e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 111769e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 11182e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1119d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1120e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1121e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1122e9db1310SAdrian Hunter record__parse_mmap_pages), 1123d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 112443bece79SLin Ming "put the counters into a counter group"), 112509b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 112609b0fd45SJiri Olsa NULL, "enables call-graph recording" , 112709b0fd45SJiri Olsa &record_callchain_opt), 112809b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 112976a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 113009b0fd45SJiri Olsa &record_parse_callchain_opt), 1131c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 11323da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1133b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1134d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1135649c48a9SPeter Zijlstra "per thread counts"), 113656100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 11373abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 11383abebc55SAdrian Hunter &record.opts.sample_time_set, 11393abebc55SAdrian Hunter "Record the sample timestamps"), 114056100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1141d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1142649c48a9SPeter Zijlstra "don't sample"), 1143d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1144d2db9a98SWang Nan &record.no_buildid_cache_set, 1145a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1146d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1147d2db9a98SWang Nan &record.no_buildid_set, 1148baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1149d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1150023695d9SStephane Eranian "monitor event in cgroup name only", 1151023695d9SStephane Eranian parse_cgroups), 1152a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 11536619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1154bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1155bea03405SNamhyung Kim "user to profile"), 1156a5aabdacSStephane Eranian 1157a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1158a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1159a5aabdacSStephane Eranian parse_branch_stack), 1160a5aabdacSStephane Eranian 1161a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1162a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1163bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 116405484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 116505484298SAndi Kleen "sample by weight (on special events only)"), 1166475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1167475eeab9SAndi Kleen "sample transaction flags (special events only)"), 11683aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 11693aa5939dSAdrian Hunter "use per-thread mmaps"), 1170bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1171bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1172bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 117385c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 117485c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1175814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1176814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1177814c8c38SPeter Zijlstra parse_clockid), 11782dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 11792dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 11809d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 11819d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1182b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1183b757bb09SAdrian Hunter "Record context switch events"), 118485723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 118585723885SJiri Olsa "Configure all used events to run in kernel space.", 118685723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 118785723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 118885723885SJiri Olsa "Configure all used events to run in user space.", 118985723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 119071dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 119171dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 119271dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 119371dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 11947efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 11957efe0e03SHe Kuang "file", "vmlinux pathname"), 11966156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 11976156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 119886470930SIngo Molnar OPT_END() 119986470930SIngo Molnar }; 120086470930SIngo Molnar 1201e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1202e5b2c207SNamhyung Kim 12031d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 120486470930SIngo Molnar { 1205ef149c25SAdrian Hunter int err; 12068c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 120716ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 120886470930SIngo Molnar 120948e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 121048e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 121148e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 121248e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 121348e1cab1SWang Nan # undef set_nobuild 121448e1cab1SWang Nan #endif 121548e1cab1SWang Nan 12167efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 12177efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 12187efe0e03SHe Kuang # define REASON "NO_DWARF=1" 12197efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 12207efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 12217efe0e03SHe Kuang # else 12227efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 12237efe0e03SHe Kuang # endif 12247efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 12257efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 12267efe0e03SHe Kuang # undef set_nobuild 12277efe0e03SHe Kuang # undef REASON 12287efe0e03SHe Kuang #endif 12297efe0e03SHe Kuang 12303e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 12313e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1232361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1233361c99a6SArnaldo Carvalho de Melo 1234eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1235eb853e80SJiri Olsa 1236bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1237a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1238602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1239bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 124086470930SIngo Molnar 1241bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1242c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1243c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1244c7118369SNamhyung Kim 1245023695d9SStephane Eranian } 1246b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1247b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1248c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1249c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1250c7118369SNamhyung Kim return -EINVAL; 1251b757bb09SAdrian Hunter } 1252023695d9SStephane Eranian 1253ef149c25SAdrian Hunter if (!rec->itr) { 1254ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1255ef149c25SAdrian Hunter if (err) 1256ef149c25SAdrian Hunter return err; 1257ef149c25SAdrian Hunter } 1258ef149c25SAdrian Hunter 12592dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 12602dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 12612dd6d8a1SAdrian Hunter if (err) 12622dd6d8a1SAdrian Hunter return err; 12632dd6d8a1SAdrian Hunter 1264ef149c25SAdrian Hunter err = -ENOMEM; 1265ef149c25SAdrian Hunter 12660a7e6d1bSNamhyung Kim symbol__init(NULL); 1267baa2f6ceSArnaldo Carvalho de Melo 1268ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1269646aaea6SArnaldo Carvalho de Melo pr_warning( 1270646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1271ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1272646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1273646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1274646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1275646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1276646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1277ec80fde7SArnaldo Carvalho de Melo 1278d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1279a1ac1d3cSStephane Eranian disable_buildid_cache(); 1280655000e7SArnaldo Carvalho de Melo 12813e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 12823e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 128369aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 128469aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1285bbd36e5eSPeter Zijlstra } 128686470930SIngo Molnar 128769e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 128869e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 128969e7e5b0SAdrian Hunter 1290602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 129116ad2ffbSNamhyung Kim if (err) { 1292602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 129316ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 129416ad2ffbSNamhyung Kim } 12954bd0f2d2SNamhyung Kim 1296602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 129716ad2ffbSNamhyung Kim if (err) { 129816ad2ffbSNamhyung Kim int saved_errno = errno; 129916ad2ffbSNamhyung Kim 1300602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 13013780f488SNamhyung Kim ui__error("%s", errbuf); 130216ad2ffbSNamhyung Kim 130316ad2ffbSNamhyung Kim err = -saved_errno; 13048fa60e1fSNamhyung Kim goto out_symbol_exit; 130516ad2ffbSNamhyung Kim } 13060d37aa34SArnaldo Carvalho de Melo 130716ad2ffbSNamhyung Kim err = -ENOMEM; 13083e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1309dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 131069aad6f1SArnaldo Carvalho de Melo 1311ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1312ef149c25SAdrian Hunter if (err) 1313ef149c25SAdrian Hunter goto out_symbol_exit; 1314ef149c25SAdrian Hunter 13156156681bSNamhyung Kim /* 13166156681bSNamhyung Kim * We take all buildids when the file contains 13176156681bSNamhyung Kim * AUX area tracing data because we do not decode the 13186156681bSNamhyung Kim * trace because it would take too long. 13196156681bSNamhyung Kim */ 13206156681bSNamhyung Kim if (rec->opts.full_auxtrace) 13216156681bSNamhyung Kim rec->buildid_all = true; 13226156681bSNamhyung Kim 1323b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 132439d17dacSArnaldo Carvalho de Melo err = -EINVAL; 132503ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 13267e4ff9e3SMike Galbraith } 13277e4ff9e3SMike Galbraith 1328d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1329d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 133045604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1331d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1332ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 133339d17dacSArnaldo Carvalho de Melo return err; 133486470930SIngo Molnar } 13352dd6d8a1SAdrian Hunter 13362dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 13372dd6d8a1SAdrian Hunter { 13382dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 13392dd6d8a1SAdrian Hunter return; 13402dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 13412dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 13422dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 13432dd6d8a1SAdrian Hunter } 1344