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 347865e817SFrederic Weisbecker enum write_mode_t { 357865e817SFrederic Weisbecker WRITE_FORCE, 367865e817SFrederic Weisbecker WRITE_APPEND 377865e817SFrederic Weisbecker }; 387865e817SFrederic Weisbecker 39d20deb64SArnaldo Carvalho de Melo struct perf_record { 4045694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 41d20deb64SArnaldo Carvalho de Melo struct perf_record_opts opts; 42d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 43d20deb64SArnaldo Carvalho de Melo const char *output_name; 44d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 45d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 46d20deb64SArnaldo Carvalho de Melo const char *progname; 470d37aa34SArnaldo Carvalho de Melo const char *uid_str; 48d20deb64SArnaldo Carvalho de Melo int output; 49d20deb64SArnaldo Carvalho de Melo unsigned int page_size; 50d20deb64SArnaldo Carvalho de Melo int realtime_prio; 51d20deb64SArnaldo Carvalho de Melo enum write_mode_t write_mode; 52d20deb64SArnaldo Carvalho de Melo bool no_buildid; 53d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 54d20deb64SArnaldo Carvalho de Melo bool force; 55d20deb64SArnaldo Carvalho de Melo bool file_new; 56d20deb64SArnaldo Carvalho de Melo bool append_file; 57d20deb64SArnaldo Carvalho de Melo long samples; 58d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 590f82ebc4SArnaldo Carvalho de Melo }; 6086470930SIngo Molnar 61d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 629215545eSTom Zanussi { 63d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 649215545eSTom Zanussi } 659215545eSTom Zanussi 66d20deb64SArnaldo Carvalho de Melo static void write_output(struct perf_record *rec, void *buf, size_t size) 67f5970550SPeter Zijlstra { 68f5970550SPeter Zijlstra while (size) { 69d20deb64SArnaldo Carvalho de Melo int ret = write(rec->output, buf, size); 70f5970550SPeter Zijlstra 71f5970550SPeter Zijlstra if (ret < 0) 72f5970550SPeter Zijlstra die("failed to write"); 73f5970550SPeter Zijlstra 74f5970550SPeter Zijlstra size -= ret; 75f5970550SPeter Zijlstra buf += ret; 76f5970550SPeter Zijlstra 77d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 78f5970550SPeter Zijlstra } 79f5970550SPeter Zijlstra } 80f5970550SPeter Zijlstra 8145694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 82d20deb64SArnaldo Carvalho de Melo union perf_event *event, 838d50e5b4SArnaldo Carvalho de Melo struct perf_sample *sample __used, 84743eb868SArnaldo Carvalho de Melo struct machine *machine __used) 85234fbbf5SArnaldo Carvalho de Melo { 8645694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 87d20deb64SArnaldo Carvalho de Melo write_output(rec, event, event->header.size); 88234fbbf5SArnaldo Carvalho de Melo return 0; 89234fbbf5SArnaldo Carvalho de Melo } 90234fbbf5SArnaldo Carvalho de Melo 91d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read(struct perf_record *rec, 92d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 9386470930SIngo Molnar { 94744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 9586470930SIngo Molnar unsigned int old = md->prev; 96d20deb64SArnaldo Carvalho de Melo unsigned char *data = md->base + rec->page_size; 9786470930SIngo Molnar unsigned long size; 9886470930SIngo Molnar void *buf; 9986470930SIngo Molnar 100dc82009aSArnaldo Carvalho de Melo if (old == head) 101dc82009aSArnaldo Carvalho de Melo return; 10286470930SIngo Molnar 103d20deb64SArnaldo Carvalho de Melo rec->samples++; 10486470930SIngo Molnar 10586470930SIngo Molnar size = head - old; 10686470930SIngo Molnar 10786470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 10886470930SIngo Molnar buf = &data[old & md->mask]; 10986470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 11086470930SIngo Molnar old += size; 11186470930SIngo Molnar 112d20deb64SArnaldo Carvalho de Melo write_output(rec, buf, size); 11386470930SIngo Molnar } 11486470930SIngo Molnar 11586470930SIngo Molnar buf = &data[old & md->mask]; 11686470930SIngo Molnar size = head - old; 11786470930SIngo Molnar old += size; 11886470930SIngo Molnar 119d20deb64SArnaldo Carvalho de Melo write_output(rec, buf, size); 12086470930SIngo Molnar 12186470930SIngo Molnar md->prev = old; 122115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 12386470930SIngo Molnar } 12486470930SIngo Molnar 12586470930SIngo Molnar static volatile int done = 0; 126f7b7c26eSPeter Zijlstra static volatile int signr = -1; 12733e49ea7SAndi Kleen static volatile int child_finished = 0; 12886470930SIngo Molnar 12986470930SIngo Molnar static void sig_handler(int sig) 13086470930SIngo Molnar { 13133e49ea7SAndi Kleen if (sig == SIGCHLD) 13233e49ea7SAndi Kleen child_finished = 1; 13333e49ea7SAndi Kleen 13486470930SIngo Molnar done = 1; 135f7b7c26eSPeter Zijlstra signr = sig; 136f7b7c26eSPeter Zijlstra } 137f7b7c26eSPeter Zijlstra 138d20deb64SArnaldo Carvalho de Melo static void perf_record__sig_exit(int exit_status __used, void *arg) 139f7b7c26eSPeter Zijlstra { 140d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 14133e49ea7SAndi Kleen int status; 14233e49ea7SAndi Kleen 143d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 14433e49ea7SAndi Kleen if (!child_finished) 145d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 146933da83aSChris Wilson 14733e49ea7SAndi Kleen wait(&status); 14833e49ea7SAndi Kleen if (WIFSIGNALED(status)) 149d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 15033e49ea7SAndi Kleen } 15133e49ea7SAndi Kleen 15218483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 153f7b7c26eSPeter Zijlstra return; 154f7b7c26eSPeter Zijlstra 155f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 156f7b7c26eSPeter Zijlstra kill(getpid(), signr); 15786470930SIngo Molnar } 15886470930SIngo Molnar 159a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 160a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 161a91e5431SArnaldo Carvalho de Melo { 162a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 163a91e5431SArnaldo Carvalho de Melo 164a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 165a91e5431SArnaldo Carvalho de Melo return false; 166a91e5431SArnaldo Carvalho de Melo 167a91e5431SArnaldo Carvalho de Melo pair = list_entry(other->entries.next, struct perf_evsel, node); 168a91e5431SArnaldo Carvalho de Melo 169a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 170a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 171a91e5431SArnaldo Carvalho de Melo return false; 172a91e5431SArnaldo Carvalho de Melo pair = list_entry(pair->node.next, struct perf_evsel, node); 173a91e5431SArnaldo Carvalho de Melo } 174a91e5431SArnaldo Carvalho de Melo 175a91e5431SArnaldo Carvalho de Melo return true; 176a91e5431SArnaldo Carvalho de Melo } 177a91e5431SArnaldo Carvalho de Melo 178d20deb64SArnaldo Carvalho de Melo static void perf_record__open(struct perf_record *rec) 179dd7927f4SArnaldo Carvalho de Melo { 180727ab04eSArnaldo Carvalho de Melo struct perf_evsel *pos, *first; 181d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 182d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 183d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 184dd7927f4SArnaldo Carvalho de Melo 185727ab04eSArnaldo Carvalho de Melo first = list_entry(evlist->entries.next, struct perf_evsel, node); 186727ab04eSArnaldo Carvalho de Melo 187d20deb64SArnaldo Carvalho de Melo perf_evlist__config_attrs(evlist, opts); 1880f82ebc4SArnaldo Carvalho de Melo 189dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 190dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 191727ab04eSArnaldo Carvalho de Melo struct xyarray *group_fd = NULL; 192dd7927f4SArnaldo Carvalho de Melo /* 193dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 194dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 195dd7927f4SArnaldo Carvalho de Melo * 196dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 197dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 198dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 199dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 200dd7927f4SArnaldo Carvalho de Melo * 201dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 202dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 203dd7927f4SArnaldo Carvalho de Melo */ 204dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 205dd7927f4SArnaldo Carvalho de Melo 206d20deb64SArnaldo Carvalho de Melo if (opts->group && pos != first) 207727ab04eSArnaldo Carvalho de Melo group_fd = first->fd; 2089c90a61cSArnaldo Carvalho de Melo retry_sample_id: 209d20deb64SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 2103da297a6SIngo Molnar try_again: 211ed80f581SArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 212d20deb64SArnaldo Carvalho de Melo opts->group, group_fd) < 0) { 21386470930SIngo Molnar int err = errno; 21486470930SIngo Molnar 215c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 216b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 217c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 218d20deb64SArnaldo Carvalho de Melo } else if (err == ENODEV && opts->cpu_list) { 219d6d901c2SZhang, Yanmin die("No such device - did you specify" 220d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 221d20deb64SArnaldo Carvalho de Melo } else if (err == EINVAL && opts->sample_id_all_avail) { 2229c90a61cSArnaldo Carvalho de Melo /* 2239c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2249c90a61cSArnaldo Carvalho de Melo */ 225d20deb64SArnaldo Carvalho de Melo opts->sample_id_all_avail = false; 226d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 227eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 228eac23d1cSIan Munsie 2299c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 230d6d901c2SZhang, Yanmin } 2313da297a6SIngo Molnar 2323da297a6SIngo Molnar /* 2333da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2343da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 2353da297a6SIngo Molnar * is always available even if no PMU support: 2363da297a6SIngo Molnar */ 2373da297a6SIngo Molnar if (attr->type == PERF_TYPE_HARDWARE 238f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2393da297a6SIngo Molnar 2403da297a6SIngo Molnar if (verbose) 241ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 242ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2433da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 244f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 2453da297a6SIngo Molnar goto try_again; 2463da297a6SIngo Molnar } 247ca6a4258SDavid Ahern 248ca6a4258SDavid Ahern if (err == ENOENT) { 249ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 250ca6a4258SDavid Ahern event_name(pos)); 251ca6a4258SDavid Ahern exit(EXIT_FAILURE); 252ca6a4258SDavid Ahern } 253ca6a4258SDavid Ahern 25430c806a0SIngo Molnar printf("\n"); 255d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 256dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 257bfd45118SSimon Kaempflein 258bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 259bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 260d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 261d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 262d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 263d6d901c2SZhang, Yanmin " force-enable it.\n"); 264bfd45118SSimon Kaempflein #endif 265bfd45118SSimon Kaempflein 266cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 2677c6a1c65SPeter Zijlstra } 2687c6a1c65SPeter Zijlstra } 2697c6a1c65SPeter Zijlstra 2700a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 2710a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2720a102479SFrederic Weisbecker strerror(errno)); 2730a102479SFrederic Weisbecker exit(-1); 2740a102479SFrederic Weisbecker } 2750a102479SFrederic Weisbecker 27618e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 27718e60939SNelson Elhage if (errno == EPERM) 27818e60939SNelson Elhage die("Permission error mapping pages.\n" 27918e60939SNelson Elhage "Consider increasing " 28018e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 28118e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 28218e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 28341d0d933SNelson Elhage else if (!is_power_of_2(opts->mmap_pages)) 28441d0d933SNelson Elhage die("--mmap_pages/-m value must be a power of two."); 28541d0d933SNelson Elhage 2860a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 28718e60939SNelson Elhage } 2880a27d7f9SArnaldo Carvalho de Melo 289d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 290a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 291a91e5431SArnaldo Carvalho de Melo else { 292a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 293a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 294a91e5431SArnaldo Carvalho de Melo exit(-1); 295dd7927f4SArnaldo Carvalho de Melo } 29686470930SIngo Molnar } 29786470930SIngo Molnar 298a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 299a91e5431SArnaldo Carvalho de Melo } 300a91e5431SArnaldo Carvalho de Melo 301d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 3026122e4e4SArnaldo Carvalho de Melo { 303d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3046122e4e4SArnaldo Carvalho de Melo 3059f591fd7SArnaldo Carvalho de Melo if (size == 0) 3069f591fd7SArnaldo Carvalho de Melo return 0; 3079f591fd7SArnaldo Carvalho de Melo 308d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 309d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 310d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3116122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3126122e4e4SArnaldo Carvalho de Melo } 3136122e4e4SArnaldo Carvalho de Melo 314d20deb64SArnaldo Carvalho de Melo static void perf_record__exit(int status __used, void *arg) 315f5970550SPeter Zijlstra { 316d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 317f5970550SPeter Zijlstra 318d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 319d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 320d20deb64SArnaldo Carvalho de Melo 321d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 322d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 323d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 324d20deb64SArnaldo Carvalho de Melo rec->output, true); 325d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 326d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 327d65a458bSArnaldo Carvalho de Melo symbol__exit(); 328c7929e47STom Zanussi } 329f5970550SPeter Zijlstra } 330f5970550SPeter Zijlstra 3318115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 332a1645ce1SZhang, Yanmin { 333a1645ce1SZhang, Yanmin int err; 33445694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 335a1645ce1SZhang, Yanmin 33623346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 337a1645ce1SZhang, Yanmin return; 338a1645ce1SZhang, Yanmin 339a1645ce1SZhang, Yanmin /* 340a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 341a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 342a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 343a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 344a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 345a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 346a1645ce1SZhang, Yanmin */ 34745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 348743eb868SArnaldo Carvalho de Melo machine); 349a1645ce1SZhang, Yanmin if (err < 0) 350a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 35123346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 352a1645ce1SZhang, Yanmin 353a1645ce1SZhang, Yanmin /* 354a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 355a1645ce1SZhang, Yanmin * have no _text sometimes. 356a1645ce1SZhang, Yanmin */ 35745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 358743eb868SArnaldo Carvalho de Melo machine, "_text"); 359a1645ce1SZhang, Yanmin if (err < 0) 36045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 361743eb868SArnaldo Carvalho de Melo machine, "_stext"); 362a1645ce1SZhang, Yanmin if (err < 0) 363a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 36423346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 365a1645ce1SZhang, Yanmin } 366a1645ce1SZhang, Yanmin 36798402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 36898402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 36998402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 37098402807SFrederic Weisbecker }; 37198402807SFrederic Weisbecker 372d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read_all(struct perf_record *rec) 37398402807SFrederic Weisbecker { 3740e2e63ddSPeter Zijlstra int i; 37598402807SFrederic Weisbecker 376d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 377d20deb64SArnaldo Carvalho de Melo if (rec->evlist->mmap[i].base) 378d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read(rec, &rec->evlist->mmap[i]); 37998402807SFrederic Weisbecker } 38098402807SFrederic Weisbecker 381d20deb64SArnaldo Carvalho de Melo if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO)) 382d20deb64SArnaldo Carvalho de Melo write_output(rec, &finished_round_event, sizeof(finished_round_event)); 38398402807SFrederic Weisbecker } 38498402807SFrederic Weisbecker 385d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 38686470930SIngo Molnar { 38786470930SIngo Molnar struct stat st; 38886470930SIngo Molnar int flags; 389781ba9d2SRobert Richter int err, output, feat; 3908b412664SPeter Zijlstra unsigned long waking = 0; 39146be604bSZhang, Yanmin const bool forks = argc > 0; 39223346f21SArnaldo Carvalho de Melo struct machine *machine; 39345694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 394d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 395d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 396d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 397d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 39886470930SIngo Molnar 399d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 40033e49ea7SAndi Kleen 401d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 40286470930SIngo Molnar 403d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 404f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 405f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 40618483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 407f5970550SPeter Zijlstra 408d7065adbSFranck Bui-Huu if (!output_name) { 409d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 410d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 411d7065adbSFranck Bui-Huu else 412d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 413d7065adbSFranck Bui-Huu } 414d7065adbSFranck Bui-Huu if (output_name) { 415529870e3STom Zanussi if (!strcmp(output_name, "-")) 416d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 417529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 418d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 419b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 420b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 421b38d3464SArnaldo Carvalho de Melo output_name); 422b38d3464SArnaldo Carvalho de Melo unlink(oldname); 423b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 424b38d3464SArnaldo Carvalho de Melo } 425d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 426d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 427266e0e21SPierre Habouzit } 428d7065adbSFranck Bui-Huu } 42986470930SIngo Molnar 430f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 431d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 432d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 43386470930SIngo Molnar else 43486470930SIngo Molnar flags |= O_TRUNC; 43586470930SIngo Molnar 436d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 437529870e3STom Zanussi output = STDOUT_FILENO; 438529870e3STom Zanussi else 43986470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 44086470930SIngo Molnar if (output < 0) { 44186470930SIngo Molnar perror("failed to create output file"); 44286470930SIngo Molnar exit(-1); 44386470930SIngo Molnar } 44486470930SIngo Molnar 445d20deb64SArnaldo Carvalho de Melo rec->output = output; 446d20deb64SArnaldo Carvalho de Melo 4477865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 448d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 44994c744b6SArnaldo Carvalho de Melo if (session == NULL) { 450a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 451a9a70bbcSArnaldo Carvalho de Melo return -1; 452a9a70bbcSArnaldo Carvalho de Melo } 453a9a70bbcSArnaldo Carvalho de Melo 454d20deb64SArnaldo Carvalho de Melo rec->session = session; 455d20deb64SArnaldo Carvalho de Melo 456781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 457781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 458781ba9d2SRobert Richter 459781ba9d2SRobert Richter if (rec->no_buildid) 460781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 461781ba9d2SRobert Richter 462781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 463781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_TRACE_INFO); 464baa2f6ceSArnaldo Carvalho de Melo 465d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 466a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4674dc0a04bSArnaldo Carvalho de Melo if (err < 0) 46839d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4694dc0a04bSArnaldo Carvalho de Melo } 4704dc0a04bSArnaldo Carvalho de Melo 471d4db3f16SArnaldo Carvalho de Melo if (forks) { 472d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 47335b9d88eSArnaldo Carvalho de Melo if (err < 0) { 47435b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 47535b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 476856e9660SPeter Zijlstra } 477856e9660SPeter Zijlstra } 478856e9660SPeter Zijlstra 479d20deb64SArnaldo Carvalho de Melo perf_record__open(rec); 48086470930SIngo Molnar 481712a4b60SArnaldo Carvalho de Melo /* 482d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 483712a4b60SArnaldo Carvalho de Melo */ 484d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 485712a4b60SArnaldo Carvalho de Melo 486d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 487529870e3STom Zanussi err = perf_header__write_pipe(output); 488529870e3STom Zanussi if (err < 0) 489529870e3STom Zanussi return err; 490d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 491a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 492361c99a6SArnaldo Carvalho de Melo output, false); 493d5eed904SArnaldo Carvalho de Melo if (err < 0) 494d5eed904SArnaldo Carvalho de Melo return err; 495d5eed904SArnaldo Carvalho de Melo } 4967c6a1c65SPeter Zijlstra 497*d3665498SDavid Ahern if (!rec->no_buildid 498e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 499*d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 500e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 501e20960c0SRobert Richter return -1; 502e20960c0SRobert Richter } 503e20960c0SRobert Richter 504d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5056122e4e4SArnaldo Carvalho de Melo 506743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 507743eb868SArnaldo Carvalho de Melo if (!machine) { 508743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 509743eb868SArnaldo Carvalho de Melo return -1; 510743eb868SArnaldo Carvalho de Melo } 511743eb868SArnaldo Carvalho de Melo 512d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 51345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 514a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5152c46dbb5STom Zanussi if (err < 0) { 5162c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5172c46dbb5STom Zanussi return err; 5182c46dbb5STom Zanussi } 519cd19a035STom Zanussi 52045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 521743eb868SArnaldo Carvalho de Melo machine); 522cd19a035STom Zanussi if (err < 0) { 523cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 524cd19a035STom Zanussi return err; 525cd19a035STom Zanussi } 5269215545eSTom Zanussi 527361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 52863e0c771STom Zanussi /* 52963e0c771STom Zanussi * FIXME err <= 0 here actually means that 53063e0c771STom Zanussi * there were no tracepoints so its not really 53163e0c771STom Zanussi * an error, just that we don't need to 53263e0c771STom Zanussi * synthesize anything. We really have to 53363e0c771STom Zanussi * return this more properly and also 53463e0c771STom Zanussi * propagate errors that now are calling die() 53563e0c771STom Zanussi */ 53645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 537743eb868SArnaldo Carvalho de Melo process_synthesized_event); 53863e0c771STom Zanussi if (err <= 0) { 53963e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 54063e0c771STom Zanussi return err; 54163e0c771STom Zanussi } 542d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 5432c46dbb5STom Zanussi } 54463e0c771STom Zanussi } 5452c46dbb5STom Zanussi 54645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 547743eb868SArnaldo Carvalho de Melo machine, "_text"); 54870162138SArnaldo Carvalho de Melo if (err < 0) 54945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 550743eb868SArnaldo Carvalho de Melo machine, "_stext"); 551c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 552c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 553c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 554c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 55556b03f3cSArnaldo Carvalho de Melo 55645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 557743eb868SArnaldo Carvalho de Melo machine); 558c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 559c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 560c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 561c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 562c1a3a4b9SArnaldo Carvalho de Melo 563a1645ce1SZhang, Yanmin if (perf_guest) 56445694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 5658115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 566b7cece76SArnaldo Carvalho de Melo 567d20deb64SArnaldo Carvalho de Melo if (!opts->system_wide) 56845694aa7SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(tool, evsel_list->threads, 5698115d60cSArnaldo Carvalho de Melo process_synthesized_event, 570743eb868SArnaldo Carvalho de Melo machine); 571234fbbf5SArnaldo Carvalho de Melo else 57245694aa7SArnaldo Carvalho de Melo perf_event__synthesize_threads(tool, process_synthesized_event, 573743eb868SArnaldo Carvalho de Melo machine); 5747c6a1c65SPeter Zijlstra 575d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 57686470930SIngo Molnar struct sched_param param; 57786470930SIngo Molnar 578d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 57986470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5806beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 58186470930SIngo Molnar exit(-1); 58286470930SIngo Molnar } 58386470930SIngo Molnar } 58486470930SIngo Molnar 585764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 586764e16a3SDavid Ahern 587856e9660SPeter Zijlstra /* 588856e9660SPeter Zijlstra * Let the child rip 589856e9660SPeter Zijlstra */ 590d4db3f16SArnaldo Carvalho de Melo if (forks) 59135b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 592856e9660SPeter Zijlstra 593649c48a9SPeter Zijlstra for (;;) { 594d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 59586470930SIngo Molnar 596d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read_all(rec); 59786470930SIngo Molnar 598d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 599649c48a9SPeter Zijlstra if (done) 600649c48a9SPeter Zijlstra break; 6015c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6028b412664SPeter Zijlstra waking++; 6038b412664SPeter Zijlstra } 6048b412664SPeter Zijlstra 6054152ab37SArnaldo Carvalho de Melo if (done) 6064152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6078b412664SPeter Zijlstra } 6088b412664SPeter Zijlstra 60918483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 610b44308f5SArnaldo Carvalho de Melo return 0; 611b44308f5SArnaldo Carvalho de Melo 6128b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 61386470930SIngo Molnar 61486470930SIngo Molnar /* 61586470930SIngo Molnar * Approximate RIP event size: 24 bytes. 61686470930SIngo Molnar */ 61786470930SIngo Molnar fprintf(stderr, 6189486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 619d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 62086470930SIngo Molnar output_name, 621d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 62286470930SIngo Molnar 62386470930SIngo Molnar return 0; 62439d17dacSArnaldo Carvalho de Melo 62539d17dacSArnaldo Carvalho de Melo out_delete_session: 62639d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 62739d17dacSArnaldo Carvalho de Melo return err; 62886470930SIngo Molnar } 62986470930SIngo Molnar 63086470930SIngo Molnar static const char * const record_usage[] = { 63186470930SIngo Molnar "perf record [<options>] [<command>]", 63286470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 63386470930SIngo Molnar NULL 63486470930SIngo Molnar }; 63586470930SIngo Molnar 636d20deb64SArnaldo Carvalho de Melo /* 637d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 638d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 639d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 640d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 641d20deb64SArnaldo Carvalho de Melo * 642d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 643d20deb64SArnaldo Carvalho de Melo * 644d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 645d20deb64SArnaldo Carvalho de Melo */ 646d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 647d20deb64SArnaldo Carvalho de Melo .opts = { 648d20deb64SArnaldo Carvalho de Melo .target_pid = -1, 649d20deb64SArnaldo Carvalho de Melo .target_tid = -1, 650d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 651d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 652d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 653d20deb64SArnaldo Carvalho de Melo .freq = 1000, 654d20deb64SArnaldo Carvalho de Melo .sample_id_all_avail = true, 655d20deb64SArnaldo Carvalho de Melo }, 656d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 657d20deb64SArnaldo Carvalho de Melo .file_new = true, 658d20deb64SArnaldo Carvalho de Melo }; 6597865e817SFrederic Weisbecker 660d20deb64SArnaldo Carvalho de Melo /* 661d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 662d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 663d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 664d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 665d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 666d20deb64SArnaldo Carvalho de Melo */ 667bca647aaSTom Zanussi const struct option record_options[] = { 668d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 66986470930SIngo Molnar "event selector. use 'perf list' to list available events", 670f120f9d5SJiri Olsa parse_events_option), 671d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 672c171b552SLi Zefan "event filter", parse_filter), 673d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('p', "pid", &record.opts.target_pid, 674d6d901c2SZhang, Yanmin "record events on existing process id"), 675d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('t', "tid", &record.opts.target_tid, 676d6d901c2SZhang, Yanmin "record events on existing thread id"), 677d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 67886470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 679d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 680acac03faSKirill Smelkov "collect data without buffering"), 681d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 682daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 683d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide, 68486470930SIngo Molnar "system-wide collection from all CPUs"), 685d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 68686470930SIngo Molnar "append to the output file to do incremental profiling"), 687d20deb64SArnaldo Carvalho de Melo OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu", 688c45c6ea2SStephane Eranian "list of cpus to monitor"), 689d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 6907865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 691d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 692d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 69386470930SIngo Molnar "output file name"), 694d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 6952e6cdf99SStephane Eranian "child tasks do not inherit counters"), 696d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 697d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 69801c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 699d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 70043bece79SLin Ming "put the counters into a counter group"), 701d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph, 7023efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 703c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7043da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 705b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 706d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 707649c48a9SPeter Zijlstra "per thread counts"), 708d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 7094bba828dSAnton Blanchard "Sample addresses"), 710d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 7113e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 712d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 713649c48a9SPeter Zijlstra "don't sample"), 714d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 715a1ac1d3cSStephane Eranian "do not update the buildid cache"), 716d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 717baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 718d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 719023695d9SStephane Eranian "monitor event in cgroup name only", 720023695d9SStephane Eranian parse_cgroups), 7210d37aa34SArnaldo Carvalho de Melo OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"), 72286470930SIngo Molnar OPT_END() 72386470930SIngo Molnar }; 72486470930SIngo Molnar 725f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 72686470930SIngo Molnar { 72769aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 72869aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 729d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 730d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 73186470930SIngo Molnar 732fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 733fbe96f29SStephane Eranian 7347e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 735361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 736361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 737361c99a6SArnaldo Carvalho de Melo 738d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 739d20deb64SArnaldo Carvalho de Melo 740bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 741a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 742d20deb64SArnaldo Carvalho de Melo if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 7430d37aa34SArnaldo Carvalho de Melo !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str) 744bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 74586470930SIngo Molnar 746d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 7477865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 7487865e817SFrederic Weisbecker " You need to choose between -f and -A"); 749bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 750d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 751d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 7527865e817SFrederic Weisbecker } else { 753d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 7547865e817SFrederic Weisbecker } 7557865e817SFrederic Weisbecker 756d20deb64SArnaldo Carvalho de Melo if (nr_cgroups && !rec->opts.system_wide) { 757023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 758023695d9SStephane Eranian " system-wide mode\n"); 759023695d9SStephane Eranian usage_with_options(record_usage, record_options); 760023695d9SStephane Eranian } 761023695d9SStephane Eranian 762655000e7SArnaldo Carvalho de Melo symbol__init(); 763baa2f6ceSArnaldo Carvalho de Melo 764ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 765646aaea6SArnaldo Carvalho de Melo pr_warning( 766646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 767ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 768646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 769646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 770646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 771646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 772646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 773ec80fde7SArnaldo Carvalho de Melo 774d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 775a1ac1d3cSStephane Eranian disable_buildid_cache(); 776655000e7SArnaldo Carvalho de Melo 777361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 778361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 77969aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 78069aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 781bbd36e5eSPeter Zijlstra } 78286470930SIngo Molnar 7830d37aa34SArnaldo Carvalho de Melo rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid, 7840d37aa34SArnaldo Carvalho de Melo rec->opts.target_pid); 7850d37aa34SArnaldo Carvalho de Melo if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1) 7860d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 7870d37aa34SArnaldo Carvalho de Melo 788d20deb64SArnaldo Carvalho de Melo if (rec->opts.target_pid != -1) 789d20deb64SArnaldo Carvalho de Melo rec->opts.target_tid = rec->opts.target_pid; 790d6d901c2SZhang, Yanmin 791d20deb64SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 7920d37aa34SArnaldo Carvalho de Melo rec->opts.target_tid, rec->opts.uid, 7930d37aa34SArnaldo Carvalho de Melo rec->opts.cpu_list) < 0) 794dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 79569aad6f1SArnaldo Carvalho de Melo 796361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 797ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 798ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 799d6d901c2SZhang, Yanmin } 8005c581041SArnaldo Carvalho de Melo 801d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 802d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 803d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 804d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 805f9212819SFrederic Weisbecker 8067e4ff9e3SMike Galbraith /* 8077e4ff9e3SMike Galbraith * User specified count overrides default frequency. 8087e4ff9e3SMike Galbraith */ 809d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 810d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 811d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 812d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 8137e4ff9e3SMike Galbraith } else { 8147e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 81539d17dacSArnaldo Carvalho de Melo err = -EINVAL; 8165c581041SArnaldo Carvalho de Melo goto out_free_fd; 8177e4ff9e3SMike Galbraith } 8187e4ff9e3SMike Galbraith 819d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 82039d17dacSArnaldo Carvalho de Melo out_free_fd: 8217e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 822d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 823d65a458bSArnaldo Carvalho de Melo symbol__exit(); 82439d17dacSArnaldo Carvalho de Melo return err; 82586470930SIngo Molnar } 826