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" 1486470930SIngo Molnar #include "util/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" 357c6a1c65SPeter Zijlstra 3686470930SIngo Molnar #include <unistd.h> 3786470930SIngo Molnar #include <sched.h> 38a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3986470930SIngo Molnar 4078da39faSBernhard Rosenkraenzer 418c6f45a7SArnaldo Carvalho de Melo struct record { 4245694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 43b4006796SArnaldo Carvalho de Melo struct record_opts opts; 44d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 45f5fc1412SJiri Olsa struct perf_data_file file; 46ef149c25SAdrian Hunter struct auxtrace_record *itr; 47d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 48d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 49d20deb64SArnaldo Carvalho de Melo const char *progname; 50d20deb64SArnaldo Carvalho de Melo int realtime_prio; 51d20deb64SArnaldo Carvalho de Melo bool no_buildid; 52d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 539f065194SYang Shi unsigned long long samples; 540f82ebc4SArnaldo Carvalho de Melo }; 5586470930SIngo Molnar 568c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 57f5970550SPeter Zijlstra { 58cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 594f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 608d3eca20SDavid Ahern return -1; 618d3eca20SDavid Ahern } 62f5970550SPeter Zijlstra 63cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 648d3eca20SDavid Ahern return 0; 65f5970550SPeter Zijlstra } 66f5970550SPeter Zijlstra 6745694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 68d20deb64SArnaldo Carvalho de Melo union perf_event *event, 691d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 701d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 71234fbbf5SArnaldo Carvalho de Melo { 728c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 738c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 74234fbbf5SArnaldo Carvalho de Melo } 75234fbbf5SArnaldo Carvalho de Melo 76e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 7786470930SIngo Molnar { 78e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 797b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 807b8283b5SDavid Ahern u64 old = md->prev; 81918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8286470930SIngo Molnar unsigned long size; 8386470930SIngo Molnar void *buf; 848d3eca20SDavid Ahern int rc = 0; 8586470930SIngo Molnar 86dc82009aSArnaldo Carvalho de Melo if (old == head) 878d3eca20SDavid Ahern return 0; 8886470930SIngo Molnar 89d20deb64SArnaldo Carvalho de Melo rec->samples++; 9086470930SIngo Molnar 9186470930SIngo Molnar size = head - old; 9286470930SIngo Molnar 9386470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9486470930SIngo Molnar buf = &data[old & md->mask]; 9586470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 9686470930SIngo Molnar old += size; 9786470930SIngo Molnar 988c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 998d3eca20SDavid Ahern rc = -1; 1008d3eca20SDavid Ahern goto out; 1018d3eca20SDavid Ahern } 10286470930SIngo Molnar } 10386470930SIngo Molnar 10486470930SIngo Molnar buf = &data[old & md->mask]; 10586470930SIngo Molnar size = head - old; 10686470930SIngo Molnar old += size; 10786470930SIngo Molnar 1088c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1098d3eca20SDavid Ahern rc = -1; 1108d3eca20SDavid Ahern goto out; 1118d3eca20SDavid Ahern } 11286470930SIngo Molnar 11386470930SIngo Molnar md->prev = old; 114e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1158d3eca20SDavid Ahern out: 1168d3eca20SDavid Ahern return rc; 11786470930SIngo Molnar } 11886470930SIngo Molnar 1192dd6d8a1SAdrian Hunter static volatile int done; 1202dd6d8a1SAdrian Hunter static volatile int signr = -1; 1212dd6d8a1SAdrian Hunter static volatile int child_finished; 1222dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1232dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1242dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1252dd6d8a1SAdrian Hunter 1262dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1272dd6d8a1SAdrian Hunter { 1282dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1292dd6d8a1SAdrian Hunter child_finished = 1; 1302dd6d8a1SAdrian Hunter else 1312dd6d8a1SAdrian Hunter signr = sig; 1322dd6d8a1SAdrian Hunter 1332dd6d8a1SAdrian Hunter done = 1; 1342dd6d8a1SAdrian Hunter } 1352dd6d8a1SAdrian Hunter 1362dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1372dd6d8a1SAdrian Hunter { 1382dd6d8a1SAdrian Hunter if (signr == -1) 1392dd6d8a1SAdrian Hunter return; 1402dd6d8a1SAdrian Hunter 1412dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1422dd6d8a1SAdrian Hunter raise(signr); 1432dd6d8a1SAdrian Hunter } 1442dd6d8a1SAdrian Hunter 145e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 146e31f0d01SAdrian Hunter 147ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 148ef149c25SAdrian Hunter union perf_event *event, void *data1, 149ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 150ef149c25SAdrian Hunter { 151ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 15299fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 153ef149c25SAdrian Hunter size_t padding; 154ef149c25SAdrian Hunter u8 pad[8] = {0}; 155ef149c25SAdrian Hunter 15699fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 15799fa2984SAdrian Hunter off_t file_offset; 15899fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 15999fa2984SAdrian Hunter int err; 16099fa2984SAdrian Hunter 16199fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 16299fa2984SAdrian Hunter if (file_offset == -1) 16399fa2984SAdrian Hunter return -1; 16499fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 16599fa2984SAdrian Hunter event, file_offset); 16699fa2984SAdrian Hunter if (err) 16799fa2984SAdrian Hunter return err; 16899fa2984SAdrian Hunter } 16999fa2984SAdrian Hunter 170ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 171ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 172ef149c25SAdrian Hunter if (padding) 173ef149c25SAdrian Hunter padding = 8 - padding; 174ef149c25SAdrian Hunter 175ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 176ef149c25SAdrian Hunter record__write(rec, data1, len1); 177ef149c25SAdrian Hunter if (len2) 178ef149c25SAdrian Hunter record__write(rec, data2, len2); 179ef149c25SAdrian Hunter record__write(rec, &pad, padding); 180ef149c25SAdrian Hunter 181ef149c25SAdrian Hunter return 0; 182ef149c25SAdrian Hunter } 183ef149c25SAdrian Hunter 184ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 185ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 186ef149c25SAdrian Hunter { 187ef149c25SAdrian Hunter int ret; 188ef149c25SAdrian Hunter 189ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 190ef149c25SAdrian Hunter record__process_auxtrace); 191ef149c25SAdrian Hunter if (ret < 0) 192ef149c25SAdrian Hunter return ret; 193ef149c25SAdrian Hunter 194ef149c25SAdrian Hunter if (ret) 195ef149c25SAdrian Hunter rec->samples++; 196ef149c25SAdrian Hunter 197ef149c25SAdrian Hunter return 0; 198ef149c25SAdrian Hunter } 199ef149c25SAdrian Hunter 2002dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2012dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2022dd6d8a1SAdrian Hunter { 2032dd6d8a1SAdrian Hunter int ret; 2042dd6d8a1SAdrian Hunter 2052dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2062dd6d8a1SAdrian Hunter record__process_auxtrace, 2072dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2082dd6d8a1SAdrian Hunter if (ret < 0) 2092dd6d8a1SAdrian Hunter return ret; 2102dd6d8a1SAdrian Hunter 2112dd6d8a1SAdrian Hunter if (ret) 2122dd6d8a1SAdrian Hunter rec->samples++; 2132dd6d8a1SAdrian Hunter 2142dd6d8a1SAdrian Hunter return 0; 2152dd6d8a1SAdrian Hunter } 2162dd6d8a1SAdrian Hunter 2172dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2182dd6d8a1SAdrian Hunter { 2192dd6d8a1SAdrian Hunter int i; 2202dd6d8a1SAdrian Hunter int rc = 0; 2212dd6d8a1SAdrian Hunter 2222dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2232dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2242dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2252dd6d8a1SAdrian Hunter 2262dd6d8a1SAdrian Hunter if (!mm->base) 2272dd6d8a1SAdrian Hunter continue; 2282dd6d8a1SAdrian Hunter 2292dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2302dd6d8a1SAdrian Hunter rc = -1; 2312dd6d8a1SAdrian Hunter goto out; 2322dd6d8a1SAdrian Hunter } 2332dd6d8a1SAdrian Hunter } 2342dd6d8a1SAdrian Hunter out: 2352dd6d8a1SAdrian Hunter return rc; 2362dd6d8a1SAdrian Hunter } 2372dd6d8a1SAdrian Hunter 2382dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2392dd6d8a1SAdrian Hunter { 2402dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2412dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2422dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2432dd6d8a1SAdrian Hunter } else { 2442dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2452dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2462dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2472dd6d8a1SAdrian Hunter } 2482dd6d8a1SAdrian Hunter } 2492dd6d8a1SAdrian Hunter 250e31f0d01SAdrian Hunter #else 251e31f0d01SAdrian Hunter 252e31f0d01SAdrian Hunter static inline 253e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 254e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 255e31f0d01SAdrian Hunter { 256e31f0d01SAdrian Hunter return 0; 257e31f0d01SAdrian Hunter } 258e31f0d01SAdrian Hunter 2592dd6d8a1SAdrian Hunter static inline 2602dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2612dd6d8a1SAdrian Hunter { 2622dd6d8a1SAdrian Hunter } 2632dd6d8a1SAdrian Hunter 2642dd6d8a1SAdrian Hunter static inline 2652dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2662dd6d8a1SAdrian Hunter { 2672dd6d8a1SAdrian Hunter return 0; 2682dd6d8a1SAdrian Hunter } 2692dd6d8a1SAdrian Hunter 270e31f0d01SAdrian Hunter #endif 271e31f0d01SAdrian Hunter 2728c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 273dd7927f4SArnaldo Carvalho de Melo { 27456e52e85SArnaldo Carvalho de Melo char msg[512]; 2756a4bb04cSJiri Olsa struct perf_evsel *pos; 276d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 277d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 278b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2798d3eca20SDavid Ahern int rc = 0; 280dd7927f4SArnaldo Carvalho de Melo 281f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 282cac21425SJiri Olsa 2830050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2843da297a6SIngo Molnar try_again: 285d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 28656e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2873da297a6SIngo Molnar if (verbose) 288c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2893da297a6SIngo Molnar goto try_again; 2903da297a6SIngo Molnar } 291ca6a4258SDavid Ahern 29256e52e85SArnaldo Carvalho de Melo rc = -errno; 29356e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 29456e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 29556e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2968d3eca20SDavid Ahern goto out; 2977c6a1c65SPeter Zijlstra } 2987c6a1c65SPeter Zijlstra } 2997c6a1c65SPeter Zijlstra 30023d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 30123d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 30223d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30335550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3048d3eca20SDavid Ahern rc = -1; 3058d3eca20SDavid Ahern goto out; 3060a102479SFrederic Weisbecker } 3070a102479SFrederic Weisbecker 308ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3092dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3102dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3118d3eca20SDavid Ahern if (errno == EPERM) { 3128d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31318e60939SNelson Elhage "Consider increasing " 31418e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 31518e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 316ef149c25SAdrian Hunter "(current value: %u,%u)\n", 317ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3188d3eca20SDavid Ahern rc = -errno; 3198d3eca20SDavid Ahern } else { 32035550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 32135550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3228d3eca20SDavid Ahern rc = -errno; 3238d3eca20SDavid Ahern } 3248d3eca20SDavid Ahern goto out; 32518e60939SNelson Elhage } 3260a27d7f9SArnaldo Carvalho de Melo 327a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3287b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3298d3eca20SDavid Ahern out: 3308d3eca20SDavid Ahern return rc; 331a91e5431SArnaldo Carvalho de Melo } 332a91e5431SArnaldo Carvalho de Melo 333e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 334e3d59112SNamhyung Kim union perf_event *event, 335e3d59112SNamhyung Kim struct perf_sample *sample, 336e3d59112SNamhyung Kim struct perf_evsel *evsel, 337e3d59112SNamhyung Kim struct machine *machine) 338e3d59112SNamhyung Kim { 339e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 340e3d59112SNamhyung Kim 341e3d59112SNamhyung Kim rec->samples++; 342e3d59112SNamhyung Kim 343e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 344e3d59112SNamhyung Kim } 345e3d59112SNamhyung Kim 3468c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3476122e4e4SArnaldo Carvalho de Melo { 348f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 349f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3506122e4e4SArnaldo Carvalho de Melo 351457ae94aSHe Kuang if (file->size == 0) 3529f591fd7SArnaldo Carvalho de Melo return 0; 3539f591fd7SArnaldo Carvalho de Melo 35400dc8657SNamhyung Kim /* 35500dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 35600dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 35700dc8657SNamhyung Kim * we prefer the vmlinux path like 35800dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 35900dc8657SNamhyung Kim * 36000dc8657SNamhyung Kim * rather than build-id path (in debug directory). 36100dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 36200dc8657SNamhyung Kim */ 36300dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 36400dc8657SNamhyung Kim 365b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3666122e4e4SArnaldo Carvalho de Melo } 3676122e4e4SArnaldo Carvalho de Melo 3688115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 369a1645ce1SZhang, Yanmin { 370a1645ce1SZhang, Yanmin int err; 37145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 372a1645ce1SZhang, Yanmin /* 373a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 374a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 375a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 376a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 377a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 378a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 379a1645ce1SZhang, Yanmin */ 38045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 381743eb868SArnaldo Carvalho de Melo machine); 382a1645ce1SZhang, Yanmin if (err < 0) 383a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 38423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 385a1645ce1SZhang, Yanmin 386a1645ce1SZhang, Yanmin /* 387a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 388a1645ce1SZhang, Yanmin * have no _text sometimes. 389a1645ce1SZhang, Yanmin */ 39045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 3910ae617beSAdrian Hunter machine); 392a1645ce1SZhang, Yanmin if (err < 0) 393a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 39423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 395a1645ce1SZhang, Yanmin } 396a1645ce1SZhang, Yanmin 39798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 39898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 39998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 40098402807SFrederic Weisbecker }; 40198402807SFrederic Weisbecker 4028c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 40398402807SFrederic Weisbecker { 404dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4050e2e63ddSPeter Zijlstra int i; 4068d3eca20SDavid Ahern int rc = 0; 40798402807SFrederic Weisbecker 408d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 409ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 410ef149c25SAdrian Hunter 4118d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 412e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4138d3eca20SDavid Ahern rc = -1; 4148d3eca20SDavid Ahern goto out; 4158d3eca20SDavid Ahern } 4168d3eca20SDavid Ahern } 417ef149c25SAdrian Hunter 4182dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 419ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 420ef149c25SAdrian Hunter rc = -1; 421ef149c25SAdrian Hunter goto out; 422ef149c25SAdrian Hunter } 42398402807SFrederic Weisbecker } 42498402807SFrederic Weisbecker 425dcabb507SJiri Olsa /* 426dcabb507SJiri Olsa * Mark the round finished in case we wrote 427dcabb507SJiri Olsa * at least one event. 428dcabb507SJiri Olsa */ 429dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4308c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4318d3eca20SDavid Ahern 4328d3eca20SDavid Ahern out: 4338d3eca20SDavid Ahern return rc; 43498402807SFrederic Weisbecker } 43598402807SFrederic Weisbecker 4368c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 43757706abcSDavid Ahern { 43857706abcSDavid Ahern struct perf_session *session = rec->session; 43957706abcSDavid Ahern int feat; 44057706abcSDavid Ahern 44157706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 44257706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 44357706abcSDavid Ahern 44457706abcSDavid Ahern if (rec->no_buildid) 44557706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 44657706abcSDavid Ahern 4473e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 44857706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 44957706abcSDavid Ahern 45057706abcSDavid Ahern if (!rec->opts.branch_stack) 45157706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 452ef149c25SAdrian Hunter 453ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 454ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 45557706abcSDavid Ahern } 45657706abcSDavid Ahern 457f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 458f33cbe72SArnaldo Carvalho de Melo 459f33cbe72SArnaldo Carvalho de Melo /* 460f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 461f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 462f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 463f33cbe72SArnaldo Carvalho de Melo */ 46445604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 46545604710SNamhyung Kim siginfo_t *info, 466f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 467f33cbe72SArnaldo Carvalho de Melo { 468f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 469f33cbe72SArnaldo Carvalho de Melo done = 1; 470f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 471f33cbe72SArnaldo Carvalho de Melo } 472f33cbe72SArnaldo Carvalho de Melo 4732dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 4742dd6d8a1SAdrian Hunter 4758c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 47686470930SIngo Molnar { 47757706abcSDavid Ahern int err; 47845604710SNamhyung Kim int status = 0; 4798b412664SPeter Zijlstra unsigned long waking = 0; 48046be604bSZhang, Yanmin const bool forks = argc > 0; 48123346f21SArnaldo Carvalho de Melo struct machine *machine; 48245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 483b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 484f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 485d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 4866dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 48742aa276fSNamhyung Kim int fd; 48886470930SIngo Molnar 489d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 49033e49ea7SAndi Kleen 49145604710SNamhyung Kim atexit(record__sig_exit); 492f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 493f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 494804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 4952dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 4962dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 4972dd6d8a1SAdrian Hunter else 4982dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 499f5970550SPeter Zijlstra 500b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 50194c744b6SArnaldo Carvalho de Melo if (session == NULL) { 502ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 503a9a70bbcSArnaldo Carvalho de Melo return -1; 504a9a70bbcSArnaldo Carvalho de Melo } 505a9a70bbcSArnaldo Carvalho de Melo 50642aa276fSNamhyung Kim fd = perf_data_file__fd(file); 507d20deb64SArnaldo Carvalho de Melo rec->session = session; 508d20deb64SArnaldo Carvalho de Melo 5098c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 510330aa675SStephane Eranian 511d4db3f16SArnaldo Carvalho de Melo if (forks) { 5123e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 513f5fc1412SJiri Olsa argv, file->is_pipe, 514735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 51535b9d88eSArnaldo Carvalho de Melo if (err < 0) { 51635b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 51745604710SNamhyung Kim status = err; 51835b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 519856e9660SPeter Zijlstra } 520856e9660SPeter Zijlstra } 521856e9660SPeter Zijlstra 5228c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 5238d3eca20SDavid Ahern err = -1; 52445604710SNamhyung Kim goto out_child; 5258d3eca20SDavid Ahern } 52686470930SIngo Molnar 527cca8482cSAdrian Hunter /* 528cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 529cca8482cSAdrian Hunter * evlist. 530cca8482cSAdrian Hunter */ 531cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 532cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 533cca8482cSAdrian Hunter rec->tool.ordered_events = false; 534cca8482cSAdrian Hunter } 535cca8482cSAdrian Hunter 5363e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 537a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 538a8bb559bSNamhyung Kim 539f5fc1412SJiri Olsa if (file->is_pipe) { 54042aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 541529870e3STom Zanussi if (err < 0) 54245604710SNamhyung Kim goto out_child; 543563aecb2SJiri Olsa } else { 54442aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 545d5eed904SArnaldo Carvalho de Melo if (err < 0) 54645604710SNamhyung Kim goto out_child; 547d5eed904SArnaldo Carvalho de Melo } 5487c6a1c65SPeter Zijlstra 549d3665498SDavid Ahern if (!rec->no_buildid 550e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 551d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 552e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5538d3eca20SDavid Ahern err = -1; 55445604710SNamhyung Kim goto out_child; 555e20960c0SRobert Richter } 556e20960c0SRobert Richter 55734ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 558743eb868SArnaldo Carvalho de Melo 559f5fc1412SJiri Olsa if (file->is_pipe) { 56045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 561a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5622c46dbb5STom Zanussi if (err < 0) { 5632c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 56445604710SNamhyung Kim goto out_child; 5652c46dbb5STom Zanussi } 566cd19a035STom Zanussi 5673e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 56863e0c771STom Zanussi /* 56963e0c771STom Zanussi * FIXME err <= 0 here actually means that 57063e0c771STom Zanussi * there were no tracepoints so its not really 57163e0c771STom Zanussi * an error, just that we don't need to 57263e0c771STom Zanussi * synthesize anything. We really have to 57363e0c771STom Zanussi * return this more properly and also 57463e0c771STom Zanussi * propagate errors that now are calling die() 57563e0c771STom Zanussi */ 57642aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 577743eb868SArnaldo Carvalho de Melo process_synthesized_event); 57863e0c771STom Zanussi if (err <= 0) { 57963e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 58045604710SNamhyung Kim goto out_child; 58163e0c771STom Zanussi } 582f34b9001SDavid Ahern rec->bytes_written += err; 5832c46dbb5STom Zanussi } 58463e0c771STom Zanussi } 5852c46dbb5STom Zanussi 586ef149c25SAdrian Hunter if (rec->opts.full_auxtrace) { 587ef149c25SAdrian Hunter err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 588ef149c25SAdrian Hunter session, process_synthesized_event); 589ef149c25SAdrian Hunter if (err) 590ef149c25SAdrian Hunter goto out_delete_session; 591ef149c25SAdrian Hunter } 592ef149c25SAdrian Hunter 59345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 5940ae617beSAdrian Hunter machine); 595c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 596c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 597c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 598c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 59956b03f3cSArnaldo Carvalho de Melo 60045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 601743eb868SArnaldo Carvalho de Melo machine); 602c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 603c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 604c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 605c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 606c1a3a4b9SArnaldo Carvalho de Melo 6077e383de4SArnaldo Carvalho de Melo if (perf_guest) { 608876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 6097e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 6107e383de4SArnaldo Carvalho de Melo } 611b7cece76SArnaldo Carvalho de Melo 6123e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 6139d9cad76SKan Liang process_synthesized_event, opts->sample_address, 6149d9cad76SKan Liang opts->proc_map_timeout); 6158d3eca20SDavid Ahern if (err != 0) 61645604710SNamhyung Kim goto out_child; 6178d3eca20SDavid Ahern 618d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 61986470930SIngo Molnar struct sched_param param; 62086470930SIngo Molnar 621d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 62286470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6236beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6248d3eca20SDavid Ahern err = -1; 62545604710SNamhyung Kim goto out_child; 62686470930SIngo Molnar } 62786470930SIngo Molnar } 62886470930SIngo Molnar 629774cb499SJiri Olsa /* 630774cb499SJiri Olsa * When perf is starting the traced process, all the events 631774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 632774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 633774cb499SJiri Olsa */ 6346619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 6353e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 636764e16a3SDavid Ahern 637856e9660SPeter Zijlstra /* 638856e9660SPeter Zijlstra * Let the child rip 639856e9660SPeter Zijlstra */ 640e803cf97SNamhyung Kim if (forks) { 641e5bed564SNamhyung Kim union perf_event *event; 642e5bed564SNamhyung Kim 643e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 644e5bed564SNamhyung Kim if (event == NULL) { 645e5bed564SNamhyung Kim err = -ENOMEM; 646e5bed564SNamhyung Kim goto out_child; 647e5bed564SNamhyung Kim } 648e5bed564SNamhyung Kim 649e803cf97SNamhyung Kim /* 650e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 651e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 652e803cf97SNamhyung Kim * cannot see a correct process name for those events. 653e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 654e803cf97SNamhyung Kim */ 655e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 656e803cf97SNamhyung Kim rec->evlist->workload.pid, 657e803cf97SNamhyung Kim process_synthesized_event, 658e803cf97SNamhyung Kim machine); 659e5bed564SNamhyung Kim free(event); 660e803cf97SNamhyung Kim 6613e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 662e803cf97SNamhyung Kim } 663856e9660SPeter Zijlstra 6646619a53eSAndi Kleen if (opts->initial_delay) { 6656619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 6666619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 6676619a53eSAndi Kleen } 6686619a53eSAndi Kleen 6692dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 670649c48a9SPeter Zijlstra for (;;) { 6719f065194SYang Shi unsigned long long hits = rec->samples; 67286470930SIngo Molnar 6738c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 6742dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6758d3eca20SDavid Ahern err = -1; 67645604710SNamhyung Kim goto out_child; 6778d3eca20SDavid Ahern } 67886470930SIngo Molnar 6792dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 6802dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 6812dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 6822dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 6832dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 6842dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 6852dd6d8a1SAdrian Hunter err = -1; 6862dd6d8a1SAdrian Hunter goto out_child; 6872dd6d8a1SAdrian Hunter } 6882dd6d8a1SAdrian Hunter } 6892dd6d8a1SAdrian Hunter 690d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 6916dcf45efSArnaldo Carvalho de Melo if (done || draining) 692649c48a9SPeter Zijlstra break; 693f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 694a515114fSJiri Olsa /* 695a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 696a515114fSJiri Olsa * number of returned events and interrupt error. 697a515114fSJiri Olsa */ 698a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 69945604710SNamhyung Kim err = 0; 7008b412664SPeter Zijlstra waking++; 7016dcf45efSArnaldo Carvalho de Melo 7026dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 7036dcf45efSArnaldo Carvalho de Melo draining = true; 7048b412664SPeter Zijlstra } 7058b412664SPeter Zijlstra 706774cb499SJiri Olsa /* 707774cb499SJiri Olsa * When perf is starting the traced process, at the end events 708774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 709774cb499SJiri Olsa * disable events in this case. 710774cb499SJiri Olsa */ 711602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 7122dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7133e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 7142711926aSJiri Olsa disabled = true; 7152711926aSJiri Olsa } 7168b412664SPeter Zijlstra } 7172dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7188b412664SPeter Zijlstra 719f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 72035550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 721f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 722f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 723f33cbe72SArnaldo Carvalho de Melo err = -1; 72445604710SNamhyung Kim goto out_child; 725f33cbe72SArnaldo Carvalho de Melo } 726f33cbe72SArnaldo Carvalho de Melo 727e3d59112SNamhyung Kim if (!quiet) 7288b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 72986470930SIngo Molnar 73045604710SNamhyung Kim out_child: 73145604710SNamhyung Kim if (forks) { 73245604710SNamhyung Kim int exit_status; 73345604710SNamhyung Kim 73445604710SNamhyung Kim if (!child_finished) 73545604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 73645604710SNamhyung Kim 73745604710SNamhyung Kim wait(&exit_status); 73845604710SNamhyung Kim 73945604710SNamhyung Kim if (err < 0) 74045604710SNamhyung Kim status = err; 74145604710SNamhyung Kim else if (WIFEXITED(exit_status)) 74245604710SNamhyung Kim status = WEXITSTATUS(exit_status); 74345604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 74445604710SNamhyung Kim signr = WTERMSIG(exit_status); 74545604710SNamhyung Kim } else 74645604710SNamhyung Kim status = err; 74745604710SNamhyung Kim 748e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 749e3d59112SNamhyung Kim rec->samples = 0; 750e3d59112SNamhyung Kim 75145604710SNamhyung Kim if (!err && !file->is_pipe) { 75245604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 753457ae94aSHe Kuang file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 75445604710SNamhyung Kim 755cd10b289SAdrian Hunter if (!rec->no_buildid) { 75645604710SNamhyung Kim process_buildids(rec); 757cd10b289SAdrian Hunter /* 758cd10b289SAdrian Hunter * We take all buildids when the file contains 759cd10b289SAdrian Hunter * AUX area tracing data because we do not decode the 760cd10b289SAdrian Hunter * trace because it would take too long. 761cd10b289SAdrian Hunter */ 762cd10b289SAdrian Hunter if (rec->opts.full_auxtrace) 763cd10b289SAdrian Hunter dsos__hit_all(rec->session); 764cd10b289SAdrian Hunter } 76542aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 76645604710SNamhyung Kim } 76739d17dacSArnaldo Carvalho de Melo 768e3d59112SNamhyung Kim if (!err && !quiet) { 769e3d59112SNamhyung Kim char samples[128]; 770e3d59112SNamhyung Kim 771ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 772e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 773e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 774e3d59112SNamhyung Kim else 775e3d59112SNamhyung Kim samples[0] = '\0'; 776e3d59112SNamhyung Kim 777e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 778e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 779e3d59112SNamhyung Kim file->path, samples); 780e3d59112SNamhyung Kim } 781e3d59112SNamhyung Kim 78239d17dacSArnaldo Carvalho de Melo out_delete_session: 78339d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 78445604710SNamhyung Kim return status; 78586470930SIngo Molnar } 78686470930SIngo Molnar 78772a128aaSNamhyung Kim static void callchain_debug(void) 78809b0fd45SJiri Olsa { 789aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 790a601fdffSJiri Olsa 79172a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 79226d33022SJiri Olsa 79372a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 79409b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 79572a128aaSNamhyung Kim callchain_param.dump_size); 79609b0fd45SJiri Olsa } 79709b0fd45SJiri Olsa 798c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 79909b0fd45SJiri Olsa const char *arg, 80009b0fd45SJiri Olsa int unset) 80109b0fd45SJiri Olsa { 80209b0fd45SJiri Olsa int ret; 803c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 80409b0fd45SJiri Olsa 805c421e80bSKan Liang record->callgraph_set = true; 80672a128aaSNamhyung Kim callchain_param.enabled = !unset; 807eb853e80SJiri Olsa 80809b0fd45SJiri Olsa /* --no-call-graph */ 80909b0fd45SJiri Olsa if (unset) { 81072a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 81109b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 81209b0fd45SJiri Olsa return 0; 81309b0fd45SJiri Olsa } 81409b0fd45SJiri Olsa 815c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 81609b0fd45SJiri Olsa if (!ret) 81772a128aaSNamhyung Kim callchain_debug(); 81809b0fd45SJiri Olsa 81926d33022SJiri Olsa return ret; 82026d33022SJiri Olsa } 82126d33022SJiri Olsa 822c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 82309b0fd45SJiri Olsa const char *arg __maybe_unused, 82409b0fd45SJiri Olsa int unset __maybe_unused) 82509b0fd45SJiri Olsa { 826c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 827c421e80bSKan Liang 828c421e80bSKan Liang record->callgraph_set = true; 82972a128aaSNamhyung Kim callchain_param.enabled = true; 83009b0fd45SJiri Olsa 83172a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 83272a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 833eb853e80SJiri Olsa 83472a128aaSNamhyung Kim callchain_debug(); 83509b0fd45SJiri Olsa return 0; 83609b0fd45SJiri Olsa } 83709b0fd45SJiri Olsa 838eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 839eb853e80SJiri Olsa { 840eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 8415a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 842eb853e80SJiri Olsa 843eb853e80SJiri Olsa return perf_default_config(var, value, cb); 844eb853e80SJiri Olsa } 845eb853e80SJiri Olsa 846814c8c38SPeter Zijlstra struct clockid_map { 847814c8c38SPeter Zijlstra const char *name; 848814c8c38SPeter Zijlstra int clockid; 849814c8c38SPeter Zijlstra }; 850814c8c38SPeter Zijlstra 851814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 852814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 853814c8c38SPeter Zijlstra 854814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 855814c8c38SPeter Zijlstra 856814c8c38SPeter Zijlstra 857814c8c38SPeter Zijlstra /* 858814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 859814c8c38SPeter Zijlstra */ 860814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 861814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 862814c8c38SPeter Zijlstra #endif 863814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 864814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 865814c8c38SPeter Zijlstra #endif 866814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 867814c8c38SPeter Zijlstra #define CLOCK_TAI 11 868814c8c38SPeter Zijlstra #endif 869814c8c38SPeter Zijlstra 870814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 871814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 872814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 873814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 874814c8c38SPeter Zijlstra 875814c8c38SPeter Zijlstra /* available for some events */ 876814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 877814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 878814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 879814c8c38SPeter Zijlstra 880814c8c38SPeter Zijlstra /* available for the lazy */ 881814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 882814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 883814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 884814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 885814c8c38SPeter Zijlstra 886814c8c38SPeter Zijlstra CLOCKID_END, 887814c8c38SPeter Zijlstra }; 888814c8c38SPeter Zijlstra 889814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 890814c8c38SPeter Zijlstra { 891814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 892814c8c38SPeter Zijlstra const struct clockid_map *cm; 893814c8c38SPeter Zijlstra const char *ostr = str; 894814c8c38SPeter Zijlstra 895814c8c38SPeter Zijlstra if (unset) { 896814c8c38SPeter Zijlstra opts->use_clockid = 0; 897814c8c38SPeter Zijlstra return 0; 898814c8c38SPeter Zijlstra } 899814c8c38SPeter Zijlstra 900814c8c38SPeter Zijlstra /* no arg passed */ 901814c8c38SPeter Zijlstra if (!str) 902814c8c38SPeter Zijlstra return 0; 903814c8c38SPeter Zijlstra 904814c8c38SPeter Zijlstra /* no setting it twice */ 905814c8c38SPeter Zijlstra if (opts->use_clockid) 906814c8c38SPeter Zijlstra return -1; 907814c8c38SPeter Zijlstra 908814c8c38SPeter Zijlstra opts->use_clockid = true; 909814c8c38SPeter Zijlstra 910814c8c38SPeter Zijlstra /* if its a number, we're done */ 911814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 912814c8c38SPeter Zijlstra return 0; 913814c8c38SPeter Zijlstra 914814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 915814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 916814c8c38SPeter Zijlstra str += 6; 917814c8c38SPeter Zijlstra 918814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 919814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 920814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 921814c8c38SPeter Zijlstra return 0; 922814c8c38SPeter Zijlstra } 923814c8c38SPeter Zijlstra } 924814c8c38SPeter Zijlstra 925814c8c38SPeter Zijlstra opts->use_clockid = false; 926814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 927814c8c38SPeter Zijlstra return -1; 928814c8c38SPeter Zijlstra } 929814c8c38SPeter Zijlstra 930e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 931e9db1310SAdrian Hunter const char *str, 932e9db1310SAdrian Hunter int unset __maybe_unused) 933e9db1310SAdrian Hunter { 934e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 935e9db1310SAdrian Hunter char *s, *p; 936e9db1310SAdrian Hunter unsigned int mmap_pages; 937e9db1310SAdrian Hunter int ret; 938e9db1310SAdrian Hunter 939e9db1310SAdrian Hunter if (!str) 940e9db1310SAdrian Hunter return -EINVAL; 941e9db1310SAdrian Hunter 942e9db1310SAdrian Hunter s = strdup(str); 943e9db1310SAdrian Hunter if (!s) 944e9db1310SAdrian Hunter return -ENOMEM; 945e9db1310SAdrian Hunter 946e9db1310SAdrian Hunter p = strchr(s, ','); 947e9db1310SAdrian Hunter if (p) 948e9db1310SAdrian Hunter *p = '\0'; 949e9db1310SAdrian Hunter 950e9db1310SAdrian Hunter if (*s) { 951e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 952e9db1310SAdrian Hunter if (ret) 953e9db1310SAdrian Hunter goto out_free; 954e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 955e9db1310SAdrian Hunter } 956e9db1310SAdrian Hunter 957e9db1310SAdrian Hunter if (!p) { 958e9db1310SAdrian Hunter ret = 0; 959e9db1310SAdrian Hunter goto out_free; 960e9db1310SAdrian Hunter } 961e9db1310SAdrian Hunter 962e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 963e9db1310SAdrian Hunter if (ret) 964e9db1310SAdrian Hunter goto out_free; 965e9db1310SAdrian Hunter 966e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 967e9db1310SAdrian Hunter 968e9db1310SAdrian Hunter out_free: 969e9db1310SAdrian Hunter free(s); 970e9db1310SAdrian Hunter return ret; 971e9db1310SAdrian Hunter } 972e9db1310SAdrian Hunter 973e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 97486470930SIngo Molnar "perf record [<options>] [<command>]", 97586470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 97686470930SIngo Molnar NULL 97786470930SIngo Molnar }; 978e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 97986470930SIngo Molnar 980d20deb64SArnaldo Carvalho de Melo /* 9818c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 9828c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 983d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 984d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 985d20deb64SArnaldo Carvalho de Melo * 986d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 987d20deb64SArnaldo Carvalho de Melo * 988d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 989d20deb64SArnaldo Carvalho de Melo */ 9908c6f45a7SArnaldo Carvalho de Melo static struct record record = { 991d20deb64SArnaldo Carvalho de Melo .opts = { 9928affc2b8SAndi Kleen .sample_time = true, 993d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 994d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 995d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 996447a6013SArnaldo Carvalho de Melo .freq = 4000, 997d1cb9fceSNamhyung Kim .target = { 998d1cb9fceSNamhyung Kim .uses_mmap = true, 9993aa5939dSAdrian Hunter .default_per_cpu = true, 1000d1cb9fceSNamhyung Kim }, 10019d9cad76SKan Liang .proc_map_timeout = 500, 1002d20deb64SArnaldo Carvalho de Melo }, 1003e3d59112SNamhyung Kim .tool = { 1004e3d59112SNamhyung Kim .sample = process_sample_event, 1005e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1006cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1007e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1008e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1009e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1010cca8482cSAdrian Hunter .ordered_events = true, 1011e3d59112SNamhyung Kim }, 1012d20deb64SArnaldo Carvalho de Melo }; 10137865e817SFrederic Weisbecker 101476a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 101576a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 101661eaa3beSArnaldo Carvalho de Melo 1017d20deb64SArnaldo Carvalho de Melo /* 1018d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1019d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1020b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1021d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1022d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1023d20deb64SArnaldo Carvalho de Melo */ 1024e5b2c207SNamhyung Kim struct option __record_options[] = { 1025d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 102686470930SIngo Molnar "event selector. use 'perf list' to list available events", 1027f120f9d5SJiri Olsa parse_events_option), 1028d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1029c171b552SLi Zefan "event filter", parse_filter), 10304ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 10314ba1faa1SWang Nan NULL, "don't record events from perf itself", 10324ba1faa1SWang Nan exclude_perf), 1033bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1034d6d901c2SZhang, Yanmin "record events on existing process id"), 1035bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1036d6d901c2SZhang, Yanmin "record events on existing thread id"), 1037d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 103886470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1039509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1040acac03faSKirill Smelkov "collect data without buffering"), 1041d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1042daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1043bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 104486470930SIngo Molnar "system-wide collection from all CPUs"), 1045bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1046c45c6ea2SStephane Eranian "list of cpus to monitor"), 1047d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1048f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 104986470930SIngo Molnar "output file name"), 105069e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 105169e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 10522e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1053d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1054e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1055e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1056e9db1310SAdrian Hunter record__parse_mmap_pages), 1057d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 105843bece79SLin Ming "put the counters into a counter group"), 105909b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 106009b0fd45SJiri Olsa NULL, "enables call-graph recording" , 106109b0fd45SJiri Olsa &record_callchain_opt), 106209b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 106376a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 106409b0fd45SJiri Olsa &record_parse_callchain_opt), 1065c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 10663da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1067b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1068d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1069649c48a9SPeter Zijlstra "per thread counts"), 107056100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 10713abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 10723abebc55SAdrian Hunter &record.opts.sample_time_set, 10733abebc55SAdrian Hunter "Record the sample timestamps"), 107456100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1075d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1076649c48a9SPeter Zijlstra "don't sample"), 1077d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1078a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1079d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 1080baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1081d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1082023695d9SStephane Eranian "monitor event in cgroup name only", 1083023695d9SStephane Eranian parse_cgroups), 1084a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 10856619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1086bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1087bea03405SNamhyung Kim "user to profile"), 1088a5aabdacSStephane Eranian 1089a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1090a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1091a5aabdacSStephane Eranian parse_branch_stack), 1092a5aabdacSStephane Eranian 1093a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1094a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1095bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 109605484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 109705484298SAndi Kleen "sample by weight (on special events only)"), 1098475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1099475eeab9SAndi Kleen "sample transaction flags (special events only)"), 11003aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 11013aa5939dSAdrian Hunter "use per-thread mmaps"), 1102bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1103bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1104bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 110585c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 110685c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1107814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1108814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1109814c8c38SPeter Zijlstra parse_clockid), 11102dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 11112dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 11129d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 11139d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1114b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1115b757bb09SAdrian Hunter "Record context switch events"), 111671dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 111771dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 111871dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 111971dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 112086470930SIngo Molnar OPT_END() 112186470930SIngo Molnar }; 112286470930SIngo Molnar 1123e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1124e5b2c207SNamhyung Kim 11251d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 112686470930SIngo Molnar { 1127ef149c25SAdrian Hunter int err; 11288c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 112916ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 113086470930SIngo Molnar 1131*48e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 1132*48e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 1133*48e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 1134*48e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 1135*48e1cab1SWang Nan # undef set_nobuild 1136*48e1cab1SWang Nan #endif 1137*48e1cab1SWang Nan 11383e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 11393e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1140361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1141361c99a6SArnaldo Carvalho de Melo 1142eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1143eb853e80SJiri Olsa 1144bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1145a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1146602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1147bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 114886470930SIngo Molnar 1149bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1150c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1151c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1152c7118369SNamhyung Kim 1153023695d9SStephane Eranian } 1154b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1155b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1156c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1157c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1158c7118369SNamhyung Kim return -EINVAL; 1159b757bb09SAdrian Hunter } 1160023695d9SStephane Eranian 1161ef149c25SAdrian Hunter if (!rec->itr) { 1162ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1163ef149c25SAdrian Hunter if (err) 1164ef149c25SAdrian Hunter return err; 1165ef149c25SAdrian Hunter } 1166ef149c25SAdrian Hunter 11672dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 11682dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 11692dd6d8a1SAdrian Hunter if (err) 11702dd6d8a1SAdrian Hunter return err; 11712dd6d8a1SAdrian Hunter 1172ef149c25SAdrian Hunter err = -ENOMEM; 1173ef149c25SAdrian Hunter 11740a7e6d1bSNamhyung Kim symbol__init(NULL); 1175baa2f6ceSArnaldo Carvalho de Melo 1176ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1177646aaea6SArnaldo Carvalho de Melo pr_warning( 1178646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1179ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1180646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1181646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1182646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1183646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1184646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1185ec80fde7SArnaldo Carvalho de Melo 1186d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1187a1ac1d3cSStephane Eranian disable_buildid_cache(); 1188655000e7SArnaldo Carvalho de Melo 11893e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 11903e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 119169aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 119269aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1193bbd36e5eSPeter Zijlstra } 119486470930SIngo Molnar 119569e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 119669e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 119769e7e5b0SAdrian Hunter 1198602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 119916ad2ffbSNamhyung Kim if (err) { 1200602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 120116ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 120216ad2ffbSNamhyung Kim } 12034bd0f2d2SNamhyung Kim 1204602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 120516ad2ffbSNamhyung Kim if (err) { 120616ad2ffbSNamhyung Kim int saved_errno = errno; 120716ad2ffbSNamhyung Kim 1208602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 12093780f488SNamhyung Kim ui__error("%s", errbuf); 121016ad2ffbSNamhyung Kim 121116ad2ffbSNamhyung Kim err = -saved_errno; 12128fa60e1fSNamhyung Kim goto out_symbol_exit; 121316ad2ffbSNamhyung Kim } 12140d37aa34SArnaldo Carvalho de Melo 121516ad2ffbSNamhyung Kim err = -ENOMEM; 12163e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1217dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 121869aad6f1SArnaldo Carvalho de Melo 1219ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1220ef149c25SAdrian Hunter if (err) 1221ef149c25SAdrian Hunter goto out_symbol_exit; 1222ef149c25SAdrian Hunter 1223b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 122439d17dacSArnaldo Carvalho de Melo err = -EINVAL; 122503ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 12267e4ff9e3SMike Galbraith } 12277e4ff9e3SMike Galbraith 1228d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1229d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 123045604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1231d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1232ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 123339d17dacSArnaldo Carvalho de Melo return err; 123486470930SIngo Molnar } 12352dd6d8a1SAdrian Hunter 12362dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 12372dd6d8a1SAdrian Hunter { 12382dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 12392dd6d8a1SAdrian Hunter return; 12402dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 12412dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 12422dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 12432dd6d8a1SAdrian Hunter } 1244