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; 47*0d37aa34SArnaldo 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; 389d20deb64SArnaldo Carvalho de Melo int err, output; 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 456d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 457baa2f6ceSArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_BUILD_ID); 458baa2f6ceSArnaldo Carvalho de Melo 459d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 460a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4614dc0a04bSArnaldo Carvalho de Melo if (err < 0) 46239d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4634dc0a04bSArnaldo Carvalho de Melo } 4644dc0a04bSArnaldo Carvalho de Melo 465361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) 46694c744b6SArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 46703456a15SFrederic Weisbecker 468fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_HOSTNAME); 469fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_OSRELEASE); 470fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_ARCH); 471fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUDESC); 472fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NRCPUS); 473fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_EVENT_DESC); 474fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CMDLINE); 475fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_VERSION); 476fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); 477fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_TOTAL_MEM); 478fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 479fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUID); 480fbe96f29SStephane Eranian 481d4db3f16SArnaldo Carvalho de Melo if (forks) { 482d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 48335b9d88eSArnaldo Carvalho de Melo if (err < 0) { 48435b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 48535b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 486856e9660SPeter Zijlstra } 487856e9660SPeter Zijlstra } 488856e9660SPeter Zijlstra 489d20deb64SArnaldo Carvalho de Melo perf_record__open(rec); 49086470930SIngo Molnar 491712a4b60SArnaldo Carvalho de Melo /* 492d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 493712a4b60SArnaldo Carvalho de Melo */ 494d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 495712a4b60SArnaldo Carvalho de Melo 496d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 497529870e3STom Zanussi err = perf_header__write_pipe(output); 498529870e3STom Zanussi if (err < 0) 499529870e3STom Zanussi return err; 500d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 501a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 502361c99a6SArnaldo Carvalho de Melo output, false); 503d5eed904SArnaldo Carvalho de Melo if (err < 0) 504d5eed904SArnaldo Carvalho de Melo return err; 505d5eed904SArnaldo Carvalho de Melo } 5067c6a1c65SPeter Zijlstra 507e20960c0SRobert Richter if (!!rec->no_buildid 508e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 509e20960c0SRobert Richter pr_err("Couldn't generating buildids. " 510e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 511e20960c0SRobert Richter return -1; 512e20960c0SRobert Richter } 513e20960c0SRobert Richter 514d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5156122e4e4SArnaldo Carvalho de Melo 516743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 517743eb868SArnaldo Carvalho de Melo if (!machine) { 518743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 519743eb868SArnaldo Carvalho de Melo return -1; 520743eb868SArnaldo Carvalho de Melo } 521743eb868SArnaldo Carvalho de Melo 522d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 52345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 524a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5252c46dbb5STom Zanussi if (err < 0) { 5262c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5272c46dbb5STom Zanussi return err; 5282c46dbb5STom Zanussi } 529cd19a035STom Zanussi 53045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 531743eb868SArnaldo Carvalho de Melo machine); 532cd19a035STom Zanussi if (err < 0) { 533cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 534cd19a035STom Zanussi return err; 535cd19a035STom Zanussi } 5369215545eSTom Zanussi 537361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 53863e0c771STom Zanussi /* 53963e0c771STom Zanussi * FIXME err <= 0 here actually means that 54063e0c771STom Zanussi * there were no tracepoints so its not really 54163e0c771STom Zanussi * an error, just that we don't need to 54263e0c771STom Zanussi * synthesize anything. We really have to 54363e0c771STom Zanussi * return this more properly and also 54463e0c771STom Zanussi * propagate errors that now are calling die() 54563e0c771STom Zanussi */ 54645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 547743eb868SArnaldo Carvalho de Melo process_synthesized_event); 54863e0c771STom Zanussi if (err <= 0) { 54963e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 55063e0c771STom Zanussi return err; 55163e0c771STom Zanussi } 552d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 5532c46dbb5STom Zanussi } 55463e0c771STom Zanussi } 5552c46dbb5STom Zanussi 55645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 557743eb868SArnaldo Carvalho de Melo machine, "_text"); 55870162138SArnaldo Carvalho de Melo if (err < 0) 55945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 560743eb868SArnaldo Carvalho de Melo machine, "_stext"); 561c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 562c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 563c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 564c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 56556b03f3cSArnaldo Carvalho de Melo 56645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 567743eb868SArnaldo Carvalho de Melo machine); 568c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 569c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 570c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 571c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 572c1a3a4b9SArnaldo Carvalho de Melo 573a1645ce1SZhang, Yanmin if (perf_guest) 57445694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 5758115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 576b7cece76SArnaldo Carvalho de Melo 577d20deb64SArnaldo Carvalho de Melo if (!opts->system_wide) 57845694aa7SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(tool, evsel_list->threads, 5798115d60cSArnaldo Carvalho de Melo process_synthesized_event, 580743eb868SArnaldo Carvalho de Melo machine); 581234fbbf5SArnaldo Carvalho de Melo else 58245694aa7SArnaldo Carvalho de Melo perf_event__synthesize_threads(tool, process_synthesized_event, 583743eb868SArnaldo Carvalho de Melo machine); 5847c6a1c65SPeter Zijlstra 585d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 58686470930SIngo Molnar struct sched_param param; 58786470930SIngo Molnar 588d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 58986470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5906beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 59186470930SIngo Molnar exit(-1); 59286470930SIngo Molnar } 59386470930SIngo Molnar } 59486470930SIngo Molnar 595764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 596764e16a3SDavid Ahern 597856e9660SPeter Zijlstra /* 598856e9660SPeter Zijlstra * Let the child rip 599856e9660SPeter Zijlstra */ 600d4db3f16SArnaldo Carvalho de Melo if (forks) 60135b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 602856e9660SPeter Zijlstra 603649c48a9SPeter Zijlstra for (;;) { 604d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 60586470930SIngo Molnar 606d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read_all(rec); 60786470930SIngo Molnar 608d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 609649c48a9SPeter Zijlstra if (done) 610649c48a9SPeter Zijlstra break; 6115c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6128b412664SPeter Zijlstra waking++; 6138b412664SPeter Zijlstra } 6148b412664SPeter Zijlstra 6154152ab37SArnaldo Carvalho de Melo if (done) 6164152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6178b412664SPeter Zijlstra } 6188b412664SPeter Zijlstra 61918483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 620b44308f5SArnaldo Carvalho de Melo return 0; 621b44308f5SArnaldo Carvalho de Melo 6228b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 62386470930SIngo Molnar 62486470930SIngo Molnar /* 62586470930SIngo Molnar * Approximate RIP event size: 24 bytes. 62686470930SIngo Molnar */ 62786470930SIngo Molnar fprintf(stderr, 6289486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 629d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 63086470930SIngo Molnar output_name, 631d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 63286470930SIngo Molnar 63386470930SIngo Molnar return 0; 63439d17dacSArnaldo Carvalho de Melo 63539d17dacSArnaldo Carvalho de Melo out_delete_session: 63639d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 63739d17dacSArnaldo Carvalho de Melo return err; 63886470930SIngo Molnar } 63986470930SIngo Molnar 64086470930SIngo Molnar static const char * const record_usage[] = { 64186470930SIngo Molnar "perf record [<options>] [<command>]", 64286470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 64386470930SIngo Molnar NULL 64486470930SIngo Molnar }; 64586470930SIngo Molnar 646d20deb64SArnaldo Carvalho de Melo /* 647d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 648d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 649d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 650d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 651d20deb64SArnaldo Carvalho de Melo * 652d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 653d20deb64SArnaldo Carvalho de Melo * 654d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 655d20deb64SArnaldo Carvalho de Melo */ 656d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 657d20deb64SArnaldo Carvalho de Melo .opts = { 658d20deb64SArnaldo Carvalho de Melo .target_pid = -1, 659d20deb64SArnaldo Carvalho de Melo .target_tid = -1, 660d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 661d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 662d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 663d20deb64SArnaldo Carvalho de Melo .freq = 1000, 664d20deb64SArnaldo Carvalho de Melo .sample_id_all_avail = true, 665d20deb64SArnaldo Carvalho de Melo }, 666d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 667d20deb64SArnaldo Carvalho de Melo .file_new = true, 668d20deb64SArnaldo Carvalho de Melo }; 6697865e817SFrederic Weisbecker 670d20deb64SArnaldo Carvalho de Melo /* 671d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 672d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 673d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 674d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 675d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 676d20deb64SArnaldo Carvalho de Melo */ 677bca647aaSTom Zanussi const struct option record_options[] = { 678d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 67986470930SIngo Molnar "event selector. use 'perf list' to list available events", 680f120f9d5SJiri Olsa parse_events_option), 681d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 682c171b552SLi Zefan "event filter", parse_filter), 683d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('p', "pid", &record.opts.target_pid, 684d6d901c2SZhang, Yanmin "record events on existing process id"), 685d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('t', "tid", &record.opts.target_tid, 686d6d901c2SZhang, Yanmin "record events on existing thread id"), 687d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 68886470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 689d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 690acac03faSKirill Smelkov "collect data without buffering"), 691d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 692daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 693d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide, 69486470930SIngo Molnar "system-wide collection from all CPUs"), 695d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 69686470930SIngo Molnar "append to the output file to do incremental profiling"), 697d20deb64SArnaldo Carvalho de Melo OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu", 698c45c6ea2SStephane Eranian "list of cpus to monitor"), 699d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 7007865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 701d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 702d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 70386470930SIngo Molnar "output file name"), 704d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 7052e6cdf99SStephane Eranian "child tasks do not inherit counters"), 706d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 707d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 70801c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 709d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 71043bece79SLin Ming "put the counters into a counter group"), 711d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph, 7123efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 713c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7143da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 715b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 716d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 717649c48a9SPeter Zijlstra "per thread counts"), 718d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 7194bba828dSAnton Blanchard "Sample addresses"), 720d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 7213e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 722d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 723649c48a9SPeter Zijlstra "don't sample"), 724d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 725a1ac1d3cSStephane Eranian "do not update the buildid cache"), 726d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 727baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 728d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 729023695d9SStephane Eranian "monitor event in cgroup name only", 730023695d9SStephane Eranian parse_cgroups), 731*0d37aa34SArnaldo Carvalho de Melo OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"), 73286470930SIngo Molnar OPT_END() 73386470930SIngo Molnar }; 73486470930SIngo Molnar 735f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 73686470930SIngo Molnar { 73769aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 73869aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 739d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 740d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 74186470930SIngo Molnar 742fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 743fbe96f29SStephane Eranian 7447e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 745361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 746361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 747361c99a6SArnaldo Carvalho de Melo 748d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 749d20deb64SArnaldo Carvalho de Melo 750bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 751a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 752d20deb64SArnaldo Carvalho de Melo if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 753*0d37aa34SArnaldo Carvalho de Melo !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str) 754bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 75586470930SIngo Molnar 756d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 7577865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 7587865e817SFrederic Weisbecker " You need to choose between -f and -A"); 759bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 760d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 761d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 7627865e817SFrederic Weisbecker } else { 763d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 7647865e817SFrederic Weisbecker } 7657865e817SFrederic Weisbecker 766d20deb64SArnaldo Carvalho de Melo if (nr_cgroups && !rec->opts.system_wide) { 767023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 768023695d9SStephane Eranian " system-wide mode\n"); 769023695d9SStephane Eranian usage_with_options(record_usage, record_options); 770023695d9SStephane Eranian } 771023695d9SStephane Eranian 772655000e7SArnaldo Carvalho de Melo symbol__init(); 773baa2f6ceSArnaldo Carvalho de Melo 774ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 775646aaea6SArnaldo Carvalho de Melo pr_warning( 776646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 777ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 778646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 779646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 780646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 781646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 782646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 783ec80fde7SArnaldo Carvalho de Melo 784d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 785a1ac1d3cSStephane Eranian disable_buildid_cache(); 786655000e7SArnaldo Carvalho de Melo 787361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 788361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 78969aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 79069aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 791bbd36e5eSPeter Zijlstra } 79286470930SIngo Molnar 793*0d37aa34SArnaldo Carvalho de Melo rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid, 794*0d37aa34SArnaldo Carvalho de Melo rec->opts.target_pid); 795*0d37aa34SArnaldo Carvalho de Melo if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1) 796*0d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 797*0d37aa34SArnaldo Carvalho de Melo 798d20deb64SArnaldo Carvalho de Melo if (rec->opts.target_pid != -1) 799d20deb64SArnaldo Carvalho de Melo rec->opts.target_tid = rec->opts.target_pid; 800d6d901c2SZhang, Yanmin 801d20deb64SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 802*0d37aa34SArnaldo Carvalho de Melo rec->opts.target_tid, rec->opts.uid, 803*0d37aa34SArnaldo Carvalho de Melo rec->opts.cpu_list) < 0) 804dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 80569aad6f1SArnaldo Carvalho de Melo 806361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 807ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 808ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 809d6d901c2SZhang, Yanmin } 8105c581041SArnaldo Carvalho de Melo 811d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 812d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 813d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 814d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 815f9212819SFrederic Weisbecker 8167e4ff9e3SMike Galbraith /* 8177e4ff9e3SMike Galbraith * User specified count overrides default frequency. 8187e4ff9e3SMike Galbraith */ 819d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 820d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 821d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 822d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 8237e4ff9e3SMike Galbraith } else { 8247e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 82539d17dacSArnaldo Carvalho de Melo err = -EINVAL; 8265c581041SArnaldo Carvalho de Melo goto out_free_fd; 8277e4ff9e3SMike Galbraith } 8287e4ff9e3SMike Galbraith 829d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 83039d17dacSArnaldo Carvalho de Melo out_free_fd: 8317e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 832d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 833d65a458bSArnaldo Carvalho de Melo symbol__exit(); 83439d17dacSArnaldo Carvalho de Melo return err; 83586470930SIngo Molnar } 836