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" 307c6a1c65SPeter Zijlstra 3186470930SIngo Molnar #include <unistd.h> 3286470930SIngo Molnar #include <sched.h> 33a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3486470930SIngo Molnar 3578da39faSBernhard Rosenkraenzer 368c6f45a7SArnaldo Carvalho de Melo struct record { 3745694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 38b4006796SArnaldo Carvalho de Melo struct record_opts opts; 39d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 40f5fc1412SJiri Olsa struct perf_data_file file; 41d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 42d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 43d20deb64SArnaldo Carvalho de Melo const char *progname; 44d20deb64SArnaldo Carvalho de Melo int realtime_prio; 45d20deb64SArnaldo Carvalho de Melo bool no_buildid; 46d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 47d20deb64SArnaldo Carvalho de Melo long samples; 480f82ebc4SArnaldo Carvalho de Melo }; 4986470930SIngo Molnar 508c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 51f5970550SPeter Zijlstra { 52cf8b2e69SArnaldo Carvalho de Melo if (perf_data_file__write(rec->session->file, bf, size) < 0) { 534f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 548d3eca20SDavid Ahern return -1; 558d3eca20SDavid Ahern } 56f5970550SPeter Zijlstra 57cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 588d3eca20SDavid Ahern return 0; 59f5970550SPeter Zijlstra } 60f5970550SPeter Zijlstra 6145694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 62d20deb64SArnaldo Carvalho de Melo union perf_event *event, 631d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 641d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 65234fbbf5SArnaldo Carvalho de Melo { 668c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 678c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 68234fbbf5SArnaldo Carvalho de Melo } 69234fbbf5SArnaldo Carvalho de Melo 70e5685730SArnaldo Carvalho de Melo static int record__mmap_read(struct record *rec, int idx) 7186470930SIngo Molnar { 72e5685730SArnaldo Carvalho de Melo struct perf_mmap *md = &rec->evlist->mmap[idx]; 73744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 7486470930SIngo Molnar unsigned int old = md->prev; 75918512b4SJiri Olsa unsigned char *data = md->base + page_size; 7686470930SIngo Molnar unsigned long size; 7786470930SIngo Molnar void *buf; 788d3eca20SDavid Ahern int rc = 0; 7986470930SIngo Molnar 80dc82009aSArnaldo Carvalho de Melo if (old == head) 818d3eca20SDavid Ahern return 0; 8286470930SIngo Molnar 83d20deb64SArnaldo Carvalho de Melo rec->samples++; 8486470930SIngo Molnar 8586470930SIngo Molnar size = head - old; 8686470930SIngo Molnar 8786470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 8886470930SIngo Molnar buf = &data[old & md->mask]; 8986470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 9086470930SIngo Molnar old += size; 9186470930SIngo Molnar 928c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 938d3eca20SDavid Ahern rc = -1; 948d3eca20SDavid Ahern goto out; 958d3eca20SDavid Ahern } 9686470930SIngo Molnar } 9786470930SIngo Molnar 9886470930SIngo Molnar buf = &data[old & md->mask]; 9986470930SIngo Molnar size = head - old; 10086470930SIngo Molnar old += size; 10186470930SIngo Molnar 1028c6f45a7SArnaldo Carvalho de Melo if (record__write(rec, buf, size) < 0) { 1038d3eca20SDavid Ahern rc = -1; 1048d3eca20SDavid Ahern goto out; 1058d3eca20SDavid Ahern } 10686470930SIngo Molnar 10786470930SIngo Molnar md->prev = old; 108e5685730SArnaldo Carvalho de Melo perf_evlist__mmap_consume(rec->evlist, idx); 1098d3eca20SDavid Ahern out: 1108d3eca20SDavid Ahern return rc; 11186470930SIngo Molnar } 11286470930SIngo Molnar 11386470930SIngo Molnar static volatile int done = 0; 114f7b7c26eSPeter Zijlstra static volatile int signr = -1; 11533e49ea7SAndi Kleen static volatile int child_finished = 0; 11686470930SIngo Molnar 11786470930SIngo Molnar static void sig_handler(int sig) 11886470930SIngo Molnar { 11933e49ea7SAndi Kleen if (sig == SIGCHLD) 12033e49ea7SAndi Kleen child_finished = 1; 12145604710SNamhyung Kim else 12245604710SNamhyung Kim signr = sig; 12333e49ea7SAndi Kleen 12486470930SIngo Molnar done = 1; 125f7b7c26eSPeter Zijlstra } 126f7b7c26eSPeter Zijlstra 12745604710SNamhyung Kim static void record__sig_exit(void) 128f7b7c26eSPeter Zijlstra { 12945604710SNamhyung Kim if (signr == -1) 130f7b7c26eSPeter Zijlstra return; 131f7b7c26eSPeter Zijlstra 132f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 13345604710SNamhyung Kim raise(signr); 13486470930SIngo Molnar } 13586470930SIngo Molnar 1368c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 137dd7927f4SArnaldo Carvalho de Melo { 13856e52e85SArnaldo Carvalho de Melo char msg[512]; 1396a4bb04cSJiri Olsa struct perf_evsel *pos; 140d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 141d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 142b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 1438d3eca20SDavid Ahern int rc = 0; 144dd7927f4SArnaldo Carvalho de Melo 145f77a9518SArnaldo Carvalho de Melo perf_evlist__config(evlist, opts); 146cac21425SJiri Olsa 1470050f7aaSArnaldo Carvalho de Melo evlist__for_each(evlist, pos) { 1483da297a6SIngo Molnar try_again: 1496a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 15056e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 1513da297a6SIngo Molnar if (verbose) 152c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 1533da297a6SIngo Molnar goto try_again; 1543da297a6SIngo Molnar } 155ca6a4258SDavid Ahern 15656e52e85SArnaldo Carvalho de Melo rc = -errno; 15756e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 15856e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 15956e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 1608d3eca20SDavid Ahern goto out; 1617c6a1c65SPeter Zijlstra } 1627c6a1c65SPeter Zijlstra } 1637c6a1c65SPeter Zijlstra 1641491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 1650a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 16635550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 1678d3eca20SDavid Ahern rc = -1; 1688d3eca20SDavid Ahern goto out; 1690a102479SFrederic Weisbecker } 1700a102479SFrederic Weisbecker 17118e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 1728d3eca20SDavid Ahern if (errno == EPERM) { 1738d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 17418e60939SNelson Elhage "Consider increasing " 17518e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 17618e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 17753653d70SAdrian Hunter "(current value: %u)\n", opts->mmap_pages); 1788d3eca20SDavid Ahern rc = -errno; 1798d3eca20SDavid Ahern } else { 18035550da3SMasami Hiramatsu pr_err("failed to mmap with %d (%s)\n", errno, 18135550da3SMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 1828d3eca20SDavid Ahern rc = -errno; 1838d3eca20SDavid Ahern } 1848d3eca20SDavid Ahern goto out; 18518e60939SNelson Elhage } 1860a27d7f9SArnaldo Carvalho de Melo 187a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 1887b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 1898d3eca20SDavid Ahern out: 1908d3eca20SDavid Ahern return rc; 191a91e5431SArnaldo Carvalho de Melo } 192a91e5431SArnaldo Carvalho de Melo 1938c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 1946122e4e4SArnaldo Carvalho de Melo { 195f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 196f5fc1412SJiri Olsa struct perf_session *session = rec->session; 1977ab75cffSDavid Ahern u64 start = session->header.data_offset; 1986122e4e4SArnaldo Carvalho de Melo 199f5fc1412SJiri Olsa u64 size = lseek(file->fd, 0, SEEK_CUR); 2009f591fd7SArnaldo Carvalho de Melo if (size == 0) 2019f591fd7SArnaldo Carvalho de Melo return 0; 2029f591fd7SArnaldo Carvalho de Melo 2037ab75cffSDavid Ahern return __perf_session__process_events(session, start, 2047ab75cffSDavid Ahern size - start, 2056122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 2066122e4e4SArnaldo Carvalho de Melo } 2076122e4e4SArnaldo Carvalho de Melo 2088115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 209a1645ce1SZhang, Yanmin { 210a1645ce1SZhang, Yanmin int err; 21145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 212a1645ce1SZhang, Yanmin /* 213a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 214a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 215a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 216a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 217a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 218a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 219a1645ce1SZhang, Yanmin */ 22045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 221743eb868SArnaldo Carvalho de Melo machine); 222a1645ce1SZhang, Yanmin if (err < 0) 223a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 22423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 225a1645ce1SZhang, Yanmin 226a1645ce1SZhang, Yanmin /* 227a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 228a1645ce1SZhang, Yanmin * have no _text sometimes. 229a1645ce1SZhang, Yanmin */ 23045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 2310ae617beSAdrian Hunter machine); 232a1645ce1SZhang, Yanmin if (err < 0) 233a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 23423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 235a1645ce1SZhang, Yanmin } 236a1645ce1SZhang, Yanmin 23798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 23898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 23998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 24098402807SFrederic Weisbecker }; 24198402807SFrederic Weisbecker 2428c6f45a7SArnaldo Carvalho de Melo static int record__mmap_read_all(struct record *rec) 24398402807SFrederic Weisbecker { 244dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 2450e2e63ddSPeter Zijlstra int i; 2468d3eca20SDavid Ahern int rc = 0; 24798402807SFrederic Weisbecker 248d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2498d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 250e5685730SArnaldo Carvalho de Melo if (record__mmap_read(rec, i) != 0) { 2518d3eca20SDavid Ahern rc = -1; 2528d3eca20SDavid Ahern goto out; 2538d3eca20SDavid Ahern } 2548d3eca20SDavid Ahern } 25598402807SFrederic Weisbecker } 25698402807SFrederic Weisbecker 257dcabb507SJiri Olsa /* 258dcabb507SJiri Olsa * Mark the round finished in case we wrote 259dcabb507SJiri Olsa * at least one event. 260dcabb507SJiri Olsa */ 261dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 2628c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 2638d3eca20SDavid Ahern 2648d3eca20SDavid Ahern out: 2658d3eca20SDavid Ahern return rc; 26698402807SFrederic Weisbecker } 26798402807SFrederic Weisbecker 2688c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 26957706abcSDavid Ahern { 27057706abcSDavid Ahern struct perf_session *session = rec->session; 27157706abcSDavid Ahern int feat; 27257706abcSDavid Ahern 27357706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 27457706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 27557706abcSDavid Ahern 27657706abcSDavid Ahern if (rec->no_buildid) 27757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 27857706abcSDavid Ahern 2793e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 28057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 28157706abcSDavid Ahern 28257706abcSDavid Ahern if (!rec->opts.branch_stack) 28357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 28457706abcSDavid Ahern } 28557706abcSDavid Ahern 286f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 287f33cbe72SArnaldo Carvalho de Melo 288f33cbe72SArnaldo Carvalho de Melo /* 289f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 290f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 291f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 292f33cbe72SArnaldo Carvalho de Melo */ 29345604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 29445604710SNamhyung Kim siginfo_t *info, 295f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 296f33cbe72SArnaldo Carvalho de Melo { 297f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 298f33cbe72SArnaldo Carvalho de Melo done = 1; 299f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 300f33cbe72SArnaldo Carvalho de Melo } 301f33cbe72SArnaldo Carvalho de Melo 3028c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 30386470930SIngo Molnar { 30457706abcSDavid Ahern int err; 30545604710SNamhyung Kim int status = 0; 3068b412664SPeter Zijlstra unsigned long waking = 0; 30746be604bSZhang, Yanmin const bool forks = argc > 0; 30823346f21SArnaldo Carvalho de Melo struct machine *machine; 30945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 310b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 311f5fc1412SJiri Olsa struct perf_data_file *file = &rec->file; 312d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 3136dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 31486470930SIngo Molnar 315d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 31633e49ea7SAndi Kleen 31745604710SNamhyung Kim atexit(record__sig_exit); 318f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 319f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 320804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 321f5970550SPeter Zijlstra 322f5fc1412SJiri Olsa session = perf_session__new(file, false, NULL); 32394c744b6SArnaldo Carvalho de Melo if (session == NULL) { 324ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 325a9a70bbcSArnaldo Carvalho de Melo return -1; 326a9a70bbcSArnaldo Carvalho de Melo } 327a9a70bbcSArnaldo Carvalho de Melo 328d20deb64SArnaldo Carvalho de Melo rec->session = session; 329d20deb64SArnaldo Carvalho de Melo 3308c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 331330aa675SStephane Eranian 332d4db3f16SArnaldo Carvalho de Melo if (forks) { 3333e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 334f5fc1412SJiri Olsa argv, file->is_pipe, 335735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 33635b9d88eSArnaldo Carvalho de Melo if (err < 0) { 33735b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 33845604710SNamhyung Kim status = err; 33935b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 340856e9660SPeter Zijlstra } 341856e9660SPeter Zijlstra } 342856e9660SPeter Zijlstra 3438c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 3448d3eca20SDavid Ahern err = -1; 34545604710SNamhyung Kim goto out_child; 3468d3eca20SDavid Ahern } 34786470930SIngo Molnar 3483e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 349a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 350a8bb559bSNamhyung Kim 351f5fc1412SJiri Olsa if (file->is_pipe) { 352f5fc1412SJiri Olsa err = perf_header__write_pipe(file->fd); 353529870e3STom Zanussi if (err < 0) 35445604710SNamhyung Kim goto out_child; 355563aecb2SJiri Olsa } else { 3563e2be2daSArnaldo Carvalho de Melo err = perf_session__write_header(session, rec->evlist, 357f5fc1412SJiri Olsa file->fd, false); 358d5eed904SArnaldo Carvalho de Melo if (err < 0) 35945604710SNamhyung Kim goto out_child; 360d5eed904SArnaldo Carvalho de Melo } 3617c6a1c65SPeter Zijlstra 362d3665498SDavid Ahern if (!rec->no_buildid 363e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 364d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 365e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 3668d3eca20SDavid Ahern err = -1; 36745604710SNamhyung Kim goto out_child; 368e20960c0SRobert Richter } 369e20960c0SRobert Richter 37034ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 371743eb868SArnaldo Carvalho de Melo 372f5fc1412SJiri Olsa if (file->is_pipe) { 37345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 374a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 3752c46dbb5STom Zanussi if (err < 0) { 3762c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 37745604710SNamhyung Kim goto out_child; 3782c46dbb5STom Zanussi } 379cd19a035STom Zanussi 3803e2be2daSArnaldo Carvalho de Melo if (have_tracepoints(&rec->evlist->entries)) { 38163e0c771STom Zanussi /* 38263e0c771STom Zanussi * FIXME err <= 0 here actually means that 38363e0c771STom Zanussi * there were no tracepoints so its not really 38463e0c771STom Zanussi * an error, just that we don't need to 38563e0c771STom Zanussi * synthesize anything. We really have to 38663e0c771STom Zanussi * return this more properly and also 38763e0c771STom Zanussi * propagate errors that now are calling die() 38863e0c771STom Zanussi */ 3893e2be2daSArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist, 390743eb868SArnaldo Carvalho de Melo process_synthesized_event); 39163e0c771STom Zanussi if (err <= 0) { 39263e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 39345604710SNamhyung Kim goto out_child; 39463e0c771STom Zanussi } 395f34b9001SDavid Ahern rec->bytes_written += err; 3962c46dbb5STom Zanussi } 39763e0c771STom Zanussi } 3982c46dbb5STom Zanussi 39945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4000ae617beSAdrian Hunter machine); 401c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 402c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 403c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 404c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 40556b03f3cSArnaldo Carvalho de Melo 40645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 407743eb868SArnaldo Carvalho de Melo machine); 408c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 409c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 410c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 411c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 412c1a3a4b9SArnaldo Carvalho de Melo 4137e383de4SArnaldo Carvalho de Melo if (perf_guest) { 414876650e6SArnaldo Carvalho de Melo machines__process_guests(&session->machines, 4157e383de4SArnaldo Carvalho de Melo perf_event__synthesize_guest_os, tool); 4167e383de4SArnaldo Carvalho de Melo } 417b7cece76SArnaldo Carvalho de Melo 4183e2be2daSArnaldo Carvalho de Melo err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 41958d925dcSArnaldo Carvalho de Melo process_synthesized_event, opts->sample_address); 4208d3eca20SDavid Ahern if (err != 0) 42145604710SNamhyung Kim goto out_child; 4228d3eca20SDavid Ahern 423d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 42486470930SIngo Molnar struct sched_param param; 42586470930SIngo Molnar 426d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 42786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 4286beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 4298d3eca20SDavid Ahern err = -1; 43045604710SNamhyung Kim goto out_child; 43186470930SIngo Molnar } 43286470930SIngo Molnar } 43386470930SIngo Molnar 434774cb499SJiri Olsa /* 435774cb499SJiri Olsa * When perf is starting the traced process, all the events 436774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 437774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 438774cb499SJiri Olsa */ 4396619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 4403e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 441764e16a3SDavid Ahern 442856e9660SPeter Zijlstra /* 443856e9660SPeter Zijlstra * Let the child rip 444856e9660SPeter Zijlstra */ 445735f7e0bSArnaldo Carvalho de Melo if (forks) 4463e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 447856e9660SPeter Zijlstra 4486619a53eSAndi Kleen if (opts->initial_delay) { 4496619a53eSAndi Kleen usleep(opts->initial_delay * 1000); 4506619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 4516619a53eSAndi Kleen } 4526619a53eSAndi Kleen 453649c48a9SPeter Zijlstra for (;;) { 454d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 45586470930SIngo Molnar 4568c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 4578d3eca20SDavid Ahern err = -1; 45845604710SNamhyung Kim goto out_child; 4598d3eca20SDavid Ahern } 46086470930SIngo Molnar 461d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 4626dcf45efSArnaldo Carvalho de Melo if (done || draining) 463649c48a9SPeter Zijlstra break; 464f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 465a515114fSJiri Olsa /* 466a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 467a515114fSJiri Olsa * number of returned events and interrupt error. 468a515114fSJiri Olsa */ 469a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 47045604710SNamhyung Kim err = 0; 4718b412664SPeter Zijlstra waking++; 4726dcf45efSArnaldo Carvalho de Melo 4736dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 4746dcf45efSArnaldo Carvalho de Melo draining = true; 4758b412664SPeter Zijlstra } 4768b412664SPeter Zijlstra 477774cb499SJiri Olsa /* 478774cb499SJiri Olsa * When perf is starting the traced process, at the end events 479774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 480774cb499SJiri Olsa * disable events in this case. 481774cb499SJiri Olsa */ 482602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 4833e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 4842711926aSJiri Olsa disabled = true; 4852711926aSJiri Olsa } 4868b412664SPeter Zijlstra } 4878b412664SPeter Zijlstra 488f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 48935550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 490f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 491f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 492f33cbe72SArnaldo Carvalho de Melo err = -1; 49345604710SNamhyung Kim goto out_child; 494f33cbe72SArnaldo Carvalho de Melo } 495f33cbe72SArnaldo Carvalho de Melo 49645604710SNamhyung Kim if (!quiet) { 4978b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 49886470930SIngo Molnar 49986470930SIngo Molnar /* 50086470930SIngo Molnar * Approximate RIP event size: 24 bytes. 50186470930SIngo Molnar */ 50286470930SIngo Molnar fprintf(stderr, 5039486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 504d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 5056a4d98d7SJiri Olsa file->path, 506d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 50745604710SNamhyung Kim } 50886470930SIngo Molnar 50945604710SNamhyung Kim out_child: 51045604710SNamhyung Kim if (forks) { 51145604710SNamhyung Kim int exit_status; 51245604710SNamhyung Kim 51345604710SNamhyung Kim if (!child_finished) 51445604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 51545604710SNamhyung Kim 51645604710SNamhyung Kim wait(&exit_status); 51745604710SNamhyung Kim 51845604710SNamhyung Kim if (err < 0) 51945604710SNamhyung Kim status = err; 52045604710SNamhyung Kim else if (WIFEXITED(exit_status)) 52145604710SNamhyung Kim status = WEXITSTATUS(exit_status); 52245604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 52345604710SNamhyung Kim signr = WTERMSIG(exit_status); 52445604710SNamhyung Kim } else 52545604710SNamhyung Kim status = err; 52645604710SNamhyung Kim 52745604710SNamhyung Kim if (!err && !file->is_pipe) { 52845604710SNamhyung Kim rec->session->header.data_size += rec->bytes_written; 52945604710SNamhyung Kim 53045604710SNamhyung Kim if (!rec->no_buildid) 53145604710SNamhyung Kim process_buildids(rec); 53245604710SNamhyung Kim perf_session__write_header(rec->session, rec->evlist, 53345604710SNamhyung Kim file->fd, true); 53445604710SNamhyung Kim } 53539d17dacSArnaldo Carvalho de Melo 53639d17dacSArnaldo Carvalho de Melo out_delete_session: 53739d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 53845604710SNamhyung Kim return status; 53986470930SIngo Molnar } 54086470930SIngo Molnar 541bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 542bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 543bdfebd84SRoberto Agostino Vitillo 544bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 545bdfebd84SRoberto Agostino Vitillo 546bdfebd84SRoberto Agostino Vitillo struct branch_mode { 547bdfebd84SRoberto Agostino Vitillo const char *name; 548bdfebd84SRoberto Agostino Vitillo int mode; 549bdfebd84SRoberto Agostino Vitillo }; 550bdfebd84SRoberto Agostino Vitillo 551bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 552bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 553bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 554bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 555bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 556bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 557bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 558bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 5590126d493SAndi Kleen BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX), 5600126d493SAndi Kleen BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX), 5610126d493SAndi Kleen BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), 5620fffa5dfSAnshuman Khandual BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), 563bdfebd84SRoberto Agostino Vitillo BRANCH_END 564bdfebd84SRoberto Agostino Vitillo }; 565bdfebd84SRoberto Agostino Vitillo 566bdfebd84SRoberto Agostino Vitillo static int 567a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 568bdfebd84SRoberto Agostino Vitillo { 569bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 570bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 571bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 572bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 573bdfebd84SRoberto Agostino Vitillo 574bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 575bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 576a5aabdacSStephane Eranian char *s, *os = NULL, *p; 577bdfebd84SRoberto Agostino Vitillo int ret = -1; 578bdfebd84SRoberto Agostino Vitillo 579a5aabdacSStephane Eranian if (unset) 580a5aabdacSStephane Eranian return 0; 581bdfebd84SRoberto Agostino Vitillo 582a5aabdacSStephane Eranian /* 583a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 584a5aabdacSStephane Eranian */ 585a5aabdacSStephane Eranian if (*mode) 586a5aabdacSStephane Eranian return -1; 587a5aabdacSStephane Eranian 588a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 589a5aabdacSStephane Eranian if (str) { 590bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 591bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 592bdfebd84SRoberto Agostino Vitillo if (!s) 593bdfebd84SRoberto Agostino Vitillo return -1; 594bdfebd84SRoberto Agostino Vitillo 595bdfebd84SRoberto Agostino Vitillo for (;;) { 596bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 597bdfebd84SRoberto Agostino Vitillo if (p) 598bdfebd84SRoberto Agostino Vitillo *p = '\0'; 599bdfebd84SRoberto Agostino Vitillo 600bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 601bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 602bdfebd84SRoberto Agostino Vitillo break; 603bdfebd84SRoberto Agostino Vitillo } 604a5aabdacSStephane Eranian if (!br->name) { 605a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 606a5aabdacSStephane Eranian " check man page\n", s); 607bdfebd84SRoberto Agostino Vitillo goto error; 608a5aabdacSStephane Eranian } 609bdfebd84SRoberto Agostino Vitillo 610bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 611bdfebd84SRoberto Agostino Vitillo 612bdfebd84SRoberto Agostino Vitillo if (!p) 613bdfebd84SRoberto Agostino Vitillo break; 614bdfebd84SRoberto Agostino Vitillo 615bdfebd84SRoberto Agostino Vitillo s = p + 1; 616bdfebd84SRoberto Agostino Vitillo } 617a5aabdacSStephane Eranian } 618bdfebd84SRoberto Agostino Vitillo ret = 0; 619bdfebd84SRoberto Agostino Vitillo 620a5aabdacSStephane Eranian /* default to any branch */ 621bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 622a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 623bdfebd84SRoberto Agostino Vitillo } 624bdfebd84SRoberto Agostino Vitillo error: 625bdfebd84SRoberto Agostino Vitillo free(os); 626bdfebd84SRoberto Agostino Vitillo return ret; 627bdfebd84SRoberto Agostino Vitillo } 628bdfebd84SRoberto Agostino Vitillo 62972a128aaSNamhyung Kim static void callchain_debug(void) 63009b0fd45SJiri Olsa { 631a601fdffSJiri Olsa static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" }; 632a601fdffSJiri Olsa 63372a128aaSNamhyung Kim pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 63426d33022SJiri Olsa 63572a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_DWARF) 63609b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 63772a128aaSNamhyung Kim callchain_param.dump_size); 63809b0fd45SJiri Olsa } 63909b0fd45SJiri Olsa 64072a128aaSNamhyung Kim int record_parse_callchain_opt(const struct option *opt __maybe_unused, 64109b0fd45SJiri Olsa const char *arg, 64209b0fd45SJiri Olsa int unset) 64309b0fd45SJiri Olsa { 64409b0fd45SJiri Olsa int ret; 64509b0fd45SJiri Olsa 64672a128aaSNamhyung Kim callchain_param.enabled = !unset; 647eb853e80SJiri Olsa 64809b0fd45SJiri Olsa /* --no-call-graph */ 64909b0fd45SJiri Olsa if (unset) { 65072a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_NONE; 65109b0fd45SJiri Olsa pr_debug("callchain: disabled\n"); 65209b0fd45SJiri Olsa return 0; 65309b0fd45SJiri Olsa } 65409b0fd45SJiri Olsa 655f7f084f4SNamhyung Kim ret = parse_callchain_record_opt(arg); 65609b0fd45SJiri Olsa if (!ret) 65772a128aaSNamhyung Kim callchain_debug(); 65809b0fd45SJiri Olsa 65926d33022SJiri Olsa return ret; 66026d33022SJiri Olsa } 66126d33022SJiri Olsa 66272a128aaSNamhyung Kim int record_callchain_opt(const struct option *opt __maybe_unused, 66309b0fd45SJiri Olsa const char *arg __maybe_unused, 66409b0fd45SJiri Olsa int unset __maybe_unused) 66509b0fd45SJiri Olsa { 66672a128aaSNamhyung Kim callchain_param.enabled = true; 66709b0fd45SJiri Olsa 66872a128aaSNamhyung Kim if (callchain_param.record_mode == CALLCHAIN_NONE) 66972a128aaSNamhyung Kim callchain_param.record_mode = CALLCHAIN_FP; 670eb853e80SJiri Olsa 67172a128aaSNamhyung Kim callchain_debug(); 67209b0fd45SJiri Olsa return 0; 67309b0fd45SJiri Olsa } 67409b0fd45SJiri Olsa 675eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 676eb853e80SJiri Olsa { 677eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 6785a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 679eb853e80SJiri Olsa 680eb853e80SJiri Olsa return perf_default_config(var, value, cb); 681eb853e80SJiri Olsa } 682eb853e80SJiri Olsa 683*e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 68486470930SIngo Molnar "perf record [<options>] [<command>]", 68586470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 68686470930SIngo Molnar NULL 68786470930SIngo Molnar }; 688*e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 68986470930SIngo Molnar 690d20deb64SArnaldo Carvalho de Melo /* 6918c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 6928c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 693d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 694d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 695d20deb64SArnaldo Carvalho de Melo * 696d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 697d20deb64SArnaldo Carvalho de Melo * 698d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 699d20deb64SArnaldo Carvalho de Melo */ 7008c6f45a7SArnaldo Carvalho de Melo static struct record record = { 701d20deb64SArnaldo Carvalho de Melo .opts = { 7028affc2b8SAndi Kleen .sample_time = true, 703d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 704d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 705d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 706447a6013SArnaldo Carvalho de Melo .freq = 4000, 707d1cb9fceSNamhyung Kim .target = { 708d1cb9fceSNamhyung Kim .uses_mmap = true, 7093aa5939dSAdrian Hunter .default_per_cpu = true, 710d1cb9fceSNamhyung Kim }, 711d20deb64SArnaldo Carvalho de Melo }, 712d20deb64SArnaldo Carvalho de Melo }; 7137865e817SFrederic Weisbecker 71409b0fd45SJiri Olsa #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 71561eaa3beSArnaldo Carvalho de Melo 7169ff125d1SJiri Olsa #ifdef HAVE_DWARF_UNWIND_SUPPORT 71709b0fd45SJiri Olsa const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 71861eaa3beSArnaldo Carvalho de Melo #else 71909b0fd45SJiri Olsa const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 72061eaa3beSArnaldo Carvalho de Melo #endif 72161eaa3beSArnaldo Carvalho de Melo 722d20deb64SArnaldo Carvalho de Melo /* 723d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 724d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 725b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 726d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 727d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 728d20deb64SArnaldo Carvalho de Melo */ 729*e5b2c207SNamhyung Kim struct option __record_options[] = { 730d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 73186470930SIngo Molnar "event selector. use 'perf list' to list available events", 732f120f9d5SJiri Olsa parse_events_option), 733d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 734c171b552SLi Zefan "event filter", parse_filter), 735bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 736d6d901c2SZhang, Yanmin "record events on existing process id"), 737bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 738d6d901c2SZhang, Yanmin "record events on existing thread id"), 739d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 74086470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 741509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 742acac03faSKirill Smelkov "collect data without buffering"), 743d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 744daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 745bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 74686470930SIngo Molnar "system-wide collection from all CPUs"), 747bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 748c45c6ea2SStephane Eranian "list of cpus to monitor"), 749d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 750f5fc1412SJiri Olsa OPT_STRING('o', "output", &record.file.path, "file", 75186470930SIngo Molnar "output file name"), 75269e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 75369e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 7542e6cdf99SStephane Eranian "child tasks do not inherit counters"), 755d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 756994a1f78SJiri Olsa OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 757994a1f78SJiri Olsa "number of mmap data pages", 758994a1f78SJiri Olsa perf_evlist__parse_mmap_pages), 759d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 76043bece79SLin Ming "put the counters into a counter group"), 76109b0fd45SJiri Olsa OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 76209b0fd45SJiri Olsa NULL, "enables call-graph recording" , 76309b0fd45SJiri Olsa &record_callchain_opt), 76409b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 76575d9a108SArnaldo Carvalho de Melo "mode[,dump_size]", record_callchain_help, 76609b0fd45SJiri Olsa &record_parse_callchain_opt), 767c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7683da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 769b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 770d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 771649c48a9SPeter Zijlstra "per thread counts"), 772d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 7734bba828dSAnton Blanchard "Sample addresses"), 774d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 7753e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 776d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 777649c48a9SPeter Zijlstra "don't sample"), 778d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 779a1ac1d3cSStephane Eranian "do not update the buildid cache"), 780d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 781baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 782d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 783023695d9SStephane Eranian "monitor event in cgroup name only", 784023695d9SStephane Eranian parse_cgroups), 785a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 7866619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 787bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 788bea03405SNamhyung Kim "user to profile"), 789a5aabdacSStephane Eranian 790a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 791a5aabdacSStephane Eranian "branch any", "sample any taken branches", 792a5aabdacSStephane Eranian parse_branch_stack), 793a5aabdacSStephane Eranian 794a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 795a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 796bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 79705484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 79805484298SAndi Kleen "sample by weight (on special events only)"), 799475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 800475eeab9SAndi Kleen "sample transaction flags (special events only)"), 8013aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 8023aa5939dSAdrian Hunter "use per-thread mmaps"), 80386470930SIngo Molnar OPT_END() 80486470930SIngo Molnar }; 80586470930SIngo Molnar 806*e5b2c207SNamhyung Kim struct option *record_options = __record_options; 807*e5b2c207SNamhyung Kim 8081d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 80986470930SIngo Molnar { 81069aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 8118c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 81216ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 81386470930SIngo Molnar 8143e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 8153e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 816361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 817361c99a6SArnaldo Carvalho de Melo 818eb853e80SJiri Olsa perf_config(perf_record_config, rec); 819eb853e80SJiri Olsa 820bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 821a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 822602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 823bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 82486470930SIngo Molnar 825bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 8263780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 827023695d9SStephane Eranian " system-wide mode\n"); 828023695d9SStephane Eranian usage_with_options(record_usage, record_options); 829023695d9SStephane Eranian } 830023695d9SStephane Eranian 8310a7e6d1bSNamhyung Kim symbol__init(NULL); 832baa2f6ceSArnaldo Carvalho de Melo 833ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 834646aaea6SArnaldo Carvalho de Melo pr_warning( 835646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 836ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 837646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 838646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 839646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 840646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 841646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 842ec80fde7SArnaldo Carvalho de Melo 843d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 844a1ac1d3cSStephane Eranian disable_buildid_cache(); 845655000e7SArnaldo Carvalho de Melo 8463e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 8473e2be2daSArnaldo Carvalho de Melo perf_evlist__add_default(rec->evlist) < 0) { 84869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 84969aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 850bbd36e5eSPeter Zijlstra } 85186470930SIngo Molnar 85269e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 85369e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 85469e7e5b0SAdrian Hunter 855602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 85616ad2ffbSNamhyung Kim if (err) { 857602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 85816ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 85916ad2ffbSNamhyung Kim } 8604bd0f2d2SNamhyung Kim 861602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 86216ad2ffbSNamhyung Kim if (err) { 86316ad2ffbSNamhyung Kim int saved_errno = errno; 86416ad2ffbSNamhyung Kim 865602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 8663780f488SNamhyung Kim ui__error("%s", errbuf); 86716ad2ffbSNamhyung Kim 86816ad2ffbSNamhyung Kim err = -saved_errno; 8698fa60e1fSNamhyung Kim goto out_symbol_exit; 87016ad2ffbSNamhyung Kim } 8710d37aa34SArnaldo Carvalho de Melo 87216ad2ffbSNamhyung Kim err = -ENOMEM; 8733e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 874dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 87569aad6f1SArnaldo Carvalho de Melo 876b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 87739d17dacSArnaldo Carvalho de Melo err = -EINVAL; 87803ad9747SArnaldo Carvalho de Melo goto out_symbol_exit; 8797e4ff9e3SMike Galbraith } 8807e4ff9e3SMike Galbraith 881d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 882d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 88345604710SNamhyung Kim perf_evlist__delete(rec->evlist); 884d65a458bSArnaldo Carvalho de Melo symbol__exit(); 88539d17dacSArnaldo Carvalho de Melo return err; 88686470930SIngo Molnar } 887