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; 2080c978128SArnaldo Carvalho de Melo fallback_missing_features: 2090c978128SArnaldo Carvalho de Melo if (opts->exclude_guest_missing) 2100c978128SArnaldo Carvalho de Melo attr->exclude_guest = attr->exclude_host = 0; 2119c90a61cSArnaldo Carvalho de Melo retry_sample_id: 212808e1226SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 2133da297a6SIngo Molnar try_again: 214ed80f581SArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 215d20deb64SArnaldo Carvalho de Melo opts->group, group_fd) < 0) { 21686470930SIngo Molnar int err = errno; 21786470930SIngo Molnar 218c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 219b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 220c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 221d20deb64SArnaldo Carvalho de Melo } else if (err == ENODEV && opts->cpu_list) { 222d6d901c2SZhang, Yanmin die("No such device - did you specify" 223d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 2240c978128SArnaldo Carvalho de Melo } else if (err == EINVAL) { 2250c978128SArnaldo Carvalho de Melo if (!opts->exclude_guest_missing && 2260c978128SArnaldo Carvalho de Melo (attr->exclude_guest || attr->exclude_host)) { 2270c978128SArnaldo Carvalho de Melo pr_debug("Old kernel, cannot exclude " 2280c978128SArnaldo Carvalho de Melo "guest or host samples.\n"); 2290c978128SArnaldo Carvalho de Melo opts->exclude_guest_missing = true; 2300c978128SArnaldo Carvalho de Melo goto fallback_missing_features; 231808e1226SArnaldo Carvalho de Melo } else if (!opts->sample_id_all_missing) { 2329c90a61cSArnaldo Carvalho de Melo /* 2339c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2349c90a61cSArnaldo Carvalho de Melo */ 235808e1226SArnaldo Carvalho de Melo opts->sample_id_all_missing = true; 236d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 237eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 238eac23d1cSIan Munsie 2399c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 240d6d901c2SZhang, Yanmin } 2410c978128SArnaldo Carvalho de Melo } 2423da297a6SIngo Molnar 2433da297a6SIngo Molnar /* 2443da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2453da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 2463da297a6SIngo Molnar * is always available even if no PMU support: 2473da297a6SIngo Molnar */ 248*5a7ed29cSRobert Richter if (err == ENOENT && attr->type == PERF_TYPE_HARDWARE 249f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2503da297a6SIngo Molnar 2513da297a6SIngo Molnar if (verbose) 252ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 253ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2543da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 255f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 2563da297a6SIngo Molnar goto try_again; 2573da297a6SIngo Molnar } 258ca6a4258SDavid Ahern 259ca6a4258SDavid Ahern if (err == ENOENT) { 260ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 261ca6a4258SDavid Ahern event_name(pos)); 262ca6a4258SDavid Ahern exit(EXIT_FAILURE); 263ca6a4258SDavid Ahern } 264ca6a4258SDavid Ahern 26530c806a0SIngo Molnar printf("\n"); 266d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 267dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 268bfd45118SSimon Kaempflein 269bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 270bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 271d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 272d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 273d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 274d6d901c2SZhang, Yanmin " force-enable it.\n"); 275bfd45118SSimon Kaempflein #endif 276bfd45118SSimon Kaempflein 277cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 2787c6a1c65SPeter Zijlstra } 2797c6a1c65SPeter Zijlstra } 2807c6a1c65SPeter Zijlstra 2810a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 2820a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2830a102479SFrederic Weisbecker strerror(errno)); 2840a102479SFrederic Weisbecker exit(-1); 2850a102479SFrederic Weisbecker } 2860a102479SFrederic Weisbecker 28718e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 28818e60939SNelson Elhage if (errno == EPERM) 28918e60939SNelson Elhage die("Permission error mapping pages.\n" 29018e60939SNelson Elhage "Consider increasing " 29118e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 29218e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 29318e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 29441d0d933SNelson Elhage else if (!is_power_of_2(opts->mmap_pages)) 29541d0d933SNelson Elhage die("--mmap_pages/-m value must be a power of two."); 29641d0d933SNelson Elhage 2970a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 29818e60939SNelson Elhage } 2990a27d7f9SArnaldo Carvalho de Melo 300d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 301a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 302a91e5431SArnaldo Carvalho de Melo else { 303a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 304a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 305a91e5431SArnaldo Carvalho de Melo exit(-1); 306dd7927f4SArnaldo Carvalho de Melo } 30786470930SIngo Molnar } 30886470930SIngo Molnar 309a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 310a91e5431SArnaldo Carvalho de Melo } 311a91e5431SArnaldo Carvalho de Melo 312d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 3136122e4e4SArnaldo Carvalho de Melo { 314d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3156122e4e4SArnaldo Carvalho de Melo 3169f591fd7SArnaldo Carvalho de Melo if (size == 0) 3179f591fd7SArnaldo Carvalho de Melo return 0; 3189f591fd7SArnaldo Carvalho de Melo 319d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 320d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 321d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3226122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3236122e4e4SArnaldo Carvalho de Melo } 3246122e4e4SArnaldo Carvalho de Melo 325d20deb64SArnaldo Carvalho de Melo static void perf_record__exit(int status __used, void *arg) 326f5970550SPeter Zijlstra { 327d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 328f5970550SPeter Zijlstra 329d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 330d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 331d20deb64SArnaldo Carvalho de Melo 332d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 333d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 334d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 335d20deb64SArnaldo Carvalho de Melo rec->output, true); 336d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 337d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 338d65a458bSArnaldo Carvalho de Melo symbol__exit(); 339c7929e47STom Zanussi } 340f5970550SPeter Zijlstra } 341f5970550SPeter Zijlstra 3428115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 343a1645ce1SZhang, Yanmin { 344a1645ce1SZhang, Yanmin int err; 34545694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 346a1645ce1SZhang, Yanmin 34723346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 348a1645ce1SZhang, Yanmin return; 349a1645ce1SZhang, Yanmin 350a1645ce1SZhang, Yanmin /* 351a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 352a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 353a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 354a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 355a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 356a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 357a1645ce1SZhang, Yanmin */ 35845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 359743eb868SArnaldo Carvalho de Melo machine); 360a1645ce1SZhang, Yanmin if (err < 0) 361a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 36223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 363a1645ce1SZhang, Yanmin 364a1645ce1SZhang, Yanmin /* 365a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 366a1645ce1SZhang, Yanmin * have no _text sometimes. 367a1645ce1SZhang, Yanmin */ 36845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 369743eb868SArnaldo Carvalho de Melo machine, "_text"); 370a1645ce1SZhang, Yanmin if (err < 0) 37145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 372743eb868SArnaldo Carvalho de Melo machine, "_stext"); 373a1645ce1SZhang, Yanmin if (err < 0) 374a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 37523346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 376a1645ce1SZhang, Yanmin } 377a1645ce1SZhang, Yanmin 37898402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 37998402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 38098402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 38198402807SFrederic Weisbecker }; 38298402807SFrederic Weisbecker 383d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read_all(struct perf_record *rec) 38498402807SFrederic Weisbecker { 3850e2e63ddSPeter Zijlstra int i; 38698402807SFrederic Weisbecker 387d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 388d20deb64SArnaldo Carvalho de Melo if (rec->evlist->mmap[i].base) 389d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read(rec, &rec->evlist->mmap[i]); 39098402807SFrederic Weisbecker } 39198402807SFrederic Weisbecker 392d20deb64SArnaldo Carvalho de Melo if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO)) 393d20deb64SArnaldo Carvalho de Melo write_output(rec, &finished_round_event, sizeof(finished_round_event)); 39498402807SFrederic Weisbecker } 39598402807SFrederic Weisbecker 396d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 39786470930SIngo Molnar { 39886470930SIngo Molnar struct stat st; 39986470930SIngo Molnar int flags; 400781ba9d2SRobert Richter int err, output, feat; 4018b412664SPeter Zijlstra unsigned long waking = 0; 40246be604bSZhang, Yanmin const bool forks = argc > 0; 40323346f21SArnaldo Carvalho de Melo struct machine *machine; 40445694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 405d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 406d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 407d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 408d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 40986470930SIngo Molnar 410d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 41133e49ea7SAndi Kleen 412d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 41386470930SIngo Molnar 414d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 415f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 416f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 41718483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 418f5970550SPeter Zijlstra 419d7065adbSFranck Bui-Huu if (!output_name) { 420d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 421d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 422d7065adbSFranck Bui-Huu else 423d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 424d7065adbSFranck Bui-Huu } 425d7065adbSFranck Bui-Huu if (output_name) { 426529870e3STom Zanussi if (!strcmp(output_name, "-")) 427d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 428529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 429d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 430b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 431b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 432b38d3464SArnaldo Carvalho de Melo output_name); 433b38d3464SArnaldo Carvalho de Melo unlink(oldname); 434b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 435b38d3464SArnaldo Carvalho de Melo } 436d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 437d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 438266e0e21SPierre Habouzit } 439d7065adbSFranck Bui-Huu } 44086470930SIngo Molnar 441f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 442d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 443d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 44486470930SIngo Molnar else 44586470930SIngo Molnar flags |= O_TRUNC; 44686470930SIngo Molnar 447d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 448529870e3STom Zanussi output = STDOUT_FILENO; 449529870e3STom Zanussi else 45086470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 45186470930SIngo Molnar if (output < 0) { 45286470930SIngo Molnar perror("failed to create output file"); 45386470930SIngo Molnar exit(-1); 45486470930SIngo Molnar } 45586470930SIngo Molnar 456d20deb64SArnaldo Carvalho de Melo rec->output = output; 457d20deb64SArnaldo Carvalho de Melo 4587865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 459d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 46094c744b6SArnaldo Carvalho de Melo if (session == NULL) { 461a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 462a9a70bbcSArnaldo Carvalho de Melo return -1; 463a9a70bbcSArnaldo Carvalho de Melo } 464a9a70bbcSArnaldo Carvalho de Melo 465d20deb64SArnaldo Carvalho de Melo rec->session = session; 466d20deb64SArnaldo Carvalho de Melo 467781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 468781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 469781ba9d2SRobert Richter 470781ba9d2SRobert Richter if (rec->no_buildid) 471781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 472781ba9d2SRobert Richter 473781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 474781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_TRACE_INFO); 475baa2f6ceSArnaldo Carvalho de Melo 476330aa675SStephane Eranian if (!rec->opts.branch_stack) 477330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 478330aa675SStephane Eranian 479d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 480a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4814dc0a04bSArnaldo Carvalho de Melo if (err < 0) 48239d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4834dc0a04bSArnaldo Carvalho de Melo } 4844dc0a04bSArnaldo Carvalho de Melo 485d4db3f16SArnaldo Carvalho de Melo if (forks) { 486d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 48735b9d88eSArnaldo Carvalho de Melo if (err < 0) { 48835b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 48935b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 490856e9660SPeter Zijlstra } 491856e9660SPeter Zijlstra } 492856e9660SPeter Zijlstra 493d20deb64SArnaldo Carvalho de Melo perf_record__open(rec); 49486470930SIngo Molnar 495712a4b60SArnaldo Carvalho de Melo /* 496d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 497712a4b60SArnaldo Carvalho de Melo */ 498d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 499712a4b60SArnaldo Carvalho de Melo 500d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 501529870e3STom Zanussi err = perf_header__write_pipe(output); 502529870e3STom Zanussi if (err < 0) 503529870e3STom Zanussi return err; 504d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 505a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 506361c99a6SArnaldo Carvalho de Melo output, false); 507d5eed904SArnaldo Carvalho de Melo if (err < 0) 508d5eed904SArnaldo Carvalho de Melo return err; 509d5eed904SArnaldo Carvalho de Melo } 5107c6a1c65SPeter Zijlstra 511d3665498SDavid Ahern if (!rec->no_buildid 512e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 513d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 514e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 515e20960c0SRobert Richter return -1; 516e20960c0SRobert Richter } 517e20960c0SRobert Richter 518d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5196122e4e4SArnaldo Carvalho de Melo 520743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 521743eb868SArnaldo Carvalho de Melo if (!machine) { 522743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 523743eb868SArnaldo Carvalho de Melo return -1; 524743eb868SArnaldo Carvalho de Melo } 525743eb868SArnaldo Carvalho de Melo 526d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 52745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 528a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5292c46dbb5STom Zanussi if (err < 0) { 5302c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5312c46dbb5STom Zanussi return err; 5322c46dbb5STom Zanussi } 533cd19a035STom Zanussi 53445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 535743eb868SArnaldo Carvalho de Melo machine); 536cd19a035STom Zanussi if (err < 0) { 537cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 538cd19a035STom Zanussi return err; 539cd19a035STom Zanussi } 5409215545eSTom Zanussi 541361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 54263e0c771STom Zanussi /* 54363e0c771STom Zanussi * FIXME err <= 0 here actually means that 54463e0c771STom Zanussi * there were no tracepoints so its not really 54563e0c771STom Zanussi * an error, just that we don't need to 54663e0c771STom Zanussi * synthesize anything. We really have to 54763e0c771STom Zanussi * return this more properly and also 54863e0c771STom Zanussi * propagate errors that now are calling die() 54963e0c771STom Zanussi */ 55045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 551743eb868SArnaldo Carvalho de Melo process_synthesized_event); 55263e0c771STom Zanussi if (err <= 0) { 55363e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 55463e0c771STom Zanussi return err; 55563e0c771STom Zanussi } 556d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 5572c46dbb5STom Zanussi } 55863e0c771STom Zanussi } 5592c46dbb5STom Zanussi 56045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 561743eb868SArnaldo Carvalho de Melo machine, "_text"); 56270162138SArnaldo Carvalho de Melo if (err < 0) 56345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 564743eb868SArnaldo Carvalho de Melo machine, "_stext"); 565c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 566c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 567c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 568c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 56956b03f3cSArnaldo Carvalho de Melo 57045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 571743eb868SArnaldo Carvalho de Melo machine); 572c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 573c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 574c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 575c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 576c1a3a4b9SArnaldo Carvalho de Melo 577a1645ce1SZhang, Yanmin if (perf_guest) 57845694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 5798115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 580b7cece76SArnaldo Carvalho de Melo 581d20deb64SArnaldo Carvalho de Melo if (!opts->system_wide) 58245694aa7SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(tool, evsel_list->threads, 5838115d60cSArnaldo Carvalho de Melo process_synthesized_event, 584743eb868SArnaldo Carvalho de Melo machine); 585234fbbf5SArnaldo Carvalho de Melo else 58645694aa7SArnaldo Carvalho de Melo perf_event__synthesize_threads(tool, process_synthesized_event, 587743eb868SArnaldo Carvalho de Melo machine); 5887c6a1c65SPeter Zijlstra 589d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 59086470930SIngo Molnar struct sched_param param; 59186470930SIngo Molnar 592d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 59386470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5946beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 59586470930SIngo Molnar exit(-1); 59686470930SIngo Molnar } 59786470930SIngo Molnar } 59886470930SIngo Molnar 599764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 600764e16a3SDavid Ahern 601856e9660SPeter Zijlstra /* 602856e9660SPeter Zijlstra * Let the child rip 603856e9660SPeter Zijlstra */ 604d4db3f16SArnaldo Carvalho de Melo if (forks) 60535b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 606856e9660SPeter Zijlstra 607649c48a9SPeter Zijlstra for (;;) { 608d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 60986470930SIngo Molnar 610d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read_all(rec); 61186470930SIngo Molnar 612d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 613649c48a9SPeter Zijlstra if (done) 614649c48a9SPeter Zijlstra break; 6155c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6168b412664SPeter Zijlstra waking++; 6178b412664SPeter Zijlstra } 6188b412664SPeter Zijlstra 6194152ab37SArnaldo Carvalho de Melo if (done) 6204152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6218b412664SPeter Zijlstra } 6228b412664SPeter Zijlstra 62318483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 624b44308f5SArnaldo Carvalho de Melo return 0; 625b44308f5SArnaldo Carvalho de Melo 6268b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 62786470930SIngo Molnar 62886470930SIngo Molnar /* 62986470930SIngo Molnar * Approximate RIP event size: 24 bytes. 63086470930SIngo Molnar */ 63186470930SIngo Molnar fprintf(stderr, 6329486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 633d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 63486470930SIngo Molnar output_name, 635d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 63686470930SIngo Molnar 63786470930SIngo Molnar return 0; 63839d17dacSArnaldo Carvalho de Melo 63939d17dacSArnaldo Carvalho de Melo out_delete_session: 64039d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 64139d17dacSArnaldo Carvalho de Melo return err; 64286470930SIngo Molnar } 64386470930SIngo Molnar 644bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 645bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 646bdfebd84SRoberto Agostino Vitillo 647bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 648bdfebd84SRoberto Agostino Vitillo 649bdfebd84SRoberto Agostino Vitillo struct branch_mode { 650bdfebd84SRoberto Agostino Vitillo const char *name; 651bdfebd84SRoberto Agostino Vitillo int mode; 652bdfebd84SRoberto Agostino Vitillo }; 653bdfebd84SRoberto Agostino Vitillo 654bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 655bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 656bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 657bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 658bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 659bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 660bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 661bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 662bdfebd84SRoberto Agostino Vitillo BRANCH_END 663bdfebd84SRoberto Agostino Vitillo }; 664bdfebd84SRoberto Agostino Vitillo 665bdfebd84SRoberto Agostino Vitillo static int 666a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 667bdfebd84SRoberto Agostino Vitillo { 668bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 669bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 670bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 671bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 672bdfebd84SRoberto Agostino Vitillo 673bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 674bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 675a5aabdacSStephane Eranian char *s, *os = NULL, *p; 676bdfebd84SRoberto Agostino Vitillo int ret = -1; 677bdfebd84SRoberto Agostino Vitillo 678a5aabdacSStephane Eranian if (unset) 679a5aabdacSStephane Eranian return 0; 680bdfebd84SRoberto Agostino Vitillo 681a5aabdacSStephane Eranian /* 682a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 683a5aabdacSStephane Eranian */ 684a5aabdacSStephane Eranian if (*mode) 685a5aabdacSStephane Eranian return -1; 686a5aabdacSStephane Eranian 687a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 688a5aabdacSStephane Eranian if (str) { 689bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 690bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 691bdfebd84SRoberto Agostino Vitillo if (!s) 692bdfebd84SRoberto Agostino Vitillo return -1; 693bdfebd84SRoberto Agostino Vitillo 694bdfebd84SRoberto Agostino Vitillo for (;;) { 695bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 696bdfebd84SRoberto Agostino Vitillo if (p) 697bdfebd84SRoberto Agostino Vitillo *p = '\0'; 698bdfebd84SRoberto Agostino Vitillo 699bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 700bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 701bdfebd84SRoberto Agostino Vitillo break; 702bdfebd84SRoberto Agostino Vitillo } 703a5aabdacSStephane Eranian if (!br->name) { 704a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 705a5aabdacSStephane Eranian " check man page\n", s); 706bdfebd84SRoberto Agostino Vitillo goto error; 707a5aabdacSStephane Eranian } 708bdfebd84SRoberto Agostino Vitillo 709bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 710bdfebd84SRoberto Agostino Vitillo 711bdfebd84SRoberto Agostino Vitillo if (!p) 712bdfebd84SRoberto Agostino Vitillo break; 713bdfebd84SRoberto Agostino Vitillo 714bdfebd84SRoberto Agostino Vitillo s = p + 1; 715bdfebd84SRoberto Agostino Vitillo } 716a5aabdacSStephane Eranian } 717bdfebd84SRoberto Agostino Vitillo ret = 0; 718bdfebd84SRoberto Agostino Vitillo 719a5aabdacSStephane Eranian /* default to any branch */ 720bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 721a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 722bdfebd84SRoberto Agostino Vitillo } 723bdfebd84SRoberto Agostino Vitillo error: 724bdfebd84SRoberto Agostino Vitillo free(os); 725bdfebd84SRoberto Agostino Vitillo return ret; 726bdfebd84SRoberto Agostino Vitillo } 727bdfebd84SRoberto Agostino Vitillo 72886470930SIngo Molnar static const char * const record_usage[] = { 72986470930SIngo Molnar "perf record [<options>] [<command>]", 73086470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 73186470930SIngo Molnar NULL 73286470930SIngo Molnar }; 73386470930SIngo Molnar 734d20deb64SArnaldo Carvalho de Melo /* 735d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 736d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 737d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 738d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 739d20deb64SArnaldo Carvalho de Melo * 740d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 741d20deb64SArnaldo Carvalho de Melo * 742d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 743d20deb64SArnaldo Carvalho de Melo */ 744d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 745d20deb64SArnaldo Carvalho de Melo .opts = { 746d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 747d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 748d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 749d20deb64SArnaldo Carvalho de Melo .freq = 1000, 750d20deb64SArnaldo Carvalho de Melo }, 751d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 752d20deb64SArnaldo Carvalho de Melo .file_new = true, 753d20deb64SArnaldo Carvalho de Melo }; 7547865e817SFrederic Weisbecker 755d20deb64SArnaldo Carvalho de Melo /* 756d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 757d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 758d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 759d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 760d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 761d20deb64SArnaldo Carvalho de Melo */ 762bca647aaSTom Zanussi const struct option record_options[] = { 763d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 76486470930SIngo Molnar "event selector. use 'perf list' to list available events", 765f120f9d5SJiri Olsa parse_events_option), 766d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 767c171b552SLi Zefan "event filter", parse_filter), 768b52956c9SDavid Ahern OPT_STRING('p', "pid", &record.opts.target_pid, "pid", 769d6d901c2SZhang, Yanmin "record events on existing process id"), 770b52956c9SDavid Ahern OPT_STRING('t', "tid", &record.opts.target_tid, "tid", 771d6d901c2SZhang, Yanmin "record events on existing thread id"), 772d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 77386470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 774d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 775acac03faSKirill Smelkov "collect data without buffering"), 776d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 777daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 778d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide, 77986470930SIngo Molnar "system-wide collection from all CPUs"), 780d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 78186470930SIngo Molnar "append to the output file to do incremental profiling"), 782d20deb64SArnaldo Carvalho de Melo OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu", 783c45c6ea2SStephane Eranian "list of cpus to monitor"), 784d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 7857865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 786d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 787d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 78886470930SIngo Molnar "output file name"), 789d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 7902e6cdf99SStephane Eranian "child tasks do not inherit counters"), 791d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 792d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 79301c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 794d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 79543bece79SLin Ming "put the counters into a counter group"), 796d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph, 7973efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 798c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7993da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 800b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 801d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 802649c48a9SPeter Zijlstra "per thread counts"), 803d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 8044bba828dSAnton Blanchard "Sample addresses"), 805d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 8063e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 807d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 808649c48a9SPeter Zijlstra "don't sample"), 809d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 810a1ac1d3cSStephane Eranian "do not update the buildid cache"), 811d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 812baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 813d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 814023695d9SStephane Eranian "monitor event in cgroup name only", 815023695d9SStephane Eranian parse_cgroups), 8160d37aa34SArnaldo Carvalho de Melo OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"), 817a5aabdacSStephane Eranian 818a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 819a5aabdacSStephane Eranian "branch any", "sample any taken branches", 820a5aabdacSStephane Eranian parse_branch_stack), 821a5aabdacSStephane Eranian 822a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 823a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 824bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 82586470930SIngo Molnar OPT_END() 82686470930SIngo Molnar }; 82786470930SIngo Molnar 828f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 82986470930SIngo Molnar { 83069aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 83169aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 832d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 833d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 83486470930SIngo Molnar 835fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 836fbe96f29SStephane Eranian 8377e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 838361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 839361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 840361c99a6SArnaldo Carvalho de Melo 841d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 842d20deb64SArnaldo Carvalho de Melo 843bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 844a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 845b52956c9SDavid Ahern if (!argc && !rec->opts.target_pid && !rec->opts.target_tid && 8460d37aa34SArnaldo Carvalho de Melo !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str) 847bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 84886470930SIngo Molnar 849d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 8507865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 8517865e817SFrederic Weisbecker " You need to choose between -f and -A"); 852bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 853d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 854d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 8557865e817SFrederic Weisbecker } else { 856d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 8577865e817SFrederic Weisbecker } 8587865e817SFrederic Weisbecker 859d20deb64SArnaldo Carvalho de Melo if (nr_cgroups && !rec->opts.system_wide) { 860023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 861023695d9SStephane Eranian " system-wide mode\n"); 862023695d9SStephane Eranian usage_with_options(record_usage, record_options); 863023695d9SStephane Eranian } 864023695d9SStephane Eranian 865655000e7SArnaldo Carvalho de Melo symbol__init(); 866baa2f6ceSArnaldo Carvalho de Melo 867ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 868646aaea6SArnaldo Carvalho de Melo pr_warning( 869646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 870ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 871646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 872646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 873646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 874646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 875646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 876ec80fde7SArnaldo Carvalho de Melo 877d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 878a1ac1d3cSStephane Eranian disable_buildid_cache(); 879655000e7SArnaldo Carvalho de Melo 880361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 881361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 88269aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 88369aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 884bbd36e5eSPeter Zijlstra } 88586470930SIngo Molnar 8860d37aa34SArnaldo Carvalho de Melo rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid, 8870d37aa34SArnaldo Carvalho de Melo rec->opts.target_pid); 8880d37aa34SArnaldo Carvalho de Melo if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1) 8890d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 8900d37aa34SArnaldo Carvalho de Melo 891b52956c9SDavid Ahern if (rec->opts.target_pid) 892d20deb64SArnaldo Carvalho de Melo rec->opts.target_tid = rec->opts.target_pid; 893d6d901c2SZhang, Yanmin 894d20deb64SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 8950d37aa34SArnaldo Carvalho de Melo rec->opts.target_tid, rec->opts.uid, 8960d37aa34SArnaldo Carvalho de Melo rec->opts.cpu_list) < 0) 897dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 89869aad6f1SArnaldo Carvalho de Melo 899361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 900ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 901ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 902d6d901c2SZhang, Yanmin } 9035c581041SArnaldo Carvalho de Melo 904d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 905d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 906d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 907d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 908f9212819SFrederic Weisbecker 9097e4ff9e3SMike Galbraith /* 9107e4ff9e3SMike Galbraith * User specified count overrides default frequency. 9117e4ff9e3SMike Galbraith */ 912d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 913d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 914d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 915d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 9167e4ff9e3SMike Galbraith } else { 9177e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 91839d17dacSArnaldo Carvalho de Melo err = -EINVAL; 9195c581041SArnaldo Carvalho de Melo goto out_free_fd; 9207e4ff9e3SMike Galbraith } 9217e4ff9e3SMike Galbraith 922d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 92339d17dacSArnaldo Carvalho de Melo out_free_fd: 9247e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 925d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 926d65a458bSArnaldo Carvalho de Melo symbol__exit(); 92739d17dacSArnaldo Carvalho de Melo return err; 92886470930SIngo Molnar } 929