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" 30ef149c25SAdrian Hunter #include "util/auxtrace.h" 31f00898f4SAndi Kleen #include "util/parse-branch-options.h" 327c6a1c65SPeter Zijlstra 3386470930SIngo Molnar #include <unistd.h> 3486470930SIngo Molnar #include <sched.h> 35a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3686470930SIngo Molnar 3778da39faSBernhard Rosenkraenzer 388c6f45a7SArnaldo Carvalho de Melo struct record { 3945694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 40b4006796SArnaldo Carvalho de Melo struct record_opts opts; 41d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 42f5fc1412SJiri Olsa struct perf_data_file file; 43ef149c25SAdrian Hunter struct auxtrace_record *itr; 44d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 45d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 46d20deb64SArnaldo Carvalho de Melo const char *progname; 47d20deb64SArnaldo Carvalho de Melo int realtime_prio; 48d20deb64SArnaldo Carvalho de Melo bool no_buildid; 49d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 50d20deb64SArnaldo Carvalho de Melo long samples; 510f82ebc4SArnaldo Carvalho de Melo }; 5286470930SIngo Molnar 538c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 54f5970550SPeter Zijlstra { 55cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 564f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 578d3eca20SDavid Ahern return -1; 588d3eca20SDavid Ahern } 59f5970550SPeter Zijlstra 60cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 618d3eca20SDavid Ahern return 0; 62f5970550SPeter Zijlstra } 63f5970550SPeter Zijlstra 6445694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 65d20deb64SArnaldo Carvalho de Melo union perf_event *event, 661d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 671d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 68234fbbf5SArnaldo Carvalho de Melo { 698c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 708c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 71234fbbf5SArnaldo Carvalho de Melo } 72234fbbf5SArnaldo Carvalho de Melo 73e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 7486470930SIngo Molnar { 75e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 767b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 777b8283b5SDavid Ahern u64 old = md->prev; 78918512b4SJiri Olsa unsigned char *data = md->base + page_size; 7986470930SIngo Molnar unsigned long size; 8086470930SIngo Molnar void *buf; 818d3eca20SDavid Ahern int rc = 0; 8286470930SIngo Molnar 83dc82009aSArnaldo Carvalho de Melo if (old == head) 848d3eca20SDavid Ahern return 0; 8586470930SIngo Molnar 86d20deb64SArnaldo Carvalho de Melo rec->samples++; 8786470930SIngo Molnar 8886470930SIngo Molnar size = head - old; 8986470930SIngo Molnar 9086470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9186470930SIngo Molnar buf = &data[old & md->mask]; 9286470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 9386470930SIngo Molnar old += size; 9486470930SIngo Molnar 958c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 968d3eca20SDavid Ahern rc = -1; 978d3eca20SDavid Ahern goto out; 988d3eca20SDavid Ahern } 9986470930SIngo Molnar } 10086470930SIngo Molnar 10186470930SIngo Molnar buf = &data[old & md->mask]; 10286470930SIngo Molnar size = head - old; 10386470930SIngo Molnar old += size; 10486470930SIngo Molnar 1058c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1068d3eca20SDavid Ahern rc = -1; 1078d3eca20SDavid Ahern goto out; 1088d3eca20SDavid Ahern } 10986470930SIngo Molnar 11086470930SIngo Molnar md->prev = old; 111e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1128d3eca20SDavid Ahern out: 1138d3eca20SDavid Ahern return rc; 11486470930SIngo Molnar } 11586470930SIngo Molnar 1162dd6d8a1SAdrian Hunter static volatile int done; 1172dd6d8a1SAdrian Hunter static volatile int signr = -1; 1182dd6d8a1SAdrian Hunter static volatile int child_finished; 1192dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1202dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1212dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1222dd6d8a1SAdrian Hunter 1232dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1242dd6d8a1SAdrian Hunter { 1252dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1262dd6d8a1SAdrian Hunter child_finished = 1; 1272dd6d8a1SAdrian Hunter else 1282dd6d8a1SAdrian Hunter signr = sig; 1292dd6d8a1SAdrian Hunter 1302dd6d8a1SAdrian Hunter done = 1; 1312dd6d8a1SAdrian Hunter } 1322dd6d8a1SAdrian Hunter 1332dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1342dd6d8a1SAdrian Hunter { 1352dd6d8a1SAdrian Hunter if (signr == -1) 1362dd6d8a1SAdrian Hunter return; 1372dd6d8a1SAdrian Hunter 1382dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1392dd6d8a1SAdrian Hunter raise(signr); 1402dd6d8a1SAdrian Hunter } 1412dd6d8a1SAdrian Hunter 142e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 143e31f0d01SAdrian Hunter 144ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 145ef149c25SAdrian Hunter union perf_event *event, void *data1, 146ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 147ef149c25SAdrian Hunter { 148ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 14999fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 150ef149c25SAdrian Hunter size_t padding; 151ef149c25SAdrian Hunter u8 pad[8] = {0}; 152ef149c25SAdrian Hunter 15399fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 15499fa2984SAdrian Hunter off_t file_offset; 15599fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 15699fa2984SAdrian Hunter int err; 15799fa2984SAdrian Hunter 15899fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 15999fa2984SAdrian Hunter if (file_offset == -1) 16099fa2984SAdrian Hunter return -1; 16199fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 16299fa2984SAdrian Hunter event, file_offset); 16399fa2984SAdrian Hunter if (err) 16499fa2984SAdrian Hunter return err; 16599fa2984SAdrian Hunter } 16699fa2984SAdrian Hunter 167ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 168ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 169ef149c25SAdrian Hunter if (padding) 170ef149c25SAdrian Hunter padding = 8 - padding; 171ef149c25SAdrian Hunter 172ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 173ef149c25SAdrian Hunter record__write(rec, data1, len1); 174ef149c25SAdrian Hunter if (len2) 175ef149c25SAdrian Hunter record__write(rec, data2, len2); 176ef149c25SAdrian Hunter record__write(rec, &pad, padding); 177ef149c25SAdrian Hunter 178ef149c25SAdrian Hunter return 0; 179ef149c25SAdrian Hunter } 180ef149c25SAdrian Hunter 181ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 182ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 183ef149c25SAdrian Hunter { 184ef149c25SAdrian Hunter int ret; 185ef149c25SAdrian Hunter 186ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 187ef149c25SAdrian Hunter record__process_auxtrace); 188ef149c25SAdrian Hunter if (ret < 0) 189ef149c25SAdrian Hunter return ret; 190ef149c25SAdrian Hunter 191ef149c25SAdrian Hunter if (ret) 192ef149c25SAdrian Hunter rec->samples++; 193ef149c25SAdrian Hunter 194ef149c25SAdrian Hunter return 0; 195ef149c25SAdrian Hunter } 196ef149c25SAdrian Hunter 1972dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 1982dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 1992dd6d8a1SAdrian Hunter { 2002dd6d8a1SAdrian Hunter int ret; 2012dd6d8a1SAdrian Hunter 2022dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2032dd6d8a1SAdrian Hunter record__process_auxtrace, 2042dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2052dd6d8a1SAdrian Hunter if (ret < 0) 2062dd6d8a1SAdrian Hunter return ret; 2072dd6d8a1SAdrian Hunter 2082dd6d8a1SAdrian Hunter if (ret) 2092dd6d8a1SAdrian Hunter rec->samples++; 2102dd6d8a1SAdrian Hunter 2112dd6d8a1SAdrian Hunter return 0; 2122dd6d8a1SAdrian Hunter } 2132dd6d8a1SAdrian Hunter 2142dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2152dd6d8a1SAdrian Hunter { 2162dd6d8a1SAdrian Hunter int i; 2172dd6d8a1SAdrian Hunter int rc = 0; 2182dd6d8a1SAdrian Hunter 2192dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2202dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2212dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2222dd6d8a1SAdrian Hunter 2232dd6d8a1SAdrian Hunter if (!mm->base) 2242dd6d8a1SAdrian Hunter continue; 2252dd6d8a1SAdrian Hunter 2262dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2272dd6d8a1SAdrian Hunter rc = -1; 2282dd6d8a1SAdrian Hunter goto out; 2292dd6d8a1SAdrian Hunter } 2302dd6d8a1SAdrian Hunter } 2312dd6d8a1SAdrian Hunter out: 2322dd6d8a1SAdrian Hunter return rc; 2332dd6d8a1SAdrian Hunter } 2342dd6d8a1SAdrian Hunter 2352dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2362dd6d8a1SAdrian Hunter { 2372dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2382dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2392dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2402dd6d8a1SAdrian Hunter } else { 2412dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2422dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2432dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2442dd6d8a1SAdrian Hunter } 2452dd6d8a1SAdrian Hunter } 2462dd6d8a1SAdrian Hunter 247e31f0d01SAdrian Hunter #else 248e31f0d01SAdrian Hunter 249e31f0d01SAdrian Hunter static inline 250e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 251e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 252e31f0d01SAdrian Hunter { 253e31f0d01SAdrian Hunter return 0; 254e31f0d01SAdrian Hunter } 255e31f0d01SAdrian Hunter 2562dd6d8a1SAdrian Hunter static inline 2572dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2582dd6d8a1SAdrian Hunter { 2592dd6d8a1SAdrian Hunter } 2602dd6d8a1SAdrian Hunter 2612dd6d8a1SAdrian Hunter static inline 2622dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2632dd6d8a1SAdrian Hunter { 2642dd6d8a1SAdrian Hunter return 0; 2652dd6d8a1SAdrian Hunter } 2662dd6d8a1SAdrian Hunter 267e31f0d01SAdrian Hunter #endif 268e31f0d01SAdrian Hunter 2698c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 270dd7927f4SArnaldo Carvalho de Melo { 27156e52e85SArnaldo Carvalho de Melo char msg[512]; 2726a4bb04cSJiri Olsa struct perf_evsel *pos; 273d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 274d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 275b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2768d3eca20SDavid Ahern int rc = 0; 277dd7927f4SArnaldo Carvalho de Melo 278f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 279cac21425SJiri Olsa 2800050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2813da297a6SIngo Molnar try_again: 2826a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 28356e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2843da297a6SIngo Molnar if (verbose) 285c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2863da297a6SIngo Molnar goto try_again; 2873da297a6SIngo Molnar } 288ca6a4258SDavid Ahern 28956e52e85SArnaldo Carvalho de Melo rc = -errno; 29056e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 29156e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 29256e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2938d3eca20SDavid Ahern goto out; 2947c6a1c65SPeter Zijlstra } 2957c6a1c65SPeter Zijlstra } 2967c6a1c65SPeter Zijlstra 29723d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 29823d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 29923d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30035550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3018d3eca20SDavid Ahern rc = -1; 3028d3eca20SDavid Ahern goto out; 3030a102479SFrederic Weisbecker } 3040a102479SFrederic Weisbecker 305ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3062dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3072dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3088d3eca20SDavid Ahern if (errno == EPERM) { 3098d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31018e60939SNelson Elhage "Consider increasing " 31118e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 31218e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 313ef149c25SAdrian Hunter "(current value: %u,%u)\n", 314ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3158d3eca20SDavid Ahern rc = -errno; 3168d3eca20SDavid Ahern } else { 31735550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 31835550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3198d3eca20SDavid Ahern rc = -errno; 3208d3eca20SDavid Ahern } 3218d3eca20SDavid Ahern goto out; 32218e60939SNelson Elhage } 3230a27d7f9SArnaldo Carvalho de Melo 324a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3257b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3268d3eca20SDavid Ahern out: 3278d3eca20SDavid Ahern return rc; 328a91e5431SArnaldo Carvalho de Melo } 329a91e5431SArnaldo Carvalho de Melo 330e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 331e3d59112SNamhyung Kim union perf_event *event, 332e3d59112SNamhyung Kim struct perf_sample *sample, 333e3d59112SNamhyung Kim struct perf_evsel *evsel, 334e3d59112SNamhyung Kim struct machine *machine) 335e3d59112SNamhyung Kim { 336e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 337e3d59112SNamhyung Kim 338e3d59112SNamhyung Kim rec->samples++; 339e3d59112SNamhyung Kim 340e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 341e3d59112SNamhyung Kim } 342e3d59112SNamhyung Kim 3438c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3446122e4e4SArnaldo Carvalho de Melo { 345f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 346f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3476122e4e4SArnaldo Carvalho de Melo 348457ae94aSHe Kuang if (file->size == 0) 3499f591fd7SArnaldo Carvalho de Melo return 0; 3509f591fd7SArnaldo Carvalho de Melo 35100dc8657SNamhyung Kim /* 35200dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 35300dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 35400dc8657SNamhyung Kim * we prefer the vmlinux path like 35500dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 35600dc8657SNamhyung Kim * 35700dc8657SNamhyung Kim * rather than build-id path (in debug directory). 35800dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 35900dc8657SNamhyung Kim */ 36000dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 36100dc8657SNamhyung Kim 362b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3636122e4e4SArnaldo Carvalho de Melo } 3646122e4e4SArnaldo Carvalho de Melo 3658115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 366a1645ce1SZhang, Yanmin { 367a1645ce1SZhang, Yanmin int err; 36845694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 369a1645ce1SZhang, Yanmin /* 370a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 371a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 372a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 373a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 374a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 375a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 376a1645ce1SZhang, Yanmin */ 37745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 378743eb868SArnaldo Carvalho de Melo machine); 379a1645ce1SZhang, Yanmin if (err < 0) 380a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 38123346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 382a1645ce1SZhang, Yanmin 383a1645ce1SZhang, Yanmin /* 384a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 385a1645ce1SZhang, Yanmin * have no _text sometimes. 386a1645ce1SZhang, Yanmin */ 38745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 3880ae617beSAdrian Hunter machine); 389a1645ce1SZhang, Yanmin if (err < 0) 390a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 39123346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 392a1645ce1SZhang, Yanmin } 393a1645ce1SZhang, Yanmin 39498402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 39598402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 39698402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 39798402807SFrederic Weisbecker }; 39898402807SFrederic Weisbecker 3998c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 40098402807SFrederic Weisbecker { 401dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4020e2e63ddSPeter Zijlstra int i; 4038d3eca20SDavid Ahern int rc = 0; 40498402807SFrederic Weisbecker 405d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 406ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 407ef149c25SAdrian Hunter 4088d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 409e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4108d3eca20SDavid Ahern rc = -1; 4118d3eca20SDavid Ahern goto out; 4128d3eca20SDavid Ahern } 4138d3eca20SDavid Ahern } 414ef149c25SAdrian Hunter 4152dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 416ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 417ef149c25SAdrian Hunter rc = -1; 418ef149c25SAdrian Hunter goto out; 419ef149c25SAdrian Hunter } 42098402807SFrederic Weisbecker } 42198402807SFrederic Weisbecker 422dcabb507SJiri Olsa /* 423dcabb507SJiri Olsa * Mark the round finished in case we wrote 424dcabb507SJiri Olsa * at least one event. 425dcabb507SJiri Olsa */ 426dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4278c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4288d3eca20SDavid Ahern 4298d3eca20SDavid Ahern out: 4308d3eca20SDavid Ahern return rc; 43198402807SFrederic Weisbecker } 43298402807SFrederic Weisbecker 4338c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 43457706abcSDavid Ahern { 43557706abcSDavid Ahern struct perf_session *session = rec->session; 43657706abcSDavid Ahern int feat; 43757706abcSDavid Ahern 43857706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 43957706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 44057706abcSDavid Ahern 44157706abcSDavid Ahern if (rec->no_buildid) 44257706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 44357706abcSDavid Ahern 4443e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 44557706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 44657706abcSDavid Ahern 44757706abcSDavid Ahern if (!rec->opts.branch_stack) 44857706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 449ef149c25SAdrian Hunter 450ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 451ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 45257706abcSDavid Ahern } 45357706abcSDavid Ahern 454f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 455f33cbe72SArnaldo Carvalho de Melo 456f33cbe72SArnaldo Carvalho de Melo /* 457f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 458f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 459f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 460f33cbe72SArnaldo Carvalho de Melo */ 46145604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 46245604710SNamhyung Kim siginfo_t *info, 463f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 464f33cbe72SArnaldo Carvalho de Melo { 465f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 466f33cbe72SArnaldo Carvalho de Melo done = 1; 467f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 468f33cbe72SArnaldo Carvalho de Melo } 469f33cbe72SArnaldo Carvalho de Melo 4702dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 4712dd6d8a1SAdrian Hunter 4728c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 47386470930SIngo Molnar { 47457706abcSDavid Ahern int err; 47545604710SNamhyung Kim int status = 0; 4768b412664SPeter Zijlstra unsigned long waking = 0; 47746be604bSZhang, Yanmin const bool forks = argc > 0; 47823346f21SArnaldo Carvalho de Melo struct machine *machine; 47945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 480b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 481f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 482d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 4836dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 48442aa276fSNamhyung Kim int fd; 48586470930SIngo Molnar 486d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 48733e49ea7SAndi Kleen 48845604710SNamhyung Kim atexit(record__sig_exit); 489f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 490f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 491804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 4922dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 4932dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 4942dd6d8a1SAdrian Hunter else 4952dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 496f5970550SPeter Zijlstra 497b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 49894c744b6SArnaldo Carvalho de Melo if (session == NULL) { 499ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 500a9a70bbcSArnaldo Carvalho de Melo return -1; 501a9a70bbcSArnaldo Carvalho de Melo } 502a9a70bbcSArnaldo Carvalho de Melo 50342aa276fSNamhyung Kim fd = perf_data_file__fd(file); 504d20deb64SArnaldo Carvalho de Melo rec->session = session; 505d20deb64SArnaldo Carvalho de Melo 5068c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 507330aa675SStephane Eranian 508d4db3f16SArnaldo Carvalho de Melo if (forks) { 5093e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 510f5fc1412SJiri Olsa argv, file->is_pipe, 511735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 51235b9d88eSArnaldo Carvalho de Melo if (err < 0) { 51335b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 51445604710SNamhyung Kim status = err; 51535b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 516856e9660SPeter Zijlstra } 517856e9660SPeter Zijlstra } 518856e9660SPeter Zijlstra 5198c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 5208d3eca20SDavid Ahern err = -1; 52145604710SNamhyung Kim goto out_child; 5228d3eca20SDavid Ahern } 52386470930SIngo Molnar 5243e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 525a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 526a8bb559bSNamhyung Kim 527f5fc1412SJiri Olsa if (file->is_pipe) { 52842aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 529529870e3STom Zanussi if (err < 0) 53045604710SNamhyung Kim goto out_child; 531563aecb2SJiri Olsa } else { 53242aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 533d5eed904SArnaldo Carvalho de Melo if (err < 0) 53445604710SNamhyung Kim goto out_child; 535d5eed904SArnaldo Carvalho de Melo } 5367c6a1c65SPeter Zijlstra 537d3665498SDavid Ahern if (!rec->no_buildid 538e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 539d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 540e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5418d3eca20SDavid Ahern err = -1; 54245604710SNamhyung Kim goto out_child; 543e20960c0SRobert Richter } 544e20960c0SRobert Richter 54534ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 546743eb868SArnaldo Carvalho de Melo 547f5fc1412SJiri Olsa if (file->is_pipe) { 54845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 549a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5502c46dbb5STom Zanussi if (err < 0) { 5512c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 55245604710SNamhyung Kim goto out_child; 5532c46dbb5STom Zanussi } 554cd19a035STom Zanussi 5553e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 55663e0c771STom Zanussi /* 55763e0c771STom Zanussi * FIXME err <= 0 here actually means that 55863e0c771STom Zanussi * there were no tracepoints so its not really 55963e0c771STom Zanussi * an error, just that we don't need to 56063e0c771STom Zanussi * synthesize anything. We really have to 56163e0c771STom Zanussi * return this more properly and also 56263e0c771STom Zanussi * propagate errors that now are calling die() 56363e0c771STom Zanussi */ 56442aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 565743eb868SArnaldo Carvalho de Melo process_synthesized_event); 56663e0c771STom Zanussi if (err <= 0) { 56763e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 56845604710SNamhyung Kim goto out_child; 56963e0c771STom Zanussi } 570f34b9001SDavid Ahern rec->bytes_written += err; 5712c46dbb5STom Zanussi } 57263e0c771STom Zanussi } 5732c46dbb5STom Zanussi 574ef149c25SAdrian Hunter if (rec->opts.full_auxtrace) { 575ef149c25SAdrian Hunter err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 576ef149c25SAdrian Hunter session, process_synthesized_event); 577ef149c25SAdrian Hunter if (err) 578ef149c25SAdrian Hunter goto out_delete_session; 579ef149c25SAdrian Hunter } 580ef149c25SAdrian Hunter 58145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 5820ae617beSAdrian Hunter machine); 583c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 584c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 585c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 586c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 58756b03f3cSArnaldo Carvalho de Melo 58845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 589743eb868SArnaldo Carvalho de Melo machine); 590c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 591c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 592c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 593c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 594c1a3a4b9SArnaldo Carvalho de Melo 5957e383de4SArnaldo Carvalho de Melo if (perf_guest) { 596876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 5977e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 5987e383de4SArnaldo Carvalho de Melo } 599b7cece76SArnaldo Carvalho de Melo 6003e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 6019d9cad76SKan Liang process_synthesized_event, opts->sample_address, 6029d9cad76SKan Liang opts->proc_map_timeout); 6038d3eca20SDavid Ahern if (err != 0) 60445604710SNamhyung Kim goto out_child; 6058d3eca20SDavid Ahern 606d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 60786470930SIngo Molnar struct sched_param param; 60886470930SIngo Molnar 609d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 61086470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6116beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6128d3eca20SDavid Ahern err = -1; 61345604710SNamhyung Kim goto out_child; 61486470930SIngo Molnar } 61586470930SIngo Molnar } 61686470930SIngo Molnar 617774cb499SJiri Olsa /* 618774cb499SJiri Olsa * When perf is starting the traced process, all the events 619774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 620774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 621774cb499SJiri Olsa */ 6226619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 6233e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 624764e16a3SDavid Ahern 625856e9660SPeter Zijlstra /* 626856e9660SPeter Zijlstra * Let the child rip 627856e9660SPeter Zijlstra */ 628735f7e0bSArnaldo Carvalho de Melo if (forks) 6293e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 630856e9660SPeter Zijlstra 6316619a53eSAndi Kleen if (opts->initial_delay) { 6326619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 6336619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 6346619a53eSAndi Kleen } 6356619a53eSAndi Kleen 6362dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 637649c48a9SPeter Zijlstra for (;;) { 638d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 63986470930SIngo Molnar 6408c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 6412dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6428d3eca20SDavid Ahern err = -1; 64345604710SNamhyung Kim goto out_child; 6448d3eca20SDavid Ahern } 64586470930SIngo Molnar 6462dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 6472dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 6482dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 6492dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 6502dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 6512dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 6522dd6d8a1SAdrian Hunter err = -1; 6532dd6d8a1SAdrian Hunter goto out_child; 6542dd6d8a1SAdrian Hunter } 6552dd6d8a1SAdrian Hunter } 6562dd6d8a1SAdrian Hunter 657d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 6586dcf45efSArnaldo Carvalho de Melo if (done || draining) 659649c48a9SPeter Zijlstra break; 660f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 661a515114fSJiri Olsa /* 662a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 663a515114fSJiri Olsa * number of returned events and interrupt error. 664a515114fSJiri Olsa */ 665a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 66645604710SNamhyung Kim err = 0; 6678b412664SPeter Zijlstra waking++; 6686dcf45efSArnaldo Carvalho de Melo 6696dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 6706dcf45efSArnaldo Carvalho de Melo draining = true; 6718b412664SPeter Zijlstra } 6728b412664SPeter Zijlstra 673774cb499SJiri Olsa /* 674774cb499SJiri Olsa * When perf is starting the traced process, at the end events 675774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 676774cb499SJiri Olsa * disable events in this case. 677774cb499SJiri Olsa */ 678602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 6792dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6803e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 6812711926aSJiri Olsa disabled = true; 6822711926aSJiri Olsa } 6838b412664SPeter Zijlstra } 6842dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6858b412664SPeter Zijlstra 686f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 68735550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 688f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 689f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 690f33cbe72SArnaldo Carvalho de Melo err = -1; 69145604710SNamhyung Kim goto out_child; 692f33cbe72SArnaldo Carvalho de Melo } 693f33cbe72SArnaldo Carvalho de Melo 694e3d59112SNamhyung Kim if (!quiet) 6958b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 69686470930SIngo Molnar 69745604710SNamhyung Kim out_child: 69845604710SNamhyung Kim if (forks) { 69945604710SNamhyung Kim int exit_status; 70045604710SNamhyung Kim 70145604710SNamhyung Kim if (!child_finished) 70245604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 70345604710SNamhyung Kim 70445604710SNamhyung Kim wait(&exit_status); 70545604710SNamhyung Kim 70645604710SNamhyung Kim if (err < 0) 70745604710SNamhyung Kim status = err; 70845604710SNamhyung Kim else if (WIFEXITED(exit_status)) 70945604710SNamhyung Kim status = WEXITSTATUS(exit_status); 71045604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 71145604710SNamhyung Kim signr = WTERMSIG(exit_status); 71245604710SNamhyung Kim } else 71345604710SNamhyung Kim status = err; 71445604710SNamhyung Kim 715e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 716e3d59112SNamhyung Kim rec->samples = 0; 717e3d59112SNamhyung Kim 71845604710SNamhyung Kim if (!err && !file->is_pipe) { 71945604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 720457ae94aSHe Kuang file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 72145604710SNamhyung Kim 722cd10b289SAdrian Hunter if (!rec->no_buildid) { 72345604710SNamhyung Kim process_buildids(rec); 724cd10b289SAdrian Hunter /* 725cd10b289SAdrian Hunter * We take all buildids when the file contains 726cd10b289SAdrian Hunter * AUX area tracing data because we do not decode the 727cd10b289SAdrian Hunter * trace because it would take too long. 728cd10b289SAdrian Hunter */ 729cd10b289SAdrian Hunter if (rec->opts.full_auxtrace) 730cd10b289SAdrian Hunter dsos__hit_all(rec->session); 731cd10b289SAdrian Hunter } 73242aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 73345604710SNamhyung Kim } 73439d17dacSArnaldo Carvalho de Melo 735e3d59112SNamhyung Kim if (!err && !quiet) { 736e3d59112SNamhyung Kim char samples[128]; 737e3d59112SNamhyung Kim 738ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 739e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 740e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 741e3d59112SNamhyung Kim else 742e3d59112SNamhyung Kim samples[0] = '\0'; 743e3d59112SNamhyung Kim 744e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 745e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 746e3d59112SNamhyung Kim file->path, samples); 747e3d59112SNamhyung Kim } 748e3d59112SNamhyung Kim 74939d17dacSArnaldo Carvalho de Melo out_delete_session: 75039d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 75145604710SNamhyung Kim return status; 75286470930SIngo Molnar } 75386470930SIngo Molnar 75472a128aaSNamhyung Kim static void callchain_debug(void) 75509b0fd45SJiri Olsa { 756aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 757a601fdffSJiri Olsa 75872a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 75926d33022SJiri Olsa 76072a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 76109b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 76272a128aaSNamhyung Kim callchain_param.dump_size); 76309b0fd45SJiri Olsa } 76409b0fd45SJiri Olsa 765c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 76609b0fd45SJiri Olsa const char *arg, 76709b0fd45SJiri Olsa int unset) 76809b0fd45SJiri Olsa { 76909b0fd45SJiri Olsa int ret; 770c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 77109b0fd45SJiri Olsa 772c421e80bSKan Liang record->callgraph_set = true; 77372a128aaSNamhyung Kim callchain_param.enabled = !unset; 774eb853e80SJiri Olsa 77509b0fd45SJiri Olsa /* --no-call-graph */ 77609b0fd45SJiri Olsa if (unset) { 77772a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 77809b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 77909b0fd45SJiri Olsa return 0; 78009b0fd45SJiri Olsa } 78109b0fd45SJiri Olsa 782*c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 78309b0fd45SJiri Olsa if (!ret) 78472a128aaSNamhyung Kim callchain_debug(); 78509b0fd45SJiri Olsa 78626d33022SJiri Olsa return ret; 78726d33022SJiri Olsa } 78826d33022SJiri Olsa 789c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 79009b0fd45SJiri Olsa const char *arg __maybe_unused, 79109b0fd45SJiri Olsa int unset __maybe_unused) 79209b0fd45SJiri Olsa { 793c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 794c421e80bSKan Liang 795c421e80bSKan Liang record->callgraph_set = true; 79672a128aaSNamhyung Kim callchain_param.enabled = true; 79709b0fd45SJiri Olsa 79872a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 79972a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 800eb853e80SJiri Olsa 80172a128aaSNamhyung Kim callchain_debug(); 80209b0fd45SJiri Olsa return 0; 80309b0fd45SJiri Olsa } 80409b0fd45SJiri Olsa 805eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 806eb853e80SJiri Olsa { 807eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 8085a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 809eb853e80SJiri Olsa 810eb853e80SJiri Olsa return perf_default_config(var, value, cb); 811eb853e80SJiri Olsa } 812eb853e80SJiri Olsa 813814c8c38SPeter Zijlstra struct clockid_map { 814814c8c38SPeter Zijlstra const char *name; 815814c8c38SPeter Zijlstra int clockid; 816814c8c38SPeter Zijlstra }; 817814c8c38SPeter Zijlstra 818814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 819814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 820814c8c38SPeter Zijlstra 821814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 822814c8c38SPeter Zijlstra 823814c8c38SPeter Zijlstra 824814c8c38SPeter Zijlstra /* 825814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 826814c8c38SPeter Zijlstra */ 827814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 828814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 829814c8c38SPeter Zijlstra #endif 830814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 831814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 832814c8c38SPeter Zijlstra #endif 833814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 834814c8c38SPeter Zijlstra #define CLOCK_TAI 11 835814c8c38SPeter Zijlstra #endif 836814c8c38SPeter Zijlstra 837814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 838814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 839814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 840814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 841814c8c38SPeter Zijlstra 842814c8c38SPeter Zijlstra /* available for some events */ 843814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 844814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 845814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 846814c8c38SPeter Zijlstra 847814c8c38SPeter Zijlstra /* available for the lazy */ 848814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 849814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 850814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 851814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 852814c8c38SPeter Zijlstra 853814c8c38SPeter Zijlstra CLOCKID_END, 854814c8c38SPeter Zijlstra }; 855814c8c38SPeter Zijlstra 856814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 857814c8c38SPeter Zijlstra { 858814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 859814c8c38SPeter Zijlstra const struct clockid_map *cm; 860814c8c38SPeter Zijlstra const char *ostr = str; 861814c8c38SPeter Zijlstra 862814c8c38SPeter Zijlstra if (unset) { 863814c8c38SPeter Zijlstra opts->use_clockid = 0; 864814c8c38SPeter Zijlstra return 0; 865814c8c38SPeter Zijlstra } 866814c8c38SPeter Zijlstra 867814c8c38SPeter Zijlstra /* no arg passed */ 868814c8c38SPeter Zijlstra if (!str) 869814c8c38SPeter Zijlstra return 0; 870814c8c38SPeter Zijlstra 871814c8c38SPeter Zijlstra /* no setting it twice */ 872814c8c38SPeter Zijlstra if (opts->use_clockid) 873814c8c38SPeter Zijlstra return -1; 874814c8c38SPeter Zijlstra 875814c8c38SPeter Zijlstra opts->use_clockid = true; 876814c8c38SPeter Zijlstra 877814c8c38SPeter Zijlstra /* if its a number, we're done */ 878814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 879814c8c38SPeter Zijlstra return 0; 880814c8c38SPeter Zijlstra 881814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 882814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 883814c8c38SPeter Zijlstra str += 6; 884814c8c38SPeter Zijlstra 885814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 886814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 887814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 888814c8c38SPeter Zijlstra return 0; 889814c8c38SPeter Zijlstra } 890814c8c38SPeter Zijlstra } 891814c8c38SPeter Zijlstra 892814c8c38SPeter Zijlstra opts->use_clockid = false; 893814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 894814c8c38SPeter Zijlstra return -1; 895814c8c38SPeter Zijlstra } 896814c8c38SPeter Zijlstra 897e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 898e9db1310SAdrian Hunter const char *str, 899e9db1310SAdrian Hunter int unset __maybe_unused) 900e9db1310SAdrian Hunter { 901e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 902e9db1310SAdrian Hunter char *s, *p; 903e9db1310SAdrian Hunter unsigned int mmap_pages; 904e9db1310SAdrian Hunter int ret; 905e9db1310SAdrian Hunter 906e9db1310SAdrian Hunter if (!str) 907e9db1310SAdrian Hunter return -EINVAL; 908e9db1310SAdrian Hunter 909e9db1310SAdrian Hunter s = strdup(str); 910e9db1310SAdrian Hunter if (!s) 911e9db1310SAdrian Hunter return -ENOMEM; 912e9db1310SAdrian Hunter 913e9db1310SAdrian Hunter p = strchr(s, ','); 914e9db1310SAdrian Hunter if (p) 915e9db1310SAdrian Hunter *p = '\0'; 916e9db1310SAdrian Hunter 917e9db1310SAdrian Hunter if (*s) { 918e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 919e9db1310SAdrian Hunter if (ret) 920e9db1310SAdrian Hunter goto out_free; 921e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 922e9db1310SAdrian Hunter } 923e9db1310SAdrian Hunter 924e9db1310SAdrian Hunter if (!p) { 925e9db1310SAdrian Hunter ret = 0; 926e9db1310SAdrian Hunter goto out_free; 927e9db1310SAdrian Hunter } 928e9db1310SAdrian Hunter 929e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 930e9db1310SAdrian Hunter if (ret) 931e9db1310SAdrian Hunter goto out_free; 932e9db1310SAdrian Hunter 933e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 934e9db1310SAdrian Hunter 935e9db1310SAdrian Hunter out_free: 936e9db1310SAdrian Hunter free(s); 937e9db1310SAdrian Hunter return ret; 938e9db1310SAdrian Hunter } 939e9db1310SAdrian Hunter 940e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 94186470930SIngo Molnar "perf record [<options>] [<command>]", 94286470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 94386470930SIngo Molnar NULL 94486470930SIngo Molnar }; 945e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 94686470930SIngo Molnar 947d20deb64SArnaldo Carvalho de Melo /* 9488c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 9498c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 950d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 951d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 952d20deb64SArnaldo Carvalho de Melo * 953d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 954d20deb64SArnaldo Carvalho de Melo * 955d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 956d20deb64SArnaldo Carvalho de Melo */ 9578c6f45a7SArnaldo Carvalho de Melo static struct record record = { 958d20deb64SArnaldo Carvalho de Melo .opts = { 9598affc2b8SAndi Kleen .sample_time = true, 960d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 961d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 962d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 963447a6013SArnaldo Carvalho de Melo .freq = 4000, 964d1cb9fceSNamhyung Kim .target = { 965d1cb9fceSNamhyung Kim .uses_mmap = true, 9663aa5939dSAdrian Hunter .default_per_cpu = true, 967d1cb9fceSNamhyung Kim }, 9689d9cad76SKan Liang .proc_map_timeout = 500, 969d20deb64SArnaldo Carvalho de Melo }, 970e3d59112SNamhyung Kim .tool = { 971e3d59112SNamhyung Kim .sample = process_sample_event, 972e3d59112SNamhyung Kim .fork = perf_event__process_fork, 973e3d59112SNamhyung Kim .comm = perf_event__process_comm, 974e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 975e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 976e3d59112SNamhyung Kim }, 977d20deb64SArnaldo Carvalho de Melo }; 9787865e817SFrederic Weisbecker 97909b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 98061eaa3beSArnaldo Carvalho de Melo 9819ff125d1SJiri Olsa #ifdef HAVE_DWARF_UNWIND_SUPPORT 982aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr"; 98361eaa3beSArnaldo Carvalho de Melo #else 984aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr"; 98561eaa3beSArnaldo Carvalho de Melo #endif 98661eaa3beSArnaldo Carvalho de Melo 987d20deb64SArnaldo Carvalho de Melo /* 988d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 989d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 990b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 991d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 992d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 993d20deb64SArnaldo Carvalho de Melo */ 994e5b2c207SNamhyung Kim struct option __record_options[] = { 995d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 99686470930SIngo Molnar "event selector. use 'perf list' to list available events", 997f120f9d5SJiri Olsa parse_events_option), 998d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 999c171b552SLi Zefan "event filter", parse_filter), 10004ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 10014ba1faa1SWang Nan NULL, "don't record events from perf itself", 10024ba1faa1SWang Nan exclude_perf), 1003bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1004d6d901c2SZhang, Yanmin "record events on existing process id"), 1005bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1006d6d901c2SZhang, Yanmin "record events on existing thread id"), 1007d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 100886470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1009509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1010acac03faSKirill Smelkov "collect data without buffering"), 1011d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1012daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1013bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 101486470930SIngo Molnar "system-wide collection from all CPUs"), 1015bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1016c45c6ea2SStephane Eranian "list of cpus to monitor"), 1017d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1018f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 101986470930SIngo Molnar "output file name"), 102069e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 102169e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 10222e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1023d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1024e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1025e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1026e9db1310SAdrian Hunter record__parse_mmap_pages), 1027d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 102843bece79SLin Ming "put the counters into a counter group"), 102909b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 103009b0fd45SJiri Olsa NULL, "enables call-graph recording" , 103109b0fd45SJiri Olsa &record_callchain_opt), 103209b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 103375d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 103409b0fd45SJiri Olsa &record_parse_callchain_opt), 1035c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 10363da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1037b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1038d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1039649c48a9SPeter Zijlstra "per thread counts"), 104056100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 10413abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 10423abebc55SAdrian Hunter &record.opts.sample_time_set, 10433abebc55SAdrian Hunter "Record the sample timestamps"), 104456100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1045d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1046649c48a9SPeter Zijlstra "don't sample"), 1047d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1048a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1049d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 1050baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1051d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1052023695d9SStephane Eranian "monitor event in cgroup name only", 1053023695d9SStephane Eranian parse_cgroups), 1054a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 10556619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1056bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1057bea03405SNamhyung Kim "user to profile"), 1058a5aabdacSStephane Eranian 1059a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1060a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1061a5aabdacSStephane Eranian parse_branch_stack), 1062a5aabdacSStephane Eranian 1063a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1064a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1065bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 106605484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 106705484298SAndi Kleen "sample by weight (on special events only)"), 1068475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1069475eeab9SAndi Kleen "sample transaction flags (special events only)"), 10703aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 10713aa5939dSAdrian Hunter "use per-thread mmaps"), 10724b6c5177SStephane Eranian OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, 10734b6c5177SStephane Eranian "Sample machine registers on interrupt"), 107485c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 107585c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1076814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1077814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1078814c8c38SPeter Zijlstra parse_clockid), 10792dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 10802dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 10819d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 10829d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1083b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1084b757bb09SAdrian Hunter "Record context switch events"), 108586470930SIngo Molnar OPT_END() 108686470930SIngo Molnar }; 108786470930SIngo Molnar 1088e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1089e5b2c207SNamhyung Kim 10901d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 109186470930SIngo Molnar { 1092ef149c25SAdrian Hunter int err; 10938c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 109416ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 109586470930SIngo Molnar 10963e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 10973e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1098361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1099361c99a6SArnaldo Carvalho de Melo 1100eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1101eb853e80SJiri Olsa 1102bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1103a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1104602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1105bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 110686470930SIngo Molnar 1107bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 11083780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 1109023695d9SStephane Eranian " system-wide mode\n"); 1110023695d9SStephane Eranian usage_with_options(record_usage, record_options); 1111023695d9SStephane Eranian } 1112b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1113b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1114b757bb09SAdrian Hunter ui__error("kernel does not support recording context switch events (--switch-events option)\n"); 1115b757bb09SAdrian Hunter usage_with_options(record_usage, record_options); 1116b757bb09SAdrian Hunter } 1117023695d9SStephane Eranian 1118ef149c25SAdrian Hunter if (!rec->itr) { 1119ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1120ef149c25SAdrian Hunter if (err) 1121ef149c25SAdrian Hunter return err; 1122ef149c25SAdrian Hunter } 1123ef149c25SAdrian Hunter 11242dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 11252dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 11262dd6d8a1SAdrian Hunter if (err) 11272dd6d8a1SAdrian Hunter return err; 11282dd6d8a1SAdrian Hunter 1129ef149c25SAdrian Hunter err = -ENOMEM; 1130ef149c25SAdrian Hunter 11310a7e6d1bSNamhyung Kim symbol__init(NULL); 1132baa2f6ceSArnaldo Carvalho de Melo 1133ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1134646aaea6SArnaldo Carvalho de Melo pr_warning( 1135646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1136ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1137646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1138646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1139646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1140646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1141646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1142ec80fde7SArnaldo Carvalho de Melo 1143d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1144a1ac1d3cSStephane Eranian disable_buildid_cache(); 1145655000e7SArnaldo Carvalho de Melo 11463e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 11473e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 114869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 114969aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1150bbd36e5eSPeter Zijlstra } 115186470930SIngo Molnar 115269e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 115369e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 115469e7e5b0SAdrian Hunter 1155602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 115616ad2ffbSNamhyung Kim if (err) { 1157602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 115816ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 115916ad2ffbSNamhyung Kim } 11604bd0f2d2SNamhyung Kim 1161602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 116216ad2ffbSNamhyung Kim if (err) { 116316ad2ffbSNamhyung Kim int saved_errno = errno; 116416ad2ffbSNamhyung Kim 1165602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 11663780f488SNamhyung Kim ui__error("%s", errbuf); 116716ad2ffbSNamhyung Kim 116816ad2ffbSNamhyung Kim err = -saved_errno; 11698fa60e1fSNamhyung Kim goto out_symbol_exit; 117016ad2ffbSNamhyung Kim } 11710d37aa34SArnaldo Carvalho de Melo 117216ad2ffbSNamhyung Kim err = -ENOMEM; 11733e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1174dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 117569aad6f1SArnaldo Carvalho de Melo 1176ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1177ef149c25SAdrian Hunter if (err) 1178ef149c25SAdrian Hunter goto out_symbol_exit; 1179ef149c25SAdrian Hunter 1180b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 118139d17dacSArnaldo Carvalho de Melo err = -EINVAL; 118203ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 11837e4ff9e3SMike Galbraith } 11847e4ff9e3SMike Galbraith 1185d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1186d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 118745604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1188d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1189ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 119039d17dacSArnaldo Carvalho de Melo return err; 119186470930SIngo Molnar } 11922dd6d8a1SAdrian Hunter 11932dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 11942dd6d8a1SAdrian Hunter { 11952dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 11962dd6d8a1SAdrian Hunter return; 11972dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 11982dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 11992dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 12002dd6d8a1SAdrian Hunter } 1201