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" 347c6a1c65SPeter Zijlstra 3586470930SIngo Molnar #include <unistd.h> 3686470930SIngo Molnar #include <sched.h> 37a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3886470930SIngo Molnar 3978da39faSBernhard Rosenkraenzer 408c6f45a7SArnaldo Carvalho de Melo struct record { 4145694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 42b4006796SArnaldo Carvalho de Melo struct record_opts opts; 43d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 44f5fc1412SJiri Olsa struct perf_data_file file; 45ef149c25SAdrian Hunter struct auxtrace_record *itr; 46d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 47d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 48d20deb64SArnaldo Carvalho de Melo const char *progname; 49d20deb64SArnaldo Carvalho de Melo int realtime_prio; 50d20deb64SArnaldo Carvalho de Melo bool no_buildid; 51d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 52*9f065194SYang Shi unsigned long long samples; 530f82ebc4SArnaldo Carvalho de Melo }; 5486470930SIngo Molnar 558c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 56f5970550SPeter Zijlstra { 57cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 584f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 598d3eca20SDavid Ahern return -1; 608d3eca20SDavid Ahern } 61f5970550SPeter Zijlstra 62cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 638d3eca20SDavid Ahern return 0; 64f5970550SPeter Zijlstra } 65f5970550SPeter Zijlstra 6645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 67d20deb64SArnaldo Carvalho de Melo union perf_event *event, 681d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 691d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 70234fbbf5SArnaldo Carvalho de Melo { 718c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 728c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 73234fbbf5SArnaldo Carvalho de Melo } 74234fbbf5SArnaldo Carvalho de Melo 75e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 7686470930SIngo Molnar { 77e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 787b8283b5SDavid Ahern u64 head = perf_mmap__read_head(md); 797b8283b5SDavid Ahern u64 old = md->prev; 80918512b4SJiri Olsa unsigned char *data = md->base + page_size; 8186470930SIngo Molnar unsigned long size; 8286470930SIngo Molnar void *buf; 838d3eca20SDavid Ahern int rc = 0; 8486470930SIngo Molnar 85dc82009aSArnaldo Carvalho de Melo if (old == head) 868d3eca20SDavid Ahern return 0; 8786470930SIngo Molnar 88d20deb64SArnaldo Carvalho de Melo rec->samples++; 8986470930SIngo Molnar 9086470930SIngo Molnar size = head - old; 9186470930SIngo Molnar 9286470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 9386470930SIngo Molnar buf = &data[old & md->mask]; 9486470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 9586470930SIngo Molnar old += size; 9686470930SIngo Molnar 978c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 988d3eca20SDavid Ahern rc = -1; 998d3eca20SDavid Ahern goto out; 1008d3eca20SDavid Ahern } 10186470930SIngo Molnar } 10286470930SIngo Molnar 10386470930SIngo Molnar buf = &data[old & md->mask]; 10486470930SIngo Molnar size = head - old; 10586470930SIngo Molnar old += size; 10686470930SIngo Molnar 1078c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1088d3eca20SDavid Ahern rc = -1; 1098d3eca20SDavid Ahern goto out; 1108d3eca20SDavid Ahern } 11186470930SIngo Molnar 11286470930SIngo Molnar md->prev = old; 113e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1148d3eca20SDavid Ahern out: 1158d3eca20SDavid Ahern return rc; 11686470930SIngo Molnar } 11786470930SIngo Molnar 1182dd6d8a1SAdrian Hunter static volatile int done; 1192dd6d8a1SAdrian Hunter static volatile int signr = -1; 1202dd6d8a1SAdrian Hunter static volatile int child_finished; 1212dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_enabled; 1222dd6d8a1SAdrian Hunter static volatile int auxtrace_snapshot_err; 1232dd6d8a1SAdrian Hunter static volatile int auxtrace_record__snapshot_started; 1242dd6d8a1SAdrian Hunter 1252dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1262dd6d8a1SAdrian Hunter { 1272dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1282dd6d8a1SAdrian Hunter child_finished = 1; 1292dd6d8a1SAdrian Hunter else 1302dd6d8a1SAdrian Hunter signr = sig; 1312dd6d8a1SAdrian Hunter 1322dd6d8a1SAdrian Hunter done = 1; 1332dd6d8a1SAdrian Hunter } 1342dd6d8a1SAdrian Hunter 1352dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1362dd6d8a1SAdrian Hunter { 1372dd6d8a1SAdrian Hunter if (signr == -1) 1382dd6d8a1SAdrian Hunter return; 1392dd6d8a1SAdrian Hunter 1402dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1412dd6d8a1SAdrian Hunter raise(signr); 1422dd6d8a1SAdrian Hunter } 1432dd6d8a1SAdrian Hunter 144e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 145e31f0d01SAdrian Hunter 146ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 147ef149c25SAdrian Hunter union perf_event *event, void *data1, 148ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 149ef149c25SAdrian Hunter { 150ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 15199fa2984SAdrian Hunter struct perf_data_file *file = &rec->file; 152ef149c25SAdrian Hunter size_t padding; 153ef149c25SAdrian Hunter u8 pad[8] = {0}; 154ef149c25SAdrian Hunter 15599fa2984SAdrian Hunter if (!perf_data_file__is_pipe(file)) { 15699fa2984SAdrian Hunter off_t file_offset; 15799fa2984SAdrian Hunter int fd = perf_data_file__fd(file); 15899fa2984SAdrian Hunter int err; 15999fa2984SAdrian Hunter 16099fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 16199fa2984SAdrian Hunter if (file_offset == -1) 16299fa2984SAdrian Hunter return -1; 16399fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 16499fa2984SAdrian Hunter event, file_offset); 16599fa2984SAdrian Hunter if (err) 16699fa2984SAdrian Hunter return err; 16799fa2984SAdrian Hunter } 16899fa2984SAdrian Hunter 169ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 170ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 171ef149c25SAdrian Hunter if (padding) 172ef149c25SAdrian Hunter padding = 8 - padding; 173ef149c25SAdrian Hunter 174ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 175ef149c25SAdrian Hunter record__write(rec, data1, len1); 176ef149c25SAdrian Hunter if (len2) 177ef149c25SAdrian Hunter record__write(rec, data2, len2); 178ef149c25SAdrian Hunter record__write(rec, &pad, padding); 179ef149c25SAdrian Hunter 180ef149c25SAdrian Hunter return 0; 181ef149c25SAdrian Hunter } 182ef149c25SAdrian Hunter 183ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 184ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 185ef149c25SAdrian Hunter { 186ef149c25SAdrian Hunter int ret; 187ef149c25SAdrian Hunter 188ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 189ef149c25SAdrian Hunter record__process_auxtrace); 190ef149c25SAdrian Hunter if (ret < 0) 191ef149c25SAdrian Hunter return ret; 192ef149c25SAdrian Hunter 193ef149c25SAdrian Hunter if (ret) 194ef149c25SAdrian Hunter rec->samples++; 195ef149c25SAdrian Hunter 196ef149c25SAdrian Hunter return 0; 197ef149c25SAdrian Hunter } 198ef149c25SAdrian Hunter 1992dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2002dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2012dd6d8a1SAdrian Hunter { 2022dd6d8a1SAdrian Hunter int ret; 2032dd6d8a1SAdrian Hunter 2042dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2052dd6d8a1SAdrian Hunter record__process_auxtrace, 2062dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2072dd6d8a1SAdrian Hunter if (ret < 0) 2082dd6d8a1SAdrian Hunter return ret; 2092dd6d8a1SAdrian Hunter 2102dd6d8a1SAdrian Hunter if (ret) 2112dd6d8a1SAdrian Hunter rec->samples++; 2122dd6d8a1SAdrian Hunter 2132dd6d8a1SAdrian Hunter return 0; 2142dd6d8a1SAdrian Hunter } 2152dd6d8a1SAdrian Hunter 2162dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2172dd6d8a1SAdrian Hunter { 2182dd6d8a1SAdrian Hunter int i; 2192dd6d8a1SAdrian Hunter int rc = 0; 2202dd6d8a1SAdrian Hunter 2212dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2222dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2232dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2242dd6d8a1SAdrian Hunter 2252dd6d8a1SAdrian Hunter if (!mm->base) 2262dd6d8a1SAdrian Hunter continue; 2272dd6d8a1SAdrian Hunter 2282dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2292dd6d8a1SAdrian Hunter rc = -1; 2302dd6d8a1SAdrian Hunter goto out; 2312dd6d8a1SAdrian Hunter } 2322dd6d8a1SAdrian Hunter } 2332dd6d8a1SAdrian Hunter out: 2342dd6d8a1SAdrian Hunter return rc; 2352dd6d8a1SAdrian Hunter } 2362dd6d8a1SAdrian Hunter 2372dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2382dd6d8a1SAdrian Hunter { 2392dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2402dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2412dd6d8a1SAdrian Hunter auxtrace_snapshot_err = -1; 2422dd6d8a1SAdrian Hunter } else { 2432dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 2442dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 2452dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 2462dd6d8a1SAdrian Hunter } 2472dd6d8a1SAdrian Hunter } 2482dd6d8a1SAdrian Hunter 249e31f0d01SAdrian Hunter #else 250e31f0d01SAdrian Hunter 251e31f0d01SAdrian Hunter static inline 252e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 253e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 254e31f0d01SAdrian Hunter { 255e31f0d01SAdrian Hunter return 0; 256e31f0d01SAdrian Hunter } 257e31f0d01SAdrian Hunter 2582dd6d8a1SAdrian Hunter static inline 2592dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2602dd6d8a1SAdrian Hunter { 2612dd6d8a1SAdrian Hunter } 2622dd6d8a1SAdrian Hunter 2632dd6d8a1SAdrian Hunter static inline 2642dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2652dd6d8a1SAdrian Hunter { 2662dd6d8a1SAdrian Hunter return 0; 2672dd6d8a1SAdrian Hunter } 2682dd6d8a1SAdrian Hunter 269e31f0d01SAdrian Hunter #endif 270e31f0d01SAdrian Hunter 2718c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 272dd7927f4SArnaldo Carvalho de Melo { 27356e52e85SArnaldo Carvalho de Melo char msg[512]; 2746a4bb04cSJiri Olsa struct perf_evsel *pos; 275d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 276d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 277b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 2788d3eca20SDavid Ahern int rc = 0; 279dd7927f4SArnaldo Carvalho de Melo 280f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 281cac21425SJiri Olsa 2820050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 2833da297a6SIngo Molnar try_again: 284d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 28556e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 2863da297a6SIngo Molnar if (verbose) 287c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 2883da297a6SIngo Molnar goto try_again; 2893da297a6SIngo Molnar } 290ca6a4258SDavid Ahern 29156e52e85SArnaldo Carvalho de Melo rc = -errno; 29256e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 29356e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 29456e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 2958d3eca20SDavid Ahern goto out; 2967c6a1c65SPeter Zijlstra } 2977c6a1c65SPeter Zijlstra } 2987c6a1c65SPeter Zijlstra 29923d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 30023d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 30123d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 30235550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3038d3eca20SDavid Ahern rc = -1; 3048d3eca20SDavid Ahern goto out; 3050a102479SFrederic Weisbecker } 3060a102479SFrederic Weisbecker 307ef149c25SAdrian Hunter if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 3082dd6d8a1SAdrian Hunter opts->auxtrace_mmap_pages, 3092dd6d8a1SAdrian Hunter opts->auxtrace_snapshot_mode) < 0) { 3108d3eca20SDavid Ahern if (errno == EPERM) { 3118d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 31218e60939SNelson Elhage "Consider increasing " 31318e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 31418e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 315ef149c25SAdrian Hunter "(current value: %u,%u)\n", 316ef149c25SAdrian Hunter opts->mmap_pages, opts->auxtrace_mmap_pages); 3178d3eca20SDavid Ahern rc = -errno; 3188d3eca20SDavid Ahern } else { 31935550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 32035550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 3218d3eca20SDavid Ahern rc = -errno; 3228d3eca20SDavid Ahern } 3238d3eca20SDavid Ahern goto out; 32418e60939SNelson Elhage } 3250a27d7f9SArnaldo Carvalho de Melo 326a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3277b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3288d3eca20SDavid Ahern out: 3298d3eca20SDavid Ahern return rc; 330a91e5431SArnaldo Carvalho de Melo } 331a91e5431SArnaldo Carvalho de Melo 332e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 333e3d59112SNamhyung Kim union perf_event *event, 334e3d59112SNamhyung Kim struct perf_sample *sample, 335e3d59112SNamhyung Kim struct perf_evsel *evsel, 336e3d59112SNamhyung Kim struct machine *machine) 337e3d59112SNamhyung Kim { 338e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 339e3d59112SNamhyung Kim 340e3d59112SNamhyung Kim rec->samples++; 341e3d59112SNamhyung Kim 342e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 343e3d59112SNamhyung Kim } 344e3d59112SNamhyung Kim 3458c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 3466122e4e4SArnaldo Carvalho de Melo { 347f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 348f5fc1412SJiri Olsa struct perf_session *session = rec->session; 3496122e4e4SArnaldo Carvalho de Melo 350457ae94aSHe Kuang if (file->size == 0) 3519f591fd7SArnaldo Carvalho de Melo return 0; 3529f591fd7SArnaldo Carvalho de Melo 35300dc8657SNamhyung Kim /* 35400dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 35500dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 35600dc8657SNamhyung Kim * we prefer the vmlinux path like 35700dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 35800dc8657SNamhyung Kim * 35900dc8657SNamhyung Kim * rather than build-id path (in debug directory). 36000dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 36100dc8657SNamhyung Kim */ 36200dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 36300dc8657SNamhyung Kim 364b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 3656122e4e4SArnaldo Carvalho de Melo } 3666122e4e4SArnaldo Carvalho de Melo 3678115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 368a1645ce1SZhang, Yanmin { 369a1645ce1SZhang, Yanmin int err; 37045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 371a1645ce1SZhang, Yanmin /* 372a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 373a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 374a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 375a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 376a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 377a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 378a1645ce1SZhang, Yanmin */ 37945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 380743eb868SArnaldo Carvalho de Melo machine); 381a1645ce1SZhang, Yanmin if (err < 0) 382a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 38323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 384a1645ce1SZhang, Yanmin 385a1645ce1SZhang, Yanmin /* 386a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 387a1645ce1SZhang, Yanmin * have no _text sometimes. 388a1645ce1SZhang, Yanmin */ 38945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 3900ae617beSAdrian Hunter machine); 391a1645ce1SZhang, Yanmin if (err < 0) 392a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 39323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 394a1645ce1SZhang, Yanmin } 395a1645ce1SZhang, Yanmin 39698402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 39798402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 39898402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 39998402807SFrederic Weisbecker }; 40098402807SFrederic Weisbecker 4018c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 40298402807SFrederic Weisbecker { 403dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4040e2e63ddSPeter Zijlstra int i; 4058d3eca20SDavid Ahern int rc = 0; 40698402807SFrederic Weisbecker 407d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 408ef149c25SAdrian Hunter struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 409ef149c25SAdrian Hunter 4108d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 411e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 4128d3eca20SDavid Ahern rc = -1; 4138d3eca20SDavid Ahern goto out; 4148d3eca20SDavid Ahern } 4158d3eca20SDavid Ahern } 416ef149c25SAdrian Hunter 4172dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 418ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 419ef149c25SAdrian Hunter rc = -1; 420ef149c25SAdrian Hunter goto out; 421ef149c25SAdrian Hunter } 42298402807SFrederic Weisbecker } 42398402807SFrederic Weisbecker 424dcabb507SJiri Olsa /* 425dcabb507SJiri Olsa * Mark the round finished in case we wrote 426dcabb507SJiri Olsa * at least one event. 427dcabb507SJiri Olsa */ 428dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 4298c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 4308d3eca20SDavid Ahern 4318d3eca20SDavid Ahern out: 4328d3eca20SDavid Ahern return rc; 43398402807SFrederic Weisbecker } 43498402807SFrederic Weisbecker 4358c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 43657706abcSDavid Ahern { 43757706abcSDavid Ahern struct perf_session *session = rec->session; 43857706abcSDavid Ahern int feat; 43957706abcSDavid Ahern 44057706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 44157706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 44257706abcSDavid Ahern 44357706abcSDavid Ahern if (rec->no_buildid) 44457706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 44557706abcSDavid Ahern 4463e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 44757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 44857706abcSDavid Ahern 44957706abcSDavid Ahern if (!rec->opts.branch_stack) 45057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 451ef149c25SAdrian Hunter 452ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 453ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 45457706abcSDavid Ahern } 45557706abcSDavid Ahern 456f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 457f33cbe72SArnaldo Carvalho de Melo 458f33cbe72SArnaldo Carvalho de Melo /* 459f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 460f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 461f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 462f33cbe72SArnaldo Carvalho de Melo */ 46345604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 46445604710SNamhyung Kim siginfo_t *info, 465f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 466f33cbe72SArnaldo Carvalho de Melo { 467f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 468f33cbe72SArnaldo Carvalho de Melo done = 1; 469f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 470f33cbe72SArnaldo Carvalho de Melo } 471f33cbe72SArnaldo Carvalho de Melo 4722dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 4732dd6d8a1SAdrian Hunter 4748c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 47586470930SIngo Molnar { 47657706abcSDavid Ahern int err; 47745604710SNamhyung Kim int status = 0; 4788b412664SPeter Zijlstra unsigned long waking = 0; 47946be604bSZhang, Yanmin const bool forks = argc > 0; 48023346f21SArnaldo Carvalho de Melo struct machine *machine; 48145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 482b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 483f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 484d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 4856dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 48642aa276fSNamhyung Kim int fd; 48786470930SIngo Molnar 488d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 48933e49ea7SAndi Kleen 49045604710SNamhyung Kim atexit(record__sig_exit); 491f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 492f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 493804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 4942dd6d8a1SAdrian Hunter if (rec->opts.auxtrace_snapshot_mode) 4952dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 4962dd6d8a1SAdrian Hunter else 4972dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 498f5970550SPeter Zijlstra 499b7b61cbeSArnaldo Carvalho de Melo session = perf_session__new(file, false, tool); 50094c744b6SArnaldo Carvalho de Melo if (session == NULL) { 501ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 502a9a70bbcSArnaldo Carvalho de Melo return -1; 503a9a70bbcSArnaldo Carvalho de Melo } 504a9a70bbcSArnaldo Carvalho de Melo 50542aa276fSNamhyung Kim fd = perf_data_file__fd(file); 506d20deb64SArnaldo Carvalho de Melo rec->session = session; 507d20deb64SArnaldo Carvalho de Melo 5088c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 509330aa675SStephane Eranian 510d4db3f16SArnaldo Carvalho de Melo if (forks) { 5113e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 512f5fc1412SJiri Olsa argv, file->is_pipe, 513735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 51435b9d88eSArnaldo Carvalho de Melo if (err < 0) { 51535b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 51645604710SNamhyung Kim status = err; 51735b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 518856e9660SPeter Zijlstra } 519856e9660SPeter Zijlstra } 520856e9660SPeter Zijlstra 5218c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 5228d3eca20SDavid Ahern err = -1; 52345604710SNamhyung Kim goto out_child; 5248d3eca20SDavid Ahern } 52586470930SIngo Molnar 526cca8482cSAdrian Hunter /* 527cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 528cca8482cSAdrian Hunter * evlist. 529cca8482cSAdrian Hunter */ 530cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 531cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 532cca8482cSAdrian Hunter rec->tool.ordered_events = false; 533cca8482cSAdrian Hunter } 534cca8482cSAdrian Hunter 5353e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 536a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 537a8bb559bSNamhyung Kim 538f5fc1412SJiri Olsa if (file->is_pipe) { 53942aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 540529870e3STom Zanussi if (err < 0) 54145604710SNamhyung Kim goto out_child; 542563aecb2SJiri Olsa } else { 54342aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 544d5eed904SArnaldo Carvalho de Melo if (err < 0) 54545604710SNamhyung Kim goto out_child; 546d5eed904SArnaldo Carvalho de Melo } 5477c6a1c65SPeter Zijlstra 548d3665498SDavid Ahern if (!rec->no_buildid 549e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 550d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 551e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 5528d3eca20SDavid Ahern err = -1; 55345604710SNamhyung Kim goto out_child; 554e20960c0SRobert Richter } 555e20960c0SRobert Richter 55634ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 557743eb868SArnaldo Carvalho de Melo 558f5fc1412SJiri Olsa if (file->is_pipe) { 55945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 560a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5612c46dbb5STom Zanussi if (err < 0) { 5622c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 56345604710SNamhyung Kim goto out_child; 5642c46dbb5STom Zanussi } 565cd19a035STom Zanussi 5663e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 56763e0c771STom Zanussi /* 56863e0c771STom Zanussi * FIXME err <= 0 here actually means that 56963e0c771STom Zanussi * there were no tracepoints so its not really 57063e0c771STom Zanussi * an error, just that we don't need to 57163e0c771STom Zanussi * synthesize anything. We really have to 57263e0c771STom Zanussi * return this more properly and also 57363e0c771STom Zanussi * propagate errors that now are calling die() 57463e0c771STom Zanussi */ 57542aa276fSNamhyung Kim err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 576743eb868SArnaldo Carvalho de Melo process_synthesized_event); 57763e0c771STom Zanussi if (err <= 0) { 57863e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 57945604710SNamhyung Kim goto out_child; 58063e0c771STom Zanussi } 581f34b9001SDavid Ahern rec->bytes_written += err; 5822c46dbb5STom Zanussi } 58363e0c771STom Zanussi } 5842c46dbb5STom Zanussi 585ef149c25SAdrian Hunter if (rec->opts.full_auxtrace) { 586ef149c25SAdrian Hunter err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 587ef149c25SAdrian Hunter session, process_synthesized_event); 588ef149c25SAdrian Hunter if (err) 589ef149c25SAdrian Hunter goto out_delete_session; 590ef149c25SAdrian Hunter } 591ef149c25SAdrian Hunter 59245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 5930ae617beSAdrian Hunter machine); 594c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 595c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 596c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 597c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 59856b03f3cSArnaldo Carvalho de Melo 59945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 600743eb868SArnaldo Carvalho de Melo machine); 601c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 602c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 603c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 604c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 605c1a3a4b9SArnaldo Carvalho de Melo 6067e383de4SArnaldo Carvalho de Melo if (perf_guest) { 607876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 6087e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 6097e383de4SArnaldo Carvalho de Melo } 610b7cece76SArnaldo Carvalho de Melo 6113e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 6129d9cad76SKan Liang process_synthesized_event, opts->sample_address, 6139d9cad76SKan Liang opts->proc_map_timeout); 6148d3eca20SDavid Ahern if (err != 0) 61545604710SNamhyung Kim goto out_child; 6168d3eca20SDavid Ahern 617d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 61886470930SIngo Molnar struct sched_param param; 61986470930SIngo Molnar 620d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 62186470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6226beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6238d3eca20SDavid Ahern err = -1; 62445604710SNamhyung Kim goto out_child; 62586470930SIngo Molnar } 62686470930SIngo Molnar } 62786470930SIngo Molnar 628774cb499SJiri Olsa /* 629774cb499SJiri Olsa * When perf is starting the traced process, all the events 630774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 631774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 632774cb499SJiri Olsa */ 6336619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 6343e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 635764e16a3SDavid Ahern 636856e9660SPeter Zijlstra /* 637856e9660SPeter Zijlstra * Let the child rip 638856e9660SPeter Zijlstra */ 639e803cf97SNamhyung Kim if (forks) { 640e5bed564SNamhyung Kim union perf_event *event; 641e5bed564SNamhyung Kim 642e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 643e5bed564SNamhyung Kim if (event == NULL) { 644e5bed564SNamhyung Kim err = -ENOMEM; 645e5bed564SNamhyung Kim goto out_child; 646e5bed564SNamhyung Kim } 647e5bed564SNamhyung Kim 648e803cf97SNamhyung Kim /* 649e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 650e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 651e803cf97SNamhyung Kim * cannot see a correct process name for those events. 652e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 653e803cf97SNamhyung Kim */ 654e5bed564SNamhyung Kim perf_event__synthesize_comm(tool, event, 655e803cf97SNamhyung Kim rec->evlist->workload.pid, 656e803cf97SNamhyung Kim process_synthesized_event, 657e803cf97SNamhyung Kim machine); 658e5bed564SNamhyung Kim free(event); 659e803cf97SNamhyung Kim 6603e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 661e803cf97SNamhyung Kim } 662856e9660SPeter Zijlstra 6636619a53eSAndi Kleen if (opts->initial_delay) { 6646619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 6656619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 6666619a53eSAndi Kleen } 6676619a53eSAndi Kleen 6682dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 1; 669649c48a9SPeter Zijlstra for (;;) { 670*9f065194SYang Shi unsigned long long hits = rec->samples; 67186470930SIngo Molnar 6728c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 6732dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 6748d3eca20SDavid Ahern err = -1; 67545604710SNamhyung Kim goto out_child; 6768d3eca20SDavid Ahern } 67786470930SIngo Molnar 6782dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 6792dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 6802dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_err) 6812dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 6822dd6d8a1SAdrian Hunter if (auxtrace_snapshot_err) { 6832dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 6842dd6d8a1SAdrian Hunter err = -1; 6852dd6d8a1SAdrian Hunter goto out_child; 6862dd6d8a1SAdrian Hunter } 6872dd6d8a1SAdrian Hunter } 6882dd6d8a1SAdrian Hunter 689d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 6906dcf45efSArnaldo Carvalho de Melo if (done || draining) 691649c48a9SPeter Zijlstra break; 692f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 693a515114fSJiri Olsa /* 694a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 695a515114fSJiri Olsa * number of returned events and interrupt error. 696a515114fSJiri Olsa */ 697a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 69845604710SNamhyung Kim err = 0; 6998b412664SPeter Zijlstra waking++; 7006dcf45efSArnaldo Carvalho de Melo 7016dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 7026dcf45efSArnaldo Carvalho de Melo draining = true; 7038b412664SPeter Zijlstra } 7048b412664SPeter Zijlstra 705774cb499SJiri Olsa /* 706774cb499SJiri Olsa * When perf is starting the traced process, at the end events 707774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 708774cb499SJiri Olsa * disable events in this case. 709774cb499SJiri Olsa */ 710602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 7112dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7123e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 7132711926aSJiri Olsa disabled = true; 7142711926aSJiri Olsa } 7158b412664SPeter Zijlstra } 7162dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 7178b412664SPeter Zijlstra 718f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 71935550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 720f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 721f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 722f33cbe72SArnaldo Carvalho de Melo err = -1; 72345604710SNamhyung Kim goto out_child; 724f33cbe72SArnaldo Carvalho de Melo } 725f33cbe72SArnaldo Carvalho de Melo 726e3d59112SNamhyung Kim if (!quiet) 7278b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 72886470930SIngo Molnar 72945604710SNamhyung Kim out_child: 73045604710SNamhyung Kim if (forks) { 73145604710SNamhyung Kim int exit_status; 73245604710SNamhyung Kim 73345604710SNamhyung Kim if (!child_finished) 73445604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 73545604710SNamhyung Kim 73645604710SNamhyung Kim wait(&exit_status); 73745604710SNamhyung Kim 73845604710SNamhyung Kim if (err < 0) 73945604710SNamhyung Kim status = err; 74045604710SNamhyung Kim else if (WIFEXITED(exit_status)) 74145604710SNamhyung Kim status = WEXITSTATUS(exit_status); 74245604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 74345604710SNamhyung Kim signr = WTERMSIG(exit_status); 74445604710SNamhyung Kim } else 74545604710SNamhyung Kim status = err; 74645604710SNamhyung Kim 747e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 748e3d59112SNamhyung Kim rec->samples = 0; 749e3d59112SNamhyung Kim 75045604710SNamhyung Kim if (!err && !file->is_pipe) { 75145604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 752457ae94aSHe Kuang file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); 75345604710SNamhyung Kim 754cd10b289SAdrian Hunter if (!rec->no_buildid) { 75545604710SNamhyung Kim process_buildids(rec); 756cd10b289SAdrian Hunter /* 757cd10b289SAdrian Hunter * We take all buildids when the file contains 758cd10b289SAdrian Hunter * AUX area tracing data because we do not decode the 759cd10b289SAdrian Hunter * trace because it would take too long. 760cd10b289SAdrian Hunter */ 761cd10b289SAdrian Hunter if (rec->opts.full_auxtrace) 762cd10b289SAdrian Hunter dsos__hit_all(rec->session); 763cd10b289SAdrian Hunter } 76442aa276fSNamhyung Kim perf_session__write_header(rec->session, rec->evlist, fd, true); 76545604710SNamhyung Kim } 76639d17dacSArnaldo Carvalho de Melo 767e3d59112SNamhyung Kim if (!err && !quiet) { 768e3d59112SNamhyung Kim char samples[128]; 769e3d59112SNamhyung Kim 770ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 771e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 772e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 773e3d59112SNamhyung Kim else 774e3d59112SNamhyung Kim samples[0] = '\0'; 775e3d59112SNamhyung Kim 776e3d59112SNamhyung Kim fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 777e3d59112SNamhyung Kim perf_data_file__size(file) / 1024.0 / 1024.0, 778e3d59112SNamhyung Kim file->path, samples); 779e3d59112SNamhyung Kim } 780e3d59112SNamhyung Kim 78139d17dacSArnaldo Carvalho de Melo out_delete_session: 78239d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 78345604710SNamhyung Kim return status; 78486470930SIngo Molnar } 78586470930SIngo Molnar 78672a128aaSNamhyung Kim static void callchain_debug(void) 78709b0fd45SJiri Olsa { 788aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 789a601fdffSJiri Olsa 79072a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 79126d33022SJiri Olsa 79272a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 79309b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 79472a128aaSNamhyung Kim callchain_param.dump_size); 79509b0fd45SJiri Olsa } 79609b0fd45SJiri Olsa 797c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 79809b0fd45SJiri Olsa const char *arg, 79909b0fd45SJiri Olsa int unset) 80009b0fd45SJiri Olsa { 80109b0fd45SJiri Olsa int ret; 802c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 80309b0fd45SJiri Olsa 804c421e80bSKan Liang record->callgraph_set = true; 80572a128aaSNamhyung Kim callchain_param.enabled = !unset; 806eb853e80SJiri Olsa 80709b0fd45SJiri Olsa /* --no-call-graph */ 80809b0fd45SJiri Olsa if (unset) { 80972a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 81009b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 81109b0fd45SJiri Olsa return 0; 81209b0fd45SJiri Olsa } 81309b0fd45SJiri Olsa 814c3a6a8c4SKan Liang ret = parse_callchain_record_opt(arg, &callchain_param); 81509b0fd45SJiri Olsa if (!ret) 81672a128aaSNamhyung Kim callchain_debug(); 81709b0fd45SJiri Olsa 81826d33022SJiri Olsa return ret; 81926d33022SJiri Olsa } 82026d33022SJiri Olsa 821c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 82209b0fd45SJiri Olsa const char *arg __maybe_unused, 82309b0fd45SJiri Olsa int unset __maybe_unused) 82409b0fd45SJiri Olsa { 825c421e80bSKan Liang struct record_opts *record = (struct record_opts *)opt->value; 826c421e80bSKan Liang 827c421e80bSKan Liang record->callgraph_set = true; 82872a128aaSNamhyung Kim callchain_param.enabled = true; 82909b0fd45SJiri Olsa 83072a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 83172a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 832eb853e80SJiri Olsa 83372a128aaSNamhyung Kim callchain_debug(); 83409b0fd45SJiri Olsa return 0; 83509b0fd45SJiri Olsa } 83609b0fd45SJiri Olsa 837eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 838eb853e80SJiri Olsa { 839eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 8405a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 841eb853e80SJiri Olsa 842eb853e80SJiri Olsa return perf_default_config(var, value, cb); 843eb853e80SJiri Olsa } 844eb853e80SJiri Olsa 845814c8c38SPeter Zijlstra struct clockid_map { 846814c8c38SPeter Zijlstra const char *name; 847814c8c38SPeter Zijlstra int clockid; 848814c8c38SPeter Zijlstra }; 849814c8c38SPeter Zijlstra 850814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 851814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 852814c8c38SPeter Zijlstra 853814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 854814c8c38SPeter Zijlstra 855814c8c38SPeter Zijlstra 856814c8c38SPeter Zijlstra /* 857814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 858814c8c38SPeter Zijlstra */ 859814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 860814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 861814c8c38SPeter Zijlstra #endif 862814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 863814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 864814c8c38SPeter Zijlstra #endif 865814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 866814c8c38SPeter Zijlstra #define CLOCK_TAI 11 867814c8c38SPeter Zijlstra #endif 868814c8c38SPeter Zijlstra 869814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 870814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 871814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 872814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 873814c8c38SPeter Zijlstra 874814c8c38SPeter Zijlstra /* available for some events */ 875814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 876814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 877814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 878814c8c38SPeter Zijlstra 879814c8c38SPeter Zijlstra /* available for the lazy */ 880814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 881814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 882814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 883814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 884814c8c38SPeter Zijlstra 885814c8c38SPeter Zijlstra CLOCKID_END, 886814c8c38SPeter Zijlstra }; 887814c8c38SPeter Zijlstra 888814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 889814c8c38SPeter Zijlstra { 890814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 891814c8c38SPeter Zijlstra const struct clockid_map *cm; 892814c8c38SPeter Zijlstra const char *ostr = str; 893814c8c38SPeter Zijlstra 894814c8c38SPeter Zijlstra if (unset) { 895814c8c38SPeter Zijlstra opts->use_clockid = 0; 896814c8c38SPeter Zijlstra return 0; 897814c8c38SPeter Zijlstra } 898814c8c38SPeter Zijlstra 899814c8c38SPeter Zijlstra /* no arg passed */ 900814c8c38SPeter Zijlstra if (!str) 901814c8c38SPeter Zijlstra return 0; 902814c8c38SPeter Zijlstra 903814c8c38SPeter Zijlstra /* no setting it twice */ 904814c8c38SPeter Zijlstra if (opts->use_clockid) 905814c8c38SPeter Zijlstra return -1; 906814c8c38SPeter Zijlstra 907814c8c38SPeter Zijlstra opts->use_clockid = true; 908814c8c38SPeter Zijlstra 909814c8c38SPeter Zijlstra /* if its a number, we're done */ 910814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 911814c8c38SPeter Zijlstra return 0; 912814c8c38SPeter Zijlstra 913814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 914814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 915814c8c38SPeter Zijlstra str += 6; 916814c8c38SPeter Zijlstra 917814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 918814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 919814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 920814c8c38SPeter Zijlstra return 0; 921814c8c38SPeter Zijlstra } 922814c8c38SPeter Zijlstra } 923814c8c38SPeter Zijlstra 924814c8c38SPeter Zijlstra opts->use_clockid = false; 925814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 926814c8c38SPeter Zijlstra return -1; 927814c8c38SPeter Zijlstra } 928814c8c38SPeter Zijlstra 929e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 930e9db1310SAdrian Hunter const char *str, 931e9db1310SAdrian Hunter int unset __maybe_unused) 932e9db1310SAdrian Hunter { 933e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 934e9db1310SAdrian Hunter char *s, *p; 935e9db1310SAdrian Hunter unsigned int mmap_pages; 936e9db1310SAdrian Hunter int ret; 937e9db1310SAdrian Hunter 938e9db1310SAdrian Hunter if (!str) 939e9db1310SAdrian Hunter return -EINVAL; 940e9db1310SAdrian Hunter 941e9db1310SAdrian Hunter s = strdup(str); 942e9db1310SAdrian Hunter if (!s) 943e9db1310SAdrian Hunter return -ENOMEM; 944e9db1310SAdrian Hunter 945e9db1310SAdrian Hunter p = strchr(s, ','); 946e9db1310SAdrian Hunter if (p) 947e9db1310SAdrian Hunter *p = '\0'; 948e9db1310SAdrian Hunter 949e9db1310SAdrian Hunter if (*s) { 950e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 951e9db1310SAdrian Hunter if (ret) 952e9db1310SAdrian Hunter goto out_free; 953e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 954e9db1310SAdrian Hunter } 955e9db1310SAdrian Hunter 956e9db1310SAdrian Hunter if (!p) { 957e9db1310SAdrian Hunter ret = 0; 958e9db1310SAdrian Hunter goto out_free; 959e9db1310SAdrian Hunter } 960e9db1310SAdrian Hunter 961e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 962e9db1310SAdrian Hunter if (ret) 963e9db1310SAdrian Hunter goto out_free; 964e9db1310SAdrian Hunter 965e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 966e9db1310SAdrian Hunter 967e9db1310SAdrian Hunter out_free: 968e9db1310SAdrian Hunter free(s); 969e9db1310SAdrian Hunter return ret; 970e9db1310SAdrian Hunter } 971e9db1310SAdrian Hunter 972e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 97386470930SIngo Molnar "perf record [<options>] [<command>]", 97486470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 97586470930SIngo Molnar NULL 97686470930SIngo Molnar }; 977e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 97886470930SIngo Molnar 979d20deb64SArnaldo Carvalho de Melo /* 9808c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 9818c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 982d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 983d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 984d20deb64SArnaldo Carvalho de Melo * 985d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 986d20deb64SArnaldo Carvalho de Melo * 987d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 988d20deb64SArnaldo Carvalho de Melo */ 9898c6f45a7SArnaldo Carvalho de Melo static struct record record = { 990d20deb64SArnaldo Carvalho de Melo .opts = { 9918affc2b8SAndi Kleen .sample_time = true, 992d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 993d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 994d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 995447a6013SArnaldo Carvalho de Melo .freq = 4000, 996d1cb9fceSNamhyung Kim .target = { 997d1cb9fceSNamhyung Kim .uses_mmap = true, 9983aa5939dSAdrian Hunter .default_per_cpu = true, 999d1cb9fceSNamhyung Kim }, 10009d9cad76SKan Liang .proc_map_timeout = 500, 1001d20deb64SArnaldo Carvalho de Melo }, 1002e3d59112SNamhyung Kim .tool = { 1003e3d59112SNamhyung Kim .sample = process_sample_event, 1004e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1005cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1006e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1007e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1008e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1009cca8482cSAdrian Hunter .ordered_events = true, 1010e3d59112SNamhyung Kim }, 1011d20deb64SArnaldo Carvalho de Melo }; 10127865e817SFrederic Weisbecker 101309b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 101461eaa3beSArnaldo Carvalho de Melo 10159ff125d1SJiri Olsa #ifdef HAVE_DWARF_UNWIND_SUPPORT 1016aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr"; 101761eaa3beSArnaldo Carvalho de Melo #else 1018aad2b21cSKan Liang const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr"; 101961eaa3beSArnaldo Carvalho de Melo #endif 102061eaa3beSArnaldo Carvalho de Melo 1021d20deb64SArnaldo Carvalho de Melo /* 1022d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1023d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1024b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1025d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1026d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1027d20deb64SArnaldo Carvalho de Melo */ 1028e5b2c207SNamhyung Kim struct option __record_options[] = { 1029d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 103086470930SIngo Molnar "event selector. use 'perf list' to list available events", 1031f120f9d5SJiri Olsa parse_events_option), 1032d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1033c171b552SLi Zefan "event filter", parse_filter), 10344ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 10354ba1faa1SWang Nan NULL, "don't record events from perf itself", 10364ba1faa1SWang Nan exclude_perf), 1037bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1038d6d901c2SZhang, Yanmin "record events on existing process id"), 1039bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1040d6d901c2SZhang, Yanmin "record events on existing thread id"), 1041d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 104286470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1043509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1044acac03faSKirill Smelkov "collect data without buffering"), 1045d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1046daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1047bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 104886470930SIngo Molnar "system-wide collection from all CPUs"), 1049bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1050c45c6ea2SStephane Eranian "list of cpus to monitor"), 1051d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1052f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 105386470930SIngo Molnar "output file name"), 105469e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 105569e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 10562e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1057d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1058e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1059e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1060e9db1310SAdrian Hunter record__parse_mmap_pages), 1061d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 106243bece79SLin Ming "put the counters into a counter group"), 106309b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 106409b0fd45SJiri Olsa NULL, "enables call-graph recording" , 106509b0fd45SJiri Olsa &record_callchain_opt), 106609b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 106775d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 106809b0fd45SJiri Olsa &record_parse_callchain_opt), 1069c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 10703da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1071b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1072d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1073649c48a9SPeter Zijlstra "per thread counts"), 107456100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 10753abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 10763abebc55SAdrian Hunter &record.opts.sample_time_set, 10773abebc55SAdrian Hunter "Record the sample timestamps"), 107856100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1079d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1080649c48a9SPeter Zijlstra "don't sample"), 1081d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1082a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1083d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 1084baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1085d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1086023695d9SStephane Eranian "monitor event in cgroup name only", 1087023695d9SStephane Eranian parse_cgroups), 1088a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 10896619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1090bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1091bea03405SNamhyung Kim "user to profile"), 1092a5aabdacSStephane Eranian 1093a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1094a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1095a5aabdacSStephane Eranian parse_branch_stack), 1096a5aabdacSStephane Eranian 1097a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1098a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1099bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 110005484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 110105484298SAndi Kleen "sample by weight (on special events only)"), 1102475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1103475eeab9SAndi Kleen "sample transaction flags (special events only)"), 11043aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 11053aa5939dSAdrian Hunter "use per-thread mmaps"), 1106bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1107bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1108bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 110985c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 111085c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1111814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1112814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1113814c8c38SPeter Zijlstra parse_clockid), 11142dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 11152dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 11169d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 11179d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1118b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1119b757bb09SAdrian Hunter "Record context switch events"), 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 11313e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 11323e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1133361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1134361c99a6SArnaldo Carvalho de Melo 1135eb853e80SJiri Olsa perf_config(perf_record_config, rec); 1136eb853e80SJiri Olsa 1137bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1138a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1139602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1140bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 114186470930SIngo Molnar 1142bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 11433780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 1144023695d9SStephane Eranian " system-wide mode\n"); 1145023695d9SStephane Eranian usage_with_options(record_usage, record_options); 1146023695d9SStephane Eranian } 1147b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1148b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1149b757bb09SAdrian Hunter ui__error("kernel does not support recording context switch events (--switch-events option)\n"); 1150b757bb09SAdrian Hunter usage_with_options(record_usage, record_options); 1151b757bb09SAdrian Hunter } 1152023695d9SStephane Eranian 1153ef149c25SAdrian Hunter if (!rec->itr) { 1154ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1155ef149c25SAdrian Hunter if (err) 1156ef149c25SAdrian Hunter return err; 1157ef149c25SAdrian Hunter } 1158ef149c25SAdrian Hunter 11592dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 11602dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 11612dd6d8a1SAdrian Hunter if (err) 11622dd6d8a1SAdrian Hunter return err; 11632dd6d8a1SAdrian Hunter 1164ef149c25SAdrian Hunter err = -ENOMEM; 1165ef149c25SAdrian Hunter 11660a7e6d1bSNamhyung Kim symbol__init(NULL); 1167baa2f6ceSArnaldo Carvalho de Melo 1168ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1169646aaea6SArnaldo Carvalho de Melo pr_warning( 1170646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1171ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1172646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1173646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1174646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1175646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1176646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1177ec80fde7SArnaldo Carvalho de Melo 1178d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1179a1ac1d3cSStephane Eranian disable_buildid_cache(); 1180655000e7SArnaldo Carvalho de Melo 11813e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 11823e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 118369aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 118469aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1185bbd36e5eSPeter Zijlstra } 118686470930SIngo Molnar 118769e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 118869e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 118969e7e5b0SAdrian Hunter 1190602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 119116ad2ffbSNamhyung Kim if (err) { 1192602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 119316ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 119416ad2ffbSNamhyung Kim } 11954bd0f2d2SNamhyung Kim 1196602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 119716ad2ffbSNamhyung Kim if (err) { 119816ad2ffbSNamhyung Kim int saved_errno = errno; 119916ad2ffbSNamhyung Kim 1200602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 12013780f488SNamhyung Kim ui__error("%s", errbuf); 120216ad2ffbSNamhyung Kim 120316ad2ffbSNamhyung Kim err = -saved_errno; 12048fa60e1fSNamhyung Kim goto out_symbol_exit; 120516ad2ffbSNamhyung Kim } 12060d37aa34SArnaldo Carvalho de Melo 120716ad2ffbSNamhyung Kim err = -ENOMEM; 12083e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1209dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 121069aad6f1SArnaldo Carvalho de Melo 1211ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1212ef149c25SAdrian Hunter if (err) 1213ef149c25SAdrian Hunter goto out_symbol_exit; 1214ef149c25SAdrian Hunter 1215b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 121639d17dacSArnaldo Carvalho de Melo err = -EINVAL; 121703ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 12187e4ff9e3SMike Galbraith } 12197e4ff9e3SMike Galbraith 1220d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1221d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 122245604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1223d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1224ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 122539d17dacSArnaldo Carvalho de Melo return err; 122686470930SIngo Molnar } 12272dd6d8a1SAdrian Hunter 12282dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 12292dd6d8a1SAdrian Hunter { 12302dd6d8a1SAdrian Hunter if (!auxtrace_snapshot_enabled) 12312dd6d8a1SAdrian Hunter return; 12322dd6d8a1SAdrian Hunter auxtrace_snapshot_enabled = 0; 12332dd6d8a1SAdrian Hunter auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 12342dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 12352dd6d8a1SAdrian Hunter } 1236