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 */ 8b8f46c5aSXiao Guangrong #define _FILE_OFFSET_BITS 64 9b8f46c5aSXiao Guangrong 1086470930SIngo Molnar #include "builtin.h" 1186470930SIngo Molnar 1286470930SIngo Molnar #include "perf.h" 1386470930SIngo Molnar 146122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 1586470930SIngo Molnar #include "util/util.h" 1686470930SIngo Molnar #include "util/parse-options.h" 1786470930SIngo Molnar #include "util/parse-events.h" 1886470930SIngo Molnar 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" 297c6a1c65SPeter Zijlstra 3086470930SIngo Molnar #include <unistd.h> 3186470930SIngo Molnar #include <sched.h> 32a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3386470930SIngo Molnar 3478da39faSBernhard Rosenkraenzer #ifndef HAVE_ON_EXIT 3578da39faSBernhard Rosenkraenzer #ifndef ATEXIT_MAX 3678da39faSBernhard Rosenkraenzer #define ATEXIT_MAX 32 3778da39faSBernhard Rosenkraenzer #endif 3878da39faSBernhard Rosenkraenzer static int __on_exit_count = 0; 3978da39faSBernhard Rosenkraenzer typedef void (*on_exit_func_t) (int, void *); 4078da39faSBernhard Rosenkraenzer static on_exit_func_t __on_exit_funcs[ATEXIT_MAX]; 4178da39faSBernhard Rosenkraenzer static void *__on_exit_args[ATEXIT_MAX]; 4278da39faSBernhard Rosenkraenzer static int __exitcode = 0; 4378da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void); 4478da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg); 4578da39faSBernhard Rosenkraenzer #define exit(x) (exit)(__exitcode = (x)) 4678da39faSBernhard Rosenkraenzer 4778da39faSBernhard Rosenkraenzer static int on_exit(on_exit_func_t function, void *arg) 4878da39faSBernhard Rosenkraenzer { 4978da39faSBernhard Rosenkraenzer if (__on_exit_count == ATEXIT_MAX) 5078da39faSBernhard Rosenkraenzer return -ENOMEM; 5178da39faSBernhard Rosenkraenzer else if (__on_exit_count == 0) 5278da39faSBernhard Rosenkraenzer atexit(__handle_on_exit_funcs); 5378da39faSBernhard Rosenkraenzer __on_exit_funcs[__on_exit_count] = function; 5478da39faSBernhard Rosenkraenzer __on_exit_args[__on_exit_count++] = arg; 5578da39faSBernhard Rosenkraenzer return 0; 5678da39faSBernhard Rosenkraenzer } 5778da39faSBernhard Rosenkraenzer 5878da39faSBernhard Rosenkraenzer static void __handle_on_exit_funcs(void) 5978da39faSBernhard Rosenkraenzer { 6078da39faSBernhard Rosenkraenzer int i; 6178da39faSBernhard Rosenkraenzer for (i = 0; i < __on_exit_count; i++) 6278da39faSBernhard Rosenkraenzer __on_exit_funcs[i] (__exitcode, __on_exit_args[i]); 6378da39faSBernhard Rosenkraenzer } 6478da39faSBernhard Rosenkraenzer #endif 6578da39faSBernhard Rosenkraenzer 667865e817SFrederic Weisbecker enum write_mode_t { 677865e817SFrederic Weisbecker WRITE_FORCE, 687865e817SFrederic Weisbecker WRITE_APPEND 697865e817SFrederic Weisbecker }; 707865e817SFrederic Weisbecker 71d20deb64SArnaldo Carvalho de Melo struct perf_record { 7245694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 73d20deb64SArnaldo Carvalho de Melo struct perf_record_opts opts; 74d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 75d20deb64SArnaldo Carvalho de Melo const char *output_name; 76d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 77d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 78d20deb64SArnaldo Carvalho de Melo const char *progname; 79d20deb64SArnaldo Carvalho de Melo int output; 80d20deb64SArnaldo Carvalho de Melo unsigned int page_size; 81d20deb64SArnaldo Carvalho de Melo int realtime_prio; 82d20deb64SArnaldo Carvalho de Melo enum write_mode_t write_mode; 83d20deb64SArnaldo Carvalho de Melo bool no_buildid; 84d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 85d20deb64SArnaldo Carvalho de Melo bool force; 86d20deb64SArnaldo Carvalho de Melo bool file_new; 87d20deb64SArnaldo Carvalho de Melo bool append_file; 88d20deb64SArnaldo Carvalho de Melo long samples; 89d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 900f82ebc4SArnaldo Carvalho de Melo }; 9186470930SIngo Molnar 92d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 939215545eSTom Zanussi { 94d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 959215545eSTom Zanussi } 969215545eSTom Zanussi 978d3eca20SDavid Ahern static int write_output(struct perf_record *rec, void *buf, size_t size) 98f5970550SPeter Zijlstra { 99f5970550SPeter Zijlstra while (size) { 100d20deb64SArnaldo Carvalho de Melo int ret = write(rec->output, buf, size); 101f5970550SPeter Zijlstra 1028d3eca20SDavid Ahern if (ret < 0) { 1038d3eca20SDavid Ahern pr_err("failed to write\n"); 1048d3eca20SDavid Ahern return -1; 1058d3eca20SDavid Ahern } 106f5970550SPeter Zijlstra 107f5970550SPeter Zijlstra size -= ret; 108f5970550SPeter Zijlstra buf += ret; 109f5970550SPeter Zijlstra 110d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 111f5970550SPeter Zijlstra } 1128d3eca20SDavid Ahern 1138d3eca20SDavid Ahern return 0; 114f5970550SPeter Zijlstra } 115f5970550SPeter Zijlstra 11645694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 117d20deb64SArnaldo Carvalho de Melo union perf_event *event, 1181d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 1191d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 120234fbbf5SArnaldo Carvalho de Melo { 12145694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 1228d3eca20SDavid Ahern if (write_output(rec, event, event->header.size) < 0) 1238d3eca20SDavid Ahern return -1; 1248d3eca20SDavid Ahern 125234fbbf5SArnaldo Carvalho de Melo return 0; 126234fbbf5SArnaldo Carvalho de Melo } 127234fbbf5SArnaldo Carvalho de Melo 1288d3eca20SDavid Ahern static int perf_record__mmap_read(struct perf_record *rec, 129d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 13086470930SIngo Molnar { 131744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 13286470930SIngo Molnar unsigned int old = md->prev; 133d20deb64SArnaldo Carvalho de Melo unsigned char *data = md->base + rec->page_size; 13486470930SIngo Molnar unsigned long size; 13586470930SIngo Molnar void *buf; 1368d3eca20SDavid Ahern int rc = 0; 13786470930SIngo Molnar 138dc82009aSArnaldo Carvalho de Melo if (old == head) 1398d3eca20SDavid Ahern return 0; 14086470930SIngo Molnar 141d20deb64SArnaldo Carvalho de Melo rec->samples++; 14286470930SIngo Molnar 14386470930SIngo Molnar size = head - old; 14486470930SIngo Molnar 14586470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 14686470930SIngo Molnar buf = &data[old & md->mask]; 14786470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 14886470930SIngo Molnar old += size; 14986470930SIngo Molnar 1508d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1518d3eca20SDavid Ahern rc = -1; 1528d3eca20SDavid Ahern goto out; 1538d3eca20SDavid Ahern } 15486470930SIngo Molnar } 15586470930SIngo Molnar 15686470930SIngo Molnar buf = &data[old & md->mask]; 15786470930SIngo Molnar size = head - old; 15886470930SIngo Molnar old += size; 15986470930SIngo Molnar 1608d3eca20SDavid Ahern if (write_output(rec, buf, size) < 0) { 1618d3eca20SDavid Ahern rc = -1; 1628d3eca20SDavid Ahern goto out; 1638d3eca20SDavid Ahern } 16486470930SIngo Molnar 16586470930SIngo Molnar md->prev = old; 166115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 1678d3eca20SDavid Ahern 1688d3eca20SDavid Ahern out: 1698d3eca20SDavid Ahern return rc; 17086470930SIngo Molnar } 17186470930SIngo Molnar 17286470930SIngo Molnar static volatile int done = 0; 173f7b7c26eSPeter Zijlstra static volatile int signr = -1; 17433e49ea7SAndi Kleen static volatile int child_finished = 0; 17586470930SIngo Molnar 17686470930SIngo Molnar static void sig_handler(int sig) 17786470930SIngo Molnar { 17833e49ea7SAndi Kleen if (sig == SIGCHLD) 17933e49ea7SAndi Kleen child_finished = 1; 18033e49ea7SAndi Kleen 18186470930SIngo Molnar done = 1; 182f7b7c26eSPeter Zijlstra signr = sig; 183f7b7c26eSPeter Zijlstra } 184f7b7c26eSPeter Zijlstra 1851d037ca1SIrina Tirdea static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 186f7b7c26eSPeter Zijlstra { 187d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 18833e49ea7SAndi Kleen int status; 18933e49ea7SAndi Kleen 190d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 19133e49ea7SAndi Kleen if (!child_finished) 192d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 193933da83aSChris Wilson 19433e49ea7SAndi Kleen wait(&status); 19533e49ea7SAndi Kleen if (WIFSIGNALED(status)) 196d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 19733e49ea7SAndi Kleen } 19833e49ea7SAndi Kleen 19918483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 200f7b7c26eSPeter Zijlstra return; 201f7b7c26eSPeter Zijlstra 202f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 203f7b7c26eSPeter Zijlstra kill(getpid(), signr); 20486470930SIngo Molnar } 20586470930SIngo Molnar 206a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 207a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 208a91e5431SArnaldo Carvalho de Melo { 209a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 210a91e5431SArnaldo Carvalho de Melo 211a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 212a91e5431SArnaldo Carvalho de Melo return false; 213a91e5431SArnaldo Carvalho de Melo 2140c21f736SArnaldo Carvalho de Melo pair = perf_evlist__first(other); 215a91e5431SArnaldo Carvalho de Melo 216a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 217a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 218a91e5431SArnaldo Carvalho de Melo return false; 2190c21f736SArnaldo Carvalho de Melo pair = perf_evsel__next(pair); 220a91e5431SArnaldo Carvalho de Melo } 221a91e5431SArnaldo Carvalho de Melo 222a91e5431SArnaldo Carvalho de Melo return true; 223a91e5431SArnaldo Carvalho de Melo } 224a91e5431SArnaldo Carvalho de Melo 2258d3eca20SDavid Ahern static int perf_record__open(struct perf_record *rec) 226dd7927f4SArnaldo Carvalho de Melo { 2276a4bb04cSJiri Olsa struct perf_evsel *pos; 228d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 229d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 230d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 2318d3eca20SDavid Ahern int rc = 0; 232dd7927f4SArnaldo Carvalho de Melo 233cac21425SJiri Olsa /* 234cac21425SJiri Olsa * Set the evsel leader links before we configure attributes, 235cac21425SJiri Olsa * since some might depend on this info. 236cac21425SJiri Olsa */ 2376a4bb04cSJiri Olsa if (opts->group) 23863dab225SArnaldo Carvalho de Melo perf_evlist__set_leader(evlist); 2396a4bb04cSJiri Olsa 240cac21425SJiri Olsa perf_evlist__config_attrs(evlist, opts); 241cac21425SJiri Olsa 242dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 243dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 244dd7927f4SArnaldo Carvalho de Melo /* 245dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 246dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 247dd7927f4SArnaldo Carvalho de Melo * 248dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 249dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 250dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 251dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 252dd7927f4SArnaldo Carvalho de Melo * 253dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 254dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 255dd7927f4SArnaldo Carvalho de Melo */ 256dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 257dd7927f4SArnaldo Carvalho de Melo 2580c978128SArnaldo Carvalho de Melo fallback_missing_features: 2590c978128SArnaldo Carvalho de Melo if (opts->exclude_guest_missing) 2600c978128SArnaldo Carvalho de Melo attr->exclude_guest = attr->exclude_host = 0; 2619c90a61cSArnaldo Carvalho de Melo retry_sample_id: 262808e1226SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 2633da297a6SIngo Molnar try_again: 2646a4bb04cSJiri Olsa if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 26586470930SIngo Molnar int err = errno; 26686470930SIngo Molnar 267c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 268b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 2698d3eca20SDavid Ahern rc = -err; 2708d3eca20SDavid Ahern goto out; 271bea03405SNamhyung Kim } else if (err == ENODEV && opts->target.cpu_list) { 2728d3eca20SDavid Ahern pr_err("No such device - did you specify" 273d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 2748d3eca20SDavid Ahern rc = -err; 2758d3eca20SDavid Ahern goto out; 2760c978128SArnaldo Carvalho de Melo } else if (err == EINVAL) { 2770c978128SArnaldo Carvalho de Melo if (!opts->exclude_guest_missing && 2780c978128SArnaldo Carvalho de Melo (attr->exclude_guest || attr->exclude_host)) { 2790c978128SArnaldo Carvalho de Melo pr_debug("Old kernel, cannot exclude " 2800c978128SArnaldo Carvalho de Melo "guest or host samples.\n"); 2810c978128SArnaldo Carvalho de Melo opts->exclude_guest_missing = true; 2820c978128SArnaldo Carvalho de Melo goto fallback_missing_features; 283808e1226SArnaldo Carvalho de Melo } else if (!opts->sample_id_all_missing) { 2849c90a61cSArnaldo Carvalho de Melo /* 2859c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2869c90a61cSArnaldo Carvalho de Melo */ 287808e1226SArnaldo Carvalho de Melo opts->sample_id_all_missing = true; 288d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 289eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 290eac23d1cSIan Munsie 2919c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 292d6d901c2SZhang, Yanmin } 2930c978128SArnaldo Carvalho de Melo } 2943da297a6SIngo Molnar 2953da297a6SIngo Molnar /* 2963da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2973da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 298028d455bSDavid Ahern * is always available even if no PMU support. 299028d455bSDavid Ahern * 300028d455bSDavid Ahern * PPC returns ENXIO until 2.6.37 (behavior changed 301028d455bSDavid Ahern * with commit b0a873e). 3023da297a6SIngo Molnar */ 303028d455bSDavid Ahern if ((err == ENOENT || err == ENXIO) 304028d455bSDavid Ahern && attr->type == PERF_TYPE_HARDWARE 305f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 3063da297a6SIngo Molnar 3073da297a6SIngo Molnar if (verbose) 308ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 309ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 3103da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 311f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 312d1cae34dSDavid Ahern if (pos->name) { 313d1cae34dSDavid Ahern free(pos->name); 314d1cae34dSDavid Ahern pos->name = NULL; 315d1cae34dSDavid Ahern } 3163da297a6SIngo Molnar goto try_again; 3173da297a6SIngo Molnar } 318ca6a4258SDavid Ahern 319ca6a4258SDavid Ahern if (err == ENOENT) { 3203780f488SNamhyung Kim ui__error("The %s event is not supported.\n", 3217289f83cSArnaldo Carvalho de Melo perf_evsel__name(pos)); 3228d3eca20SDavid Ahern rc = -err; 3238d3eca20SDavid Ahern goto out; 3242305c82fSDavid Ahern } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) { 3252305c82fSDavid Ahern ui__error("\'precise\' request may not be supported. " 3262305c82fSDavid Ahern "Try removing 'p' modifier\n"); 3272305c82fSDavid Ahern rc = -err; 3282305c82fSDavid Ahern goto out; 329ca6a4258SDavid Ahern } 330ca6a4258SDavid Ahern 33130c806a0SIngo Molnar printf("\n"); 3321863fbbbSStephane Eranian error("sys_perf_event_open() syscall returned with %d " 3331863fbbbSStephane Eranian "(%s) for event %s. /bin/dmesg may provide " 3341863fbbbSStephane Eranian "additional information.\n", 3351863fbbbSStephane Eranian err, strerror(err), perf_evsel__name(pos)); 336bfd45118SSimon Kaempflein 337bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 3388d3eca20SDavid Ahern if (attr->type == PERF_TYPE_HARDWARE && 3398d3eca20SDavid Ahern err == EOPNOTSUPP) { 3408d3eca20SDavid Ahern pr_err("No hardware sampling interrupt available." 341d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 342d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 343d6d901c2SZhang, Yanmin " force-enable it.\n"); 3448d3eca20SDavid Ahern rc = -err; 3458d3eca20SDavid Ahern goto out; 3468d3eca20SDavid Ahern } 347bfd45118SSimon Kaempflein #endif 348bfd45118SSimon Kaempflein 3498d3eca20SDavid Ahern pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 3508d3eca20SDavid Ahern rc = -err; 3518d3eca20SDavid Ahern goto out; 3527c6a1c65SPeter Zijlstra } 3537c6a1c65SPeter Zijlstra } 3547c6a1c65SPeter Zijlstra 3551491a632SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist)) { 3560a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 3570a102479SFrederic Weisbecker strerror(errno)); 3588d3eca20SDavid Ahern rc = -1; 3598d3eca20SDavid Ahern goto out; 3600a102479SFrederic Weisbecker } 3610a102479SFrederic Weisbecker 36218e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 3638d3eca20SDavid Ahern if (errno == EPERM) { 3648d3eca20SDavid Ahern pr_err("Permission error mapping pages.\n" 36518e60939SNelson Elhage "Consider increasing " 36618e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 36718e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 36818e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 3698d3eca20SDavid Ahern rc = -errno; 3700089fa98SJiri Olsa } else if (!is_power_of_2(opts->mmap_pages) && 3710089fa98SJiri Olsa (opts->mmap_pages != UINT_MAX)) { 3728d3eca20SDavid Ahern pr_err("--mmap_pages/-m value must be a power of two."); 3738d3eca20SDavid Ahern rc = -EINVAL; 3748d3eca20SDavid Ahern } else { 3758d3eca20SDavid Ahern pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 3768d3eca20SDavid Ahern rc = -errno; 3778d3eca20SDavid Ahern } 3788d3eca20SDavid Ahern goto out; 37918e60939SNelson Elhage } 3800a27d7f9SArnaldo Carvalho de Melo 381d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 382a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 383a91e5431SArnaldo Carvalho de Melo else { 384a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 385a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 3868d3eca20SDavid Ahern rc = -1; 3878d3eca20SDavid Ahern goto out; 388dd7927f4SArnaldo Carvalho de Melo } 38986470930SIngo Molnar } 39086470930SIngo Molnar 3917b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3928d3eca20SDavid Ahern out: 3938d3eca20SDavid Ahern return rc; 394a91e5431SArnaldo Carvalho de Melo } 395a91e5431SArnaldo Carvalho de Melo 396d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 3976122e4e4SArnaldo Carvalho de Melo { 398d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3996122e4e4SArnaldo Carvalho de Melo 4009f591fd7SArnaldo Carvalho de Melo if (size == 0) 4019f591fd7SArnaldo Carvalho de Melo return 0; 4029f591fd7SArnaldo Carvalho de Melo 403d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 404d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 405d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 4066122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 4076122e4e4SArnaldo Carvalho de Melo } 4086122e4e4SArnaldo Carvalho de Melo 4098d3eca20SDavid Ahern static void perf_record__exit(int status, void *arg) 410f5970550SPeter Zijlstra { 411d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 412f5970550SPeter Zijlstra 4138d3eca20SDavid Ahern if (status != 0) 4148d3eca20SDavid Ahern return; 4158d3eca20SDavid Ahern 416d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 417d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 418d20deb64SArnaldo Carvalho de Melo 419d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 420d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 421d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 422d20deb64SArnaldo Carvalho de Melo rec->output, true); 423d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 424d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 425d65a458bSArnaldo Carvalho de Melo symbol__exit(); 426c7929e47STom Zanussi } 427f5970550SPeter Zijlstra } 428f5970550SPeter Zijlstra 4298115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 430a1645ce1SZhang, Yanmin { 431a1645ce1SZhang, Yanmin int err; 43245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 433a1645ce1SZhang, Yanmin 43423346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 435a1645ce1SZhang, Yanmin return; 436a1645ce1SZhang, Yanmin 437a1645ce1SZhang, Yanmin /* 438a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 439a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 440a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 441a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 442a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 443a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 444a1645ce1SZhang, Yanmin */ 44545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 446743eb868SArnaldo Carvalho de Melo machine); 447a1645ce1SZhang, Yanmin if (err < 0) 448a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 44923346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 450a1645ce1SZhang, Yanmin 451a1645ce1SZhang, Yanmin /* 452a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 453a1645ce1SZhang, Yanmin * have no _text sometimes. 454a1645ce1SZhang, Yanmin */ 45545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 456743eb868SArnaldo Carvalho de Melo machine, "_text"); 457a1645ce1SZhang, Yanmin if (err < 0) 45845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 459743eb868SArnaldo Carvalho de Melo machine, "_stext"); 460a1645ce1SZhang, Yanmin if (err < 0) 461a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 46223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 463a1645ce1SZhang, Yanmin } 464a1645ce1SZhang, Yanmin 46598402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 46698402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 46798402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 46898402807SFrederic Weisbecker }; 46998402807SFrederic Weisbecker 4708d3eca20SDavid Ahern static int perf_record__mmap_read_all(struct perf_record *rec) 47198402807SFrederic Weisbecker { 4720e2e63ddSPeter Zijlstra int i; 4738d3eca20SDavid Ahern int rc = 0; 47498402807SFrederic Weisbecker 475d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 4768d3eca20SDavid Ahern if (rec->evlist->mmap[i].base) { 4778d3eca20SDavid Ahern if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 4788d3eca20SDavid Ahern rc = -1; 4798d3eca20SDavid Ahern goto out; 4808d3eca20SDavid Ahern } 4818d3eca20SDavid Ahern } 48298402807SFrederic Weisbecker } 48398402807SFrederic Weisbecker 4842eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 4858d3eca20SDavid Ahern rc = write_output(rec, &finished_round_event, 4868d3eca20SDavid Ahern sizeof(finished_round_event)); 4878d3eca20SDavid Ahern 4888d3eca20SDavid Ahern out: 4898d3eca20SDavid Ahern return rc; 49098402807SFrederic Weisbecker } 49198402807SFrederic Weisbecker 492d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 49386470930SIngo Molnar { 49486470930SIngo Molnar struct stat st; 49586470930SIngo Molnar int flags; 496781ba9d2SRobert Richter int err, output, feat; 4978b412664SPeter Zijlstra unsigned long waking = 0; 49846be604bSZhang, Yanmin const bool forks = argc > 0; 49923346f21SArnaldo Carvalho de Melo struct machine *machine; 50045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 501d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 502d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 503d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 504d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 50586470930SIngo Molnar 506d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 50733e49ea7SAndi Kleen 508d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 50986470930SIngo Molnar 510d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 511f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 512f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 51318483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 514f5970550SPeter Zijlstra 515d7065adbSFranck Bui-Huu if (!output_name) { 516d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 517d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 518d7065adbSFranck Bui-Huu else 519d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 520d7065adbSFranck Bui-Huu } 521d7065adbSFranck Bui-Huu if (output_name) { 522529870e3STom Zanussi if (!strcmp(output_name, "-")) 523d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 524529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 525d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 526b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 527b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 528b38d3464SArnaldo Carvalho de Melo output_name); 529b38d3464SArnaldo Carvalho de Melo unlink(oldname); 530b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 531b38d3464SArnaldo Carvalho de Melo } 532d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 533d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 534266e0e21SPierre Habouzit } 535d7065adbSFranck Bui-Huu } 53686470930SIngo Molnar 537f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 538d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 539d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 54086470930SIngo Molnar else 54186470930SIngo Molnar flags |= O_TRUNC; 54286470930SIngo Molnar 543d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 544529870e3STom Zanussi output = STDOUT_FILENO; 545529870e3STom Zanussi else 54686470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 54786470930SIngo Molnar if (output < 0) { 54886470930SIngo Molnar perror("failed to create output file"); 5498d3eca20SDavid Ahern return -1; 55086470930SIngo Molnar } 55186470930SIngo Molnar 552d20deb64SArnaldo Carvalho de Melo rec->output = output; 553d20deb64SArnaldo Carvalho de Melo 5547865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 555d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 55694c744b6SArnaldo Carvalho de Melo if (session == NULL) { 557a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 558a9a70bbcSArnaldo Carvalho de Melo return -1; 559a9a70bbcSArnaldo Carvalho de Melo } 560a9a70bbcSArnaldo Carvalho de Melo 561d20deb64SArnaldo Carvalho de Melo rec->session = session; 562d20deb64SArnaldo Carvalho de Melo 563781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 564781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 565781ba9d2SRobert Richter 566781ba9d2SRobert Richter if (rec->no_buildid) 567781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 568781ba9d2SRobert Richter 569781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 5702eeaaa09SStephane Eranian perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 571baa2f6ceSArnaldo Carvalho de Melo 572330aa675SStephane Eranian if (!rec->opts.branch_stack) 573330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 574330aa675SStephane Eranian 575d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 576a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 5774dc0a04bSArnaldo Carvalho de Melo if (err < 0) 57839d17dacSArnaldo Carvalho de Melo goto out_delete_session; 5794dc0a04bSArnaldo Carvalho de Melo } 5804dc0a04bSArnaldo Carvalho de Melo 581d4db3f16SArnaldo Carvalho de Melo if (forks) { 582d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 58335b9d88eSArnaldo Carvalho de Melo if (err < 0) { 58435b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 58535b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 586856e9660SPeter Zijlstra } 587856e9660SPeter Zijlstra } 588856e9660SPeter Zijlstra 5898d3eca20SDavid Ahern if (perf_record__open(rec) != 0) { 5908d3eca20SDavid Ahern err = -1; 5918d3eca20SDavid Ahern goto out_delete_session; 5928d3eca20SDavid Ahern } 59386470930SIngo Molnar 594712a4b60SArnaldo Carvalho de Melo /* 595d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 596712a4b60SArnaldo Carvalho de Melo */ 597d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 598712a4b60SArnaldo Carvalho de Melo 599d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 600529870e3STom Zanussi err = perf_header__write_pipe(output); 601529870e3STom Zanussi if (err < 0) 6028d3eca20SDavid Ahern goto out_delete_session; 603d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 604a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 605361c99a6SArnaldo Carvalho de Melo output, false); 606d5eed904SArnaldo Carvalho de Melo if (err < 0) 6078d3eca20SDavid Ahern goto out_delete_session; 608d5eed904SArnaldo Carvalho de Melo } 6097c6a1c65SPeter Zijlstra 610d3665498SDavid Ahern if (!rec->no_buildid 611e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 612d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 613e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 6148d3eca20SDavid Ahern err = -1; 6158d3eca20SDavid Ahern goto out_delete_session; 616e20960c0SRobert Richter } 617e20960c0SRobert Richter 618d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 6196122e4e4SArnaldo Carvalho de Melo 620743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 621743eb868SArnaldo Carvalho de Melo if (!machine) { 622743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 6238d3eca20SDavid Ahern err = -1; 6248d3eca20SDavid Ahern goto out_delete_session; 625743eb868SArnaldo Carvalho de Melo } 626743eb868SArnaldo Carvalho de Melo 627d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 62845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 629a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 6302c46dbb5STom Zanussi if (err < 0) { 6312c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 6328d3eca20SDavid Ahern goto out_delete_session; 6332c46dbb5STom Zanussi } 634cd19a035STom Zanussi 63545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 636743eb868SArnaldo Carvalho de Melo machine); 637cd19a035STom Zanussi if (err < 0) { 638cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 6398d3eca20SDavid Ahern goto out_delete_session; 640cd19a035STom Zanussi } 6419215545eSTom Zanussi 642361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 64363e0c771STom Zanussi /* 64463e0c771STom Zanussi * FIXME err <= 0 here actually means that 64563e0c771STom Zanussi * there were no tracepoints so its not really 64663e0c771STom Zanussi * an error, just that we don't need to 64763e0c771STom Zanussi * synthesize anything. We really have to 64863e0c771STom Zanussi * return this more properly and also 64963e0c771STom Zanussi * propagate errors that now are calling die() 65063e0c771STom Zanussi */ 65145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 652743eb868SArnaldo Carvalho de Melo process_synthesized_event); 65363e0c771STom Zanussi if (err <= 0) { 65463e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 6558d3eca20SDavid Ahern goto out_delete_session; 65663e0c771STom Zanussi } 657d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 6582c46dbb5STom Zanussi } 65963e0c771STom Zanussi } 6602c46dbb5STom Zanussi 66145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 662743eb868SArnaldo Carvalho de Melo machine, "_text"); 66370162138SArnaldo Carvalho de Melo if (err < 0) 66445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 665743eb868SArnaldo Carvalho de Melo machine, "_stext"); 666c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 667c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 668c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 669c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 67056b03f3cSArnaldo Carvalho de Melo 67145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 672743eb868SArnaldo Carvalho de Melo machine); 673c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 674c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 675c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 676c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 677c1a3a4b9SArnaldo Carvalho de Melo 678a1645ce1SZhang, Yanmin if (perf_guest) 67945694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 6808115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 681b7cece76SArnaldo Carvalho de Melo 682bea03405SNamhyung Kim if (!opts->target.system_wide) 6838d3eca20SDavid Ahern err = perf_event__synthesize_thread_map(tool, evsel_list->threads, 6848115d60cSArnaldo Carvalho de Melo process_synthesized_event, 685743eb868SArnaldo Carvalho de Melo machine); 686234fbbf5SArnaldo Carvalho de Melo else 6878d3eca20SDavid Ahern err = perf_event__synthesize_threads(tool, process_synthesized_event, 688743eb868SArnaldo Carvalho de Melo machine); 6897c6a1c65SPeter Zijlstra 6908d3eca20SDavid Ahern if (err != 0) 6918d3eca20SDavid Ahern goto out_delete_session; 6928d3eca20SDavid Ahern 693d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 69486470930SIngo Molnar struct sched_param param; 69586470930SIngo Molnar 696d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 69786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6986beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 6998d3eca20SDavid Ahern err = -1; 7008d3eca20SDavid Ahern goto out_delete_session; 70186470930SIngo Molnar } 70286470930SIngo Molnar } 70386470930SIngo Molnar 704*774cb499SJiri Olsa /* 705*774cb499SJiri Olsa * When perf is starting the traced process, all the events 706*774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 707*774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 708*774cb499SJiri Olsa */ 709*774cb499SJiri Olsa if (!perf_target__none(&opts->target)) 710764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 711764e16a3SDavid Ahern 712856e9660SPeter Zijlstra /* 713856e9660SPeter Zijlstra * Let the child rip 714856e9660SPeter Zijlstra */ 715d4db3f16SArnaldo Carvalho de Melo if (forks) 71635b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 717856e9660SPeter Zijlstra 718649c48a9SPeter Zijlstra for (;;) { 719d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 72086470930SIngo Molnar 7218d3eca20SDavid Ahern if (perf_record__mmap_read_all(rec) < 0) { 7228d3eca20SDavid Ahern err = -1; 7238d3eca20SDavid Ahern goto out_delete_session; 7248d3eca20SDavid Ahern } 72586470930SIngo Molnar 726d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 727649c48a9SPeter Zijlstra if (done) 728649c48a9SPeter Zijlstra break; 7295c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 7308b412664SPeter Zijlstra waking++; 7318b412664SPeter Zijlstra } 7328b412664SPeter Zijlstra 733*774cb499SJiri Olsa /* 734*774cb499SJiri Olsa * When perf is starting the traced process, at the end events 735*774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 736*774cb499SJiri Olsa * disable events in this case. 737*774cb499SJiri Olsa */ 738*774cb499SJiri Olsa if (done && !perf_target__none(&opts->target)) 7394152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 7408b412664SPeter Zijlstra } 7418b412664SPeter Zijlstra 74218483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 743b44308f5SArnaldo Carvalho de Melo return 0; 744b44308f5SArnaldo Carvalho de Melo 7458b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 74686470930SIngo Molnar 74786470930SIngo Molnar /* 74886470930SIngo Molnar * Approximate RIP event size: 24 bytes. 74986470930SIngo Molnar */ 75086470930SIngo Molnar fprintf(stderr, 7519486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 752d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 75386470930SIngo Molnar output_name, 754d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 75586470930SIngo Molnar 75686470930SIngo Molnar return 0; 75739d17dacSArnaldo Carvalho de Melo 75839d17dacSArnaldo Carvalho de Melo out_delete_session: 75939d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 76039d17dacSArnaldo Carvalho de Melo return err; 76186470930SIngo Molnar } 76286470930SIngo Molnar 763bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 764bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 765bdfebd84SRoberto Agostino Vitillo 766bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 767bdfebd84SRoberto Agostino Vitillo 768bdfebd84SRoberto Agostino Vitillo struct branch_mode { 769bdfebd84SRoberto Agostino Vitillo const char *name; 770bdfebd84SRoberto Agostino Vitillo int mode; 771bdfebd84SRoberto Agostino Vitillo }; 772bdfebd84SRoberto Agostino Vitillo 773bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 774bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 775bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 776bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 777bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 778bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 779bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 780bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 781bdfebd84SRoberto Agostino Vitillo BRANCH_END 782bdfebd84SRoberto Agostino Vitillo }; 783bdfebd84SRoberto Agostino Vitillo 784bdfebd84SRoberto Agostino Vitillo static int 785a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 786bdfebd84SRoberto Agostino Vitillo { 787bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 788bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 789bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 790bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 791bdfebd84SRoberto Agostino Vitillo 792bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 793bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 794a5aabdacSStephane Eranian char *s, *os = NULL, *p; 795bdfebd84SRoberto Agostino Vitillo int ret = -1; 796bdfebd84SRoberto Agostino Vitillo 797a5aabdacSStephane Eranian if (unset) 798a5aabdacSStephane Eranian return 0; 799bdfebd84SRoberto Agostino Vitillo 800a5aabdacSStephane Eranian /* 801a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 802a5aabdacSStephane Eranian */ 803a5aabdacSStephane Eranian if (*mode) 804a5aabdacSStephane Eranian return -1; 805a5aabdacSStephane Eranian 806a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 807a5aabdacSStephane Eranian if (str) { 808bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 809bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 810bdfebd84SRoberto Agostino Vitillo if (!s) 811bdfebd84SRoberto Agostino Vitillo return -1; 812bdfebd84SRoberto Agostino Vitillo 813bdfebd84SRoberto Agostino Vitillo for (;;) { 814bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 815bdfebd84SRoberto Agostino Vitillo if (p) 816bdfebd84SRoberto Agostino Vitillo *p = '\0'; 817bdfebd84SRoberto Agostino Vitillo 818bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 819bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 820bdfebd84SRoberto Agostino Vitillo break; 821bdfebd84SRoberto Agostino Vitillo } 822a5aabdacSStephane Eranian if (!br->name) { 823a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 824a5aabdacSStephane Eranian " check man page\n", s); 825bdfebd84SRoberto Agostino Vitillo goto error; 826a5aabdacSStephane Eranian } 827bdfebd84SRoberto Agostino Vitillo 828bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 829bdfebd84SRoberto Agostino Vitillo 830bdfebd84SRoberto Agostino Vitillo if (!p) 831bdfebd84SRoberto Agostino Vitillo break; 832bdfebd84SRoberto Agostino Vitillo 833bdfebd84SRoberto Agostino Vitillo s = p + 1; 834bdfebd84SRoberto Agostino Vitillo } 835a5aabdacSStephane Eranian } 836bdfebd84SRoberto Agostino Vitillo ret = 0; 837bdfebd84SRoberto Agostino Vitillo 838a5aabdacSStephane Eranian /* default to any branch */ 839bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 840a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 841bdfebd84SRoberto Agostino Vitillo } 842bdfebd84SRoberto Agostino Vitillo error: 843bdfebd84SRoberto Agostino Vitillo free(os); 844bdfebd84SRoberto Agostino Vitillo return ret; 845bdfebd84SRoberto Agostino Vitillo } 846bdfebd84SRoberto Agostino Vitillo 84795485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 84826d33022SJiri Olsa static int get_stack_size(char *str, unsigned long *_size) 84926d33022SJiri Olsa { 85026d33022SJiri Olsa char *endptr; 85126d33022SJiri Olsa unsigned long size; 85226d33022SJiri Olsa unsigned long max_size = round_down(USHRT_MAX, sizeof(u64)); 85326d33022SJiri Olsa 85426d33022SJiri Olsa size = strtoul(str, &endptr, 0); 85526d33022SJiri Olsa 85626d33022SJiri Olsa do { 85726d33022SJiri Olsa if (*endptr) 85826d33022SJiri Olsa break; 85926d33022SJiri Olsa 86026d33022SJiri Olsa size = round_up(size, sizeof(u64)); 86126d33022SJiri Olsa if (!size || size > max_size) 86226d33022SJiri Olsa break; 86326d33022SJiri Olsa 86426d33022SJiri Olsa *_size = size; 86526d33022SJiri Olsa return 0; 86626d33022SJiri Olsa 86726d33022SJiri Olsa } while (0); 86826d33022SJiri Olsa 86926d33022SJiri Olsa pr_err("callchain: Incorrect stack dump size (max %ld): %s\n", 87026d33022SJiri Olsa max_size, str); 87126d33022SJiri Olsa return -1; 87226d33022SJiri Olsa } 87395485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 87426d33022SJiri Olsa 87526d33022SJiri Olsa static int 8761d037ca1SIrina Tirdea parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, 87726d33022SJiri Olsa int unset) 87826d33022SJiri Olsa { 87926d33022SJiri Olsa struct perf_record *rec = (struct perf_record *)opt->value; 88026d33022SJiri Olsa char *tok, *name, *saveptr = NULL; 88126d33022SJiri Olsa char *buf; 88226d33022SJiri Olsa int ret = -1; 88326d33022SJiri Olsa 88426d33022SJiri Olsa /* --no-call-graph */ 88526d33022SJiri Olsa if (unset) 88626d33022SJiri Olsa return 0; 88726d33022SJiri Olsa 88826d33022SJiri Olsa /* We specified default option if none is provided. */ 88926d33022SJiri Olsa BUG_ON(!arg); 89026d33022SJiri Olsa 89126d33022SJiri Olsa /* We need buffer that we know we can write to. */ 89226d33022SJiri Olsa buf = malloc(strlen(arg) + 1); 89326d33022SJiri Olsa if (!buf) 89426d33022SJiri Olsa return -ENOMEM; 89526d33022SJiri Olsa 89626d33022SJiri Olsa strcpy(buf, arg); 89726d33022SJiri Olsa 89826d33022SJiri Olsa tok = strtok_r((char *)buf, ",", &saveptr); 89926d33022SJiri Olsa name = tok ? : (char *)buf; 90026d33022SJiri Olsa 90126d33022SJiri Olsa do { 90226d33022SJiri Olsa /* Framepointer style */ 90326d33022SJiri Olsa if (!strncmp(name, "fp", sizeof("fp"))) { 90426d33022SJiri Olsa if (!strtok_r(NULL, ",", &saveptr)) { 90526d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_FP; 90626d33022SJiri Olsa ret = 0; 90726d33022SJiri Olsa } else 90826d33022SJiri Olsa pr_err("callchain: No more arguments " 90926d33022SJiri Olsa "needed for -g fp\n"); 91026d33022SJiri Olsa break; 91126d33022SJiri Olsa 91295485b1cSNamhyung Kim #ifdef LIBUNWIND_SUPPORT 91326d33022SJiri Olsa /* Dwarf style */ 91426d33022SJiri Olsa } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 91561eaa3beSArnaldo Carvalho de Melo const unsigned long default_stack_dump_size = 8192; 91661eaa3beSArnaldo Carvalho de Melo 91726d33022SJiri Olsa ret = 0; 91826d33022SJiri Olsa rec->opts.call_graph = CALLCHAIN_DWARF; 91926d33022SJiri Olsa rec->opts.stack_dump_size = default_stack_dump_size; 92026d33022SJiri Olsa 92126d33022SJiri Olsa tok = strtok_r(NULL, ",", &saveptr); 92226d33022SJiri Olsa if (tok) { 92326d33022SJiri Olsa unsigned long size = 0; 92426d33022SJiri Olsa 92526d33022SJiri Olsa ret = get_stack_size(tok, &size); 92626d33022SJiri Olsa rec->opts.stack_dump_size = size; 92726d33022SJiri Olsa } 92826d33022SJiri Olsa 92926d33022SJiri Olsa if (!ret) 93026d33022SJiri Olsa pr_debug("callchain: stack dump size %d\n", 93126d33022SJiri Olsa rec->opts.stack_dump_size); 93295485b1cSNamhyung Kim #endif /* LIBUNWIND_SUPPORT */ 93326d33022SJiri Olsa } else { 93426d33022SJiri Olsa pr_err("callchain: Unknown -g option " 93526d33022SJiri Olsa "value: %s\n", arg); 93626d33022SJiri Olsa break; 93726d33022SJiri Olsa } 93826d33022SJiri Olsa 93926d33022SJiri Olsa } while (0); 94026d33022SJiri Olsa 94126d33022SJiri Olsa free(buf); 94226d33022SJiri Olsa 94326d33022SJiri Olsa if (!ret) 94426d33022SJiri Olsa pr_debug("callchain: type %d\n", rec->opts.call_graph); 94526d33022SJiri Olsa 94626d33022SJiri Olsa return ret; 94726d33022SJiri Olsa } 94826d33022SJiri Olsa 94986470930SIngo Molnar static const char * const record_usage[] = { 95086470930SIngo Molnar "perf record [<options>] [<command>]", 95186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 95286470930SIngo Molnar NULL 95386470930SIngo Molnar }; 95486470930SIngo Molnar 955d20deb64SArnaldo Carvalho de Melo /* 956d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 957d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 958d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 959d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 960d20deb64SArnaldo Carvalho de Melo * 961d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 962d20deb64SArnaldo Carvalho de Melo * 963d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 964d20deb64SArnaldo Carvalho de Melo */ 965d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 966d20deb64SArnaldo Carvalho de Melo .opts = { 967d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 968d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 969d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 970447a6013SArnaldo Carvalho de Melo .freq = 4000, 971d1cb9fceSNamhyung Kim .target = { 972d1cb9fceSNamhyung Kim .uses_mmap = true, 973d1cb9fceSNamhyung Kim }, 974d20deb64SArnaldo Carvalho de Melo }, 975d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 976d20deb64SArnaldo Carvalho de Melo .file_new = true, 977d20deb64SArnaldo Carvalho de Melo }; 9787865e817SFrederic Weisbecker 97961eaa3beSArnaldo Carvalho de Melo #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 98061eaa3beSArnaldo Carvalho de Melo 98161eaa3beSArnaldo Carvalho de Melo #ifdef LIBUNWIND_SUPPORT 98261eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 98361eaa3beSArnaldo Carvalho de Melo #else 98461eaa3beSArnaldo Carvalho de Melo static const char callchain_help[] = CALLCHAIN_HELP "[fp]"; 98561eaa3beSArnaldo Carvalho de Melo #endif 98661eaa3beSArnaldo Carvalho de Melo 987d20deb64SArnaldo Carvalho de Melo /* 988d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 989d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 990d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 991d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 992d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 993d20deb64SArnaldo Carvalho de Melo */ 994bca647aaSTom Zanussi const struct option record_options[] = { 995d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 99686470930SIngo Molnar "event selector. use 'perf list' to list available events", 997f120f9d5SJiri Olsa parse_events_option), 998d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 999c171b552SLi Zefan "event filter", parse_filter), 1000bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1001d6d901c2SZhang, Yanmin "record events on existing process id"), 1002bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1003d6d901c2SZhang, Yanmin "record events on existing thread id"), 1004d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 100586470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1006d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 1007acac03faSKirill Smelkov "collect data without buffering"), 1008d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1009daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1010bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 101186470930SIngo Molnar "system-wide collection from all CPUs"), 1012d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 101386470930SIngo Molnar "append to the output file to do incremental profiling"), 1014bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1015c45c6ea2SStephane Eranian "list of cpus to monitor"), 1016d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 10177865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 1018d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1019d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 102086470930SIngo Molnar "output file name"), 1021d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 10222e6cdf99SStephane Eranian "child tasks do not inherit counters"), 1023d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1024d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 102501c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 1026d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 102743bece79SLin Ming "put the counters into a counter group"), 102826d33022SJiri Olsa OPT_CALLBACK_DEFAULT('g', "call-graph", &record, "mode[,dump_size]", 102926d33022SJiri Olsa callchain_help, &parse_callchain_opt, 103026d33022SJiri Olsa "fp"), 1031c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 10323da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1033b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1034d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1035649c48a9SPeter Zijlstra "per thread counts"), 1036d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 10374bba828dSAnton Blanchard "Sample addresses"), 1038d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 10393e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 1040d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1041649c48a9SPeter Zijlstra "don't sample"), 1042d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 1043a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1044d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 1045baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1046d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1047023695d9SStephane Eranian "monitor event in cgroup name only", 1048023695d9SStephane Eranian parse_cgroups), 1049bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1050bea03405SNamhyung Kim "user to profile"), 1051a5aabdacSStephane Eranian 1052a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1053a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1054a5aabdacSStephane Eranian parse_branch_stack), 1055a5aabdacSStephane Eranian 1056a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1057a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1058bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 105986470930SIngo Molnar OPT_END() 106086470930SIngo Molnar }; 106186470930SIngo Molnar 10621d037ca1SIrina Tirdea int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 106386470930SIngo Molnar { 106469aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 106569aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 1066d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 1067d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 106816ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 106986470930SIngo Molnar 10707e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 1071361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 1072361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1073361c99a6SArnaldo Carvalho de Melo 1074d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 1075d20deb64SArnaldo Carvalho de Melo 1076bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1077a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 1078d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 1079bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 108086470930SIngo Molnar 1081d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 10823780f488SNamhyung Kim ui__error("Can't overwrite and append at the same time." 10837865e817SFrederic Weisbecker " You need to choose between -f and -A"); 1084bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 1085d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 1086d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 10877865e817SFrederic Weisbecker } else { 1088d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 10897865e817SFrederic Weisbecker } 10907865e817SFrederic Weisbecker 1091bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 10923780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 1093023695d9SStephane Eranian " system-wide mode\n"); 1094023695d9SStephane Eranian usage_with_options(record_usage, record_options); 1095023695d9SStephane Eranian } 1096023695d9SStephane Eranian 1097655000e7SArnaldo Carvalho de Melo symbol__init(); 1098baa2f6ceSArnaldo Carvalho de Melo 1099ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1100646aaea6SArnaldo Carvalho de Melo pr_warning( 1101646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1102ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1103646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1104646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1105646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1106646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1107646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1108ec80fde7SArnaldo Carvalho de Melo 1109d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 1110a1ac1d3cSStephane Eranian disable_buildid_cache(); 1111655000e7SArnaldo Carvalho de Melo 1112361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 1113361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 111469aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 111569aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 1116bbd36e5eSPeter Zijlstra } 111786470930SIngo Molnar 111816ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 111916ad2ffbSNamhyung Kim if (err) { 112016ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 112116ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 112216ad2ffbSNamhyung Kim } 11234bd0f2d2SNamhyung Kim 112416ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 112516ad2ffbSNamhyung Kim if (err) { 112616ad2ffbSNamhyung Kim int saved_errno = errno; 112716ad2ffbSNamhyung Kim 112816ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 11293780f488SNamhyung Kim ui__error("%s", errbuf); 113016ad2ffbSNamhyung Kim 113116ad2ffbSNamhyung Kim err = -saved_errno; 11320d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 113316ad2ffbSNamhyung Kim } 11340d37aa34SArnaldo Carvalho de Melo 113516ad2ffbSNamhyung Kim err = -ENOMEM; 1136b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 1137dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 113869aad6f1SArnaldo Carvalho de Melo 1139361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 11407289f83cSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos))) 1141ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 1142d6d901c2SZhang, Yanmin } 11435c581041SArnaldo Carvalho de Melo 1144d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 1145d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 1146d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 1147d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 1148f9212819SFrederic Weisbecker 11497e4ff9e3SMike Galbraith /* 11507e4ff9e3SMike Galbraith * User specified count overrides default frequency. 11517e4ff9e3SMike Galbraith */ 1152d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 1153d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 1154d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 1155d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 11567e4ff9e3SMike Galbraith } else { 11573780f488SNamhyung Kim ui__error("frequency and count are zero, aborting\n"); 115839d17dacSArnaldo Carvalho de Melo err = -EINVAL; 11595c581041SArnaldo Carvalho de Melo goto out_free_fd; 11607e4ff9e3SMike Galbraith } 11617e4ff9e3SMike Galbraith 1162d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 116339d17dacSArnaldo Carvalho de Melo out_free_fd: 11647e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 1165d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 1166d65a458bSArnaldo Carvalho de Melo symbol__exit(); 116739d17dacSArnaldo Carvalho de Melo return err; 116886470930SIngo Molnar } 1169