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; 47d20deb64SArnaldo Carvalho de Melo int output; 48d20deb64SArnaldo Carvalho de Melo unsigned int page_size; 49d20deb64SArnaldo Carvalho de Melo int realtime_prio; 50d20deb64SArnaldo Carvalho de Melo enum write_mode_t write_mode; 51d20deb64SArnaldo Carvalho de Melo bool no_buildid; 52d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 53d20deb64SArnaldo Carvalho de Melo bool force; 54d20deb64SArnaldo Carvalho de Melo bool file_new; 55d20deb64SArnaldo Carvalho de Melo bool append_file; 56d20deb64SArnaldo Carvalho de Melo long samples; 57d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 580f82ebc4SArnaldo Carvalho de Melo }; 5986470930SIngo Molnar 60d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 619215545eSTom Zanussi { 62d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 639215545eSTom Zanussi } 649215545eSTom Zanussi 65d20deb64SArnaldo Carvalho de Melo static void write_output(struct perf_record *rec, void *buf, size_t size) 66f5970550SPeter Zijlstra { 67f5970550SPeter Zijlstra while (size) { 68d20deb64SArnaldo Carvalho de Melo int ret = write(rec->output, buf, size); 69f5970550SPeter Zijlstra 70f5970550SPeter Zijlstra if (ret < 0) 71f5970550SPeter Zijlstra die("failed to write"); 72f5970550SPeter Zijlstra 73f5970550SPeter Zijlstra size -= ret; 74f5970550SPeter Zijlstra buf += ret; 75f5970550SPeter Zijlstra 76d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 77f5970550SPeter Zijlstra } 78f5970550SPeter Zijlstra } 79f5970550SPeter Zijlstra 8045694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 81d20deb64SArnaldo Carvalho de Melo union perf_event *event, 828d50e5b4SArnaldo Carvalho de Melo struct perf_sample *sample __used, 83743eb868SArnaldo Carvalho de Melo struct machine *machine __used) 84234fbbf5SArnaldo Carvalho de Melo { 8545694aa7SArnaldo Carvalho de Melo struct perf_record *rec = container_of(tool, struct perf_record, tool); 86d20deb64SArnaldo Carvalho de Melo write_output(rec, event, event->header.size); 87234fbbf5SArnaldo Carvalho de Melo return 0; 88234fbbf5SArnaldo Carvalho de Melo } 89234fbbf5SArnaldo Carvalho de Melo 90d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read(struct perf_record *rec, 91d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 9286470930SIngo Molnar { 93744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 9486470930SIngo Molnar unsigned int old = md->prev; 95d20deb64SArnaldo Carvalho de Melo unsigned char *data = md->base + rec->page_size; 9686470930SIngo Molnar unsigned long size; 9786470930SIngo Molnar void *buf; 9886470930SIngo Molnar 99dc82009aSArnaldo Carvalho de Melo if (old == head) 100dc82009aSArnaldo Carvalho de Melo return; 10186470930SIngo Molnar 102d20deb64SArnaldo Carvalho de Melo rec->samples++; 10386470930SIngo Molnar 10486470930SIngo Molnar size = head - old; 10586470930SIngo Molnar 10686470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 10786470930SIngo Molnar buf = &data[old & md->mask]; 10886470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 10986470930SIngo Molnar old += size; 11086470930SIngo Molnar 111d20deb64SArnaldo Carvalho de Melo write_output(rec, buf, size); 11286470930SIngo Molnar } 11386470930SIngo Molnar 11486470930SIngo Molnar buf = &data[old & md->mask]; 11586470930SIngo Molnar size = head - old; 11686470930SIngo Molnar old += size; 11786470930SIngo Molnar 118d20deb64SArnaldo Carvalho de Melo write_output(rec, buf, size); 11986470930SIngo Molnar 12086470930SIngo Molnar md->prev = old; 121115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 12286470930SIngo Molnar } 12386470930SIngo Molnar 12486470930SIngo Molnar static volatile int done = 0; 125f7b7c26eSPeter Zijlstra static volatile int signr = -1; 12633e49ea7SAndi Kleen static volatile int child_finished = 0; 12786470930SIngo Molnar 12886470930SIngo Molnar static void sig_handler(int sig) 12986470930SIngo Molnar { 13033e49ea7SAndi Kleen if (sig == SIGCHLD) 13133e49ea7SAndi Kleen child_finished = 1; 13233e49ea7SAndi Kleen 13386470930SIngo Molnar done = 1; 134f7b7c26eSPeter Zijlstra signr = sig; 135f7b7c26eSPeter Zijlstra } 136f7b7c26eSPeter Zijlstra 137d20deb64SArnaldo Carvalho de Melo static void perf_record__sig_exit(int exit_status __used, void *arg) 138f7b7c26eSPeter Zijlstra { 139d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 14033e49ea7SAndi Kleen int status; 14133e49ea7SAndi Kleen 142d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 14333e49ea7SAndi Kleen if (!child_finished) 144d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 145933da83aSChris Wilson 14633e49ea7SAndi Kleen wait(&status); 14733e49ea7SAndi Kleen if (WIFSIGNALED(status)) 148d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 14933e49ea7SAndi Kleen } 15033e49ea7SAndi Kleen 15118483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 152f7b7c26eSPeter Zijlstra return; 153f7b7c26eSPeter Zijlstra 154f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 155f7b7c26eSPeter Zijlstra kill(getpid(), signr); 15686470930SIngo Molnar } 15786470930SIngo Molnar 158a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 159a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 160a91e5431SArnaldo Carvalho de Melo { 161a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 162a91e5431SArnaldo Carvalho de Melo 163a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 164a91e5431SArnaldo Carvalho de Melo return false; 165a91e5431SArnaldo Carvalho de Melo 166a91e5431SArnaldo Carvalho de Melo pair = list_entry(other->entries.next, struct perf_evsel, node); 167a91e5431SArnaldo Carvalho de Melo 168a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 169a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 170a91e5431SArnaldo Carvalho de Melo return false; 171a91e5431SArnaldo Carvalho de Melo pair = list_entry(pair->node.next, struct perf_evsel, node); 172a91e5431SArnaldo Carvalho de Melo } 173a91e5431SArnaldo Carvalho de Melo 174a91e5431SArnaldo Carvalho de Melo return true; 175a91e5431SArnaldo Carvalho de Melo } 176a91e5431SArnaldo Carvalho de Melo 177d20deb64SArnaldo Carvalho de Melo static void perf_record__open(struct perf_record *rec) 178dd7927f4SArnaldo Carvalho de Melo { 179727ab04eSArnaldo Carvalho de Melo struct perf_evsel *pos, *first; 180d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 181d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 182d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 183dd7927f4SArnaldo Carvalho de Melo 184727ab04eSArnaldo Carvalho de Melo first = list_entry(evlist->entries.next, struct perf_evsel, node); 185727ab04eSArnaldo Carvalho de Melo 186d20deb64SArnaldo Carvalho de Melo perf_evlist__config_attrs(evlist, opts); 1870f82ebc4SArnaldo Carvalho de Melo 188dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 189dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 190727ab04eSArnaldo Carvalho de Melo struct xyarray *group_fd = NULL; 191dd7927f4SArnaldo Carvalho de Melo /* 192dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 193dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 194dd7927f4SArnaldo Carvalho de Melo * 195dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 196dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 197dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 198dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 199dd7927f4SArnaldo Carvalho de Melo * 200dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 201dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 202dd7927f4SArnaldo Carvalho de Melo */ 203dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 204dd7927f4SArnaldo Carvalho de Melo 205d20deb64SArnaldo Carvalho de Melo if (opts->group && pos != first) 206727ab04eSArnaldo Carvalho de Melo group_fd = first->fd; 2070c978128SArnaldo Carvalho de Melo fallback_missing_features: 2080c978128SArnaldo Carvalho de Melo if (opts->exclude_guest_missing) 2090c978128SArnaldo Carvalho de Melo attr->exclude_guest = attr->exclude_host = 0; 2109c90a61cSArnaldo Carvalho de Melo retry_sample_id: 211808e1226SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; 2123da297a6SIngo Molnar try_again: 213ed80f581SArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 214d20deb64SArnaldo Carvalho de Melo opts->group, group_fd) < 0) { 21586470930SIngo Molnar int err = errno; 21686470930SIngo Molnar 217c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 218b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 219c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 220bea03405SNamhyung Kim } else if (err == ENODEV && opts->target.cpu_list) { 221d6d901c2SZhang, Yanmin die("No such device - did you specify" 222d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 2230c978128SArnaldo Carvalho de Melo } else if (err == EINVAL) { 2240c978128SArnaldo Carvalho de Melo if (!opts->exclude_guest_missing && 2250c978128SArnaldo Carvalho de Melo (attr->exclude_guest || attr->exclude_host)) { 2260c978128SArnaldo Carvalho de Melo pr_debug("Old kernel, cannot exclude " 2270c978128SArnaldo Carvalho de Melo "guest or host samples.\n"); 2280c978128SArnaldo Carvalho de Melo opts->exclude_guest_missing = true; 2290c978128SArnaldo Carvalho de Melo goto fallback_missing_features; 230808e1226SArnaldo Carvalho de Melo } else if (!opts->sample_id_all_missing) { 2319c90a61cSArnaldo Carvalho de Melo /* 2329c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2339c90a61cSArnaldo Carvalho de Melo */ 234808e1226SArnaldo Carvalho de Melo opts->sample_id_all_missing = true; 235d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 236eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 237eac23d1cSIan Munsie 2389c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 239d6d901c2SZhang, Yanmin } 2400c978128SArnaldo Carvalho de Melo } 2413da297a6SIngo Molnar 2423da297a6SIngo Molnar /* 2433da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2443da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 245028d455bSDavid Ahern * is always available even if no PMU support. 246028d455bSDavid Ahern * 247028d455bSDavid Ahern * PPC returns ENXIO until 2.6.37 (behavior changed 248028d455bSDavid Ahern * with commit b0a873e). 2493da297a6SIngo Molnar */ 250028d455bSDavid Ahern if ((err == ENOENT || err == ENXIO) 251028d455bSDavid Ahern && attr->type == PERF_TYPE_HARDWARE 252f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2533da297a6SIngo Molnar 2543da297a6SIngo Molnar if (verbose) 255ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 256ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2573da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 258f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 259d1cae34dSDavid Ahern if (pos->name) { 260d1cae34dSDavid Ahern free(pos->name); 261d1cae34dSDavid Ahern pos->name = NULL; 262d1cae34dSDavid Ahern } 2633da297a6SIngo Molnar goto try_again; 2643da297a6SIngo Molnar } 265ca6a4258SDavid Ahern 266ca6a4258SDavid Ahern if (err == ENOENT) { 2673780f488SNamhyung Kim ui__error("The %s event is not supported.\n", 268*7289f83cSArnaldo Carvalho de Melo perf_evsel__name(pos)); 269ca6a4258SDavid Ahern exit(EXIT_FAILURE); 270ca6a4258SDavid Ahern } 271ca6a4258SDavid Ahern 27230c806a0SIngo Molnar printf("\n"); 273d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 274dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 275bfd45118SSimon Kaempflein 276bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 277bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 278d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 279d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 280d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 281d6d901c2SZhang, Yanmin " force-enable it.\n"); 282bfd45118SSimon Kaempflein #endif 283bfd45118SSimon Kaempflein 284cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 2857c6a1c65SPeter Zijlstra } 2867c6a1c65SPeter Zijlstra } 2877c6a1c65SPeter Zijlstra 2880a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 2890a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2900a102479SFrederic Weisbecker strerror(errno)); 2910a102479SFrederic Weisbecker exit(-1); 2920a102479SFrederic Weisbecker } 2930a102479SFrederic Weisbecker 29418e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 29518e60939SNelson Elhage if (errno == EPERM) 29618e60939SNelson Elhage die("Permission error mapping pages.\n" 29718e60939SNelson Elhage "Consider increasing " 29818e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 29918e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 30018e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 30141d0d933SNelson Elhage else if (!is_power_of_2(opts->mmap_pages)) 30241d0d933SNelson Elhage die("--mmap_pages/-m value must be a power of two."); 30341d0d933SNelson Elhage 3040a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 30518e60939SNelson Elhage } 3060a27d7f9SArnaldo Carvalho de Melo 307d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 308a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 309a91e5431SArnaldo Carvalho de Melo else { 310a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 311a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 312a91e5431SArnaldo Carvalho de Melo exit(-1); 313dd7927f4SArnaldo Carvalho de Melo } 31486470930SIngo Molnar } 31586470930SIngo Molnar 316a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 317a91e5431SArnaldo Carvalho de Melo } 318a91e5431SArnaldo Carvalho de Melo 319d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 3206122e4e4SArnaldo Carvalho de Melo { 321d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3226122e4e4SArnaldo Carvalho de Melo 3239f591fd7SArnaldo Carvalho de Melo if (size == 0) 3249f591fd7SArnaldo Carvalho de Melo return 0; 3259f591fd7SArnaldo Carvalho de Melo 326d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 327d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 328d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3296122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3306122e4e4SArnaldo Carvalho de Melo } 3316122e4e4SArnaldo Carvalho de Melo 332d20deb64SArnaldo Carvalho de Melo static void perf_record__exit(int status __used, void *arg) 333f5970550SPeter Zijlstra { 334d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 335f5970550SPeter Zijlstra 336d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 337d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 338d20deb64SArnaldo Carvalho de Melo 339d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 340d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 341d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 342d20deb64SArnaldo Carvalho de Melo rec->output, true); 343d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 344d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 345d65a458bSArnaldo Carvalho de Melo symbol__exit(); 346c7929e47STom Zanussi } 347f5970550SPeter Zijlstra } 348f5970550SPeter Zijlstra 3498115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 350a1645ce1SZhang, Yanmin { 351a1645ce1SZhang, Yanmin int err; 35245694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 353a1645ce1SZhang, Yanmin 35423346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 355a1645ce1SZhang, Yanmin return; 356a1645ce1SZhang, Yanmin 357a1645ce1SZhang, Yanmin /* 358a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 359a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 360a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 361a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 362a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 363a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 364a1645ce1SZhang, Yanmin */ 36545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 366743eb868SArnaldo Carvalho de Melo machine); 367a1645ce1SZhang, Yanmin if (err < 0) 368a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 36923346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 370a1645ce1SZhang, Yanmin 371a1645ce1SZhang, Yanmin /* 372a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 373a1645ce1SZhang, Yanmin * have no _text sometimes. 374a1645ce1SZhang, Yanmin */ 37545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 376743eb868SArnaldo Carvalho de Melo machine, "_text"); 377a1645ce1SZhang, Yanmin if (err < 0) 37845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 379743eb868SArnaldo Carvalho de Melo machine, "_stext"); 380a1645ce1SZhang, Yanmin if (err < 0) 381a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 38223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 383a1645ce1SZhang, Yanmin } 384a1645ce1SZhang, Yanmin 38598402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 38698402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 38798402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 38898402807SFrederic Weisbecker }; 38998402807SFrederic Weisbecker 390d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read_all(struct perf_record *rec) 39198402807SFrederic Weisbecker { 3920e2e63ddSPeter Zijlstra int i; 39398402807SFrederic Weisbecker 394d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 395d20deb64SArnaldo Carvalho de Melo if (rec->evlist->mmap[i].base) 396d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read(rec, &rec->evlist->mmap[i]); 39798402807SFrederic Weisbecker } 39898402807SFrederic Weisbecker 3992eeaaa09SStephane Eranian if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 400d20deb64SArnaldo Carvalho de Melo write_output(rec, &finished_round_event, sizeof(finished_round_event)); 40198402807SFrederic Weisbecker } 40298402807SFrederic Weisbecker 403d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 40486470930SIngo Molnar { 40586470930SIngo Molnar struct stat st; 40686470930SIngo Molnar int flags; 407781ba9d2SRobert Richter int err, output, feat; 4088b412664SPeter Zijlstra unsigned long waking = 0; 40946be604bSZhang, Yanmin const bool forks = argc > 0; 41023346f21SArnaldo Carvalho de Melo struct machine *machine; 41145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 412d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 413d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 414d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 415d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 41686470930SIngo Molnar 417d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 41833e49ea7SAndi Kleen 419d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 42086470930SIngo Molnar 421d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 422f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 423f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 42418483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 425f5970550SPeter Zijlstra 426d7065adbSFranck Bui-Huu if (!output_name) { 427d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 428d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 429d7065adbSFranck Bui-Huu else 430d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 431d7065adbSFranck Bui-Huu } 432d7065adbSFranck Bui-Huu if (output_name) { 433529870e3STom Zanussi if (!strcmp(output_name, "-")) 434d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 435529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 436d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 437b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 438b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 439b38d3464SArnaldo Carvalho de Melo output_name); 440b38d3464SArnaldo Carvalho de Melo unlink(oldname); 441b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 442b38d3464SArnaldo Carvalho de Melo } 443d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 444d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 445266e0e21SPierre Habouzit } 446d7065adbSFranck Bui-Huu } 44786470930SIngo Molnar 448f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 449d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 450d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 45186470930SIngo Molnar else 45286470930SIngo Molnar flags |= O_TRUNC; 45386470930SIngo Molnar 454d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 455529870e3STom Zanussi output = STDOUT_FILENO; 456529870e3STom Zanussi else 45786470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 45886470930SIngo Molnar if (output < 0) { 45986470930SIngo Molnar perror("failed to create output file"); 46086470930SIngo Molnar exit(-1); 46186470930SIngo Molnar } 46286470930SIngo Molnar 463d20deb64SArnaldo Carvalho de Melo rec->output = output; 464d20deb64SArnaldo Carvalho de Melo 4657865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 466d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 46794c744b6SArnaldo Carvalho de Melo if (session == NULL) { 468a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 469a9a70bbcSArnaldo Carvalho de Melo return -1; 470a9a70bbcSArnaldo Carvalho de Melo } 471a9a70bbcSArnaldo Carvalho de Melo 472d20deb64SArnaldo Carvalho de Melo rec->session = session; 473d20deb64SArnaldo Carvalho de Melo 474781ba9d2SRobert Richter for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 475781ba9d2SRobert Richter perf_header__set_feat(&session->header, feat); 476781ba9d2SRobert Richter 477781ba9d2SRobert Richter if (rec->no_buildid) 478781ba9d2SRobert Richter perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 479781ba9d2SRobert Richter 480781ba9d2SRobert Richter if (!have_tracepoints(&evsel_list->entries)) 4812eeaaa09SStephane Eranian perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 482baa2f6ceSArnaldo Carvalho de Melo 483330aa675SStephane Eranian if (!rec->opts.branch_stack) 484330aa675SStephane Eranian perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 485330aa675SStephane Eranian 486d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 487a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4884dc0a04bSArnaldo Carvalho de Melo if (err < 0) 48939d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4904dc0a04bSArnaldo Carvalho de Melo } 4914dc0a04bSArnaldo Carvalho de Melo 492d4db3f16SArnaldo Carvalho de Melo if (forks) { 493d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 49435b9d88eSArnaldo Carvalho de Melo if (err < 0) { 49535b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 49635b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 497856e9660SPeter Zijlstra } 498856e9660SPeter Zijlstra } 499856e9660SPeter Zijlstra 500d20deb64SArnaldo Carvalho de Melo perf_record__open(rec); 50186470930SIngo Molnar 502712a4b60SArnaldo Carvalho de Melo /* 503d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 504712a4b60SArnaldo Carvalho de Melo */ 505d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 506712a4b60SArnaldo Carvalho de Melo 507d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 508529870e3STom Zanussi err = perf_header__write_pipe(output); 509529870e3STom Zanussi if (err < 0) 510529870e3STom Zanussi return err; 511d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 512a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 513361c99a6SArnaldo Carvalho de Melo output, false); 514d5eed904SArnaldo Carvalho de Melo if (err < 0) 515d5eed904SArnaldo Carvalho de Melo return err; 516d5eed904SArnaldo Carvalho de Melo } 5177c6a1c65SPeter Zijlstra 518d3665498SDavid Ahern if (!rec->no_buildid 519e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 520d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 521e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 522e20960c0SRobert Richter return -1; 523e20960c0SRobert Richter } 524e20960c0SRobert Richter 525d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5266122e4e4SArnaldo Carvalho de Melo 527743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 528743eb868SArnaldo Carvalho de Melo if (!machine) { 529743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 530743eb868SArnaldo Carvalho de Melo return -1; 531743eb868SArnaldo Carvalho de Melo } 532743eb868SArnaldo Carvalho de Melo 533d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 53445694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 535a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5362c46dbb5STom Zanussi if (err < 0) { 5372c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5382c46dbb5STom Zanussi return err; 5392c46dbb5STom Zanussi } 540cd19a035STom Zanussi 54145694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 542743eb868SArnaldo Carvalho de Melo machine); 543cd19a035STom Zanussi if (err < 0) { 544cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 545cd19a035STom Zanussi return err; 546cd19a035STom Zanussi } 5479215545eSTom Zanussi 548361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 54963e0c771STom Zanussi /* 55063e0c771STom Zanussi * FIXME err <= 0 here actually means that 55163e0c771STom Zanussi * there were no tracepoints so its not really 55263e0c771STom Zanussi * an error, just that we don't need to 55363e0c771STom Zanussi * synthesize anything. We really have to 55463e0c771STom Zanussi * return this more properly and also 55563e0c771STom Zanussi * propagate errors that now are calling die() 55663e0c771STom Zanussi */ 55745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 558743eb868SArnaldo Carvalho de Melo process_synthesized_event); 55963e0c771STom Zanussi if (err <= 0) { 56063e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 56163e0c771STom Zanussi return err; 56263e0c771STom Zanussi } 563d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 5642c46dbb5STom Zanussi } 56563e0c771STom Zanussi } 5662c46dbb5STom Zanussi 56745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 568743eb868SArnaldo Carvalho de Melo machine, "_text"); 56970162138SArnaldo Carvalho de Melo if (err < 0) 57045694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 571743eb868SArnaldo Carvalho de Melo machine, "_stext"); 572c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 573c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 574c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 575c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 57656b03f3cSArnaldo Carvalho de Melo 57745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 578743eb868SArnaldo Carvalho de Melo machine); 579c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 580c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 581c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 582c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 583c1a3a4b9SArnaldo Carvalho de Melo 584a1645ce1SZhang, Yanmin if (perf_guest) 58545694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 5868115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 587b7cece76SArnaldo Carvalho de Melo 588bea03405SNamhyung Kim if (!opts->target.system_wide) 58945694aa7SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(tool, evsel_list->threads, 5908115d60cSArnaldo Carvalho de Melo process_synthesized_event, 591743eb868SArnaldo Carvalho de Melo machine); 592234fbbf5SArnaldo Carvalho de Melo else 59345694aa7SArnaldo Carvalho de Melo perf_event__synthesize_threads(tool, process_synthesized_event, 594743eb868SArnaldo Carvalho de Melo machine); 5957c6a1c65SPeter Zijlstra 596d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 59786470930SIngo Molnar struct sched_param param; 59886470930SIngo Molnar 599d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 60086470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6016beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 60286470930SIngo Molnar exit(-1); 60386470930SIngo Molnar } 60486470930SIngo Molnar } 60586470930SIngo Molnar 606764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 607764e16a3SDavid Ahern 608856e9660SPeter Zijlstra /* 609856e9660SPeter Zijlstra * Let the child rip 610856e9660SPeter Zijlstra */ 611d4db3f16SArnaldo Carvalho de Melo if (forks) 61235b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 613856e9660SPeter Zijlstra 614649c48a9SPeter Zijlstra for (;;) { 615d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 61686470930SIngo Molnar 617d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read_all(rec); 61886470930SIngo Molnar 619d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 620649c48a9SPeter Zijlstra if (done) 621649c48a9SPeter Zijlstra break; 6225c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6238b412664SPeter Zijlstra waking++; 6248b412664SPeter Zijlstra } 6258b412664SPeter Zijlstra 6264152ab37SArnaldo Carvalho de Melo if (done) 6274152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6288b412664SPeter Zijlstra } 6298b412664SPeter Zijlstra 63018483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 631b44308f5SArnaldo Carvalho de Melo return 0; 632b44308f5SArnaldo Carvalho de Melo 6338b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 63486470930SIngo Molnar 63586470930SIngo Molnar /* 63686470930SIngo Molnar * Approximate RIP event size: 24 bytes. 63786470930SIngo Molnar */ 63886470930SIngo Molnar fprintf(stderr, 6399486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 640d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 64186470930SIngo Molnar output_name, 642d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 64386470930SIngo Molnar 64486470930SIngo Molnar return 0; 64539d17dacSArnaldo Carvalho de Melo 64639d17dacSArnaldo Carvalho de Melo out_delete_session: 64739d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 64839d17dacSArnaldo Carvalho de Melo return err; 64986470930SIngo Molnar } 65086470930SIngo Molnar 651bdfebd84SRoberto Agostino Vitillo #define BRANCH_OPT(n, m) \ 652bdfebd84SRoberto Agostino Vitillo { .name = n, .mode = (m) } 653bdfebd84SRoberto Agostino Vitillo 654bdfebd84SRoberto Agostino Vitillo #define BRANCH_END { .name = NULL } 655bdfebd84SRoberto Agostino Vitillo 656bdfebd84SRoberto Agostino Vitillo struct branch_mode { 657bdfebd84SRoberto Agostino Vitillo const char *name; 658bdfebd84SRoberto Agostino Vitillo int mode; 659bdfebd84SRoberto Agostino Vitillo }; 660bdfebd84SRoberto Agostino Vitillo 661bdfebd84SRoberto Agostino Vitillo static const struct branch_mode branch_modes[] = { 662bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER), 663bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL), 664bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV), 665bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY), 666bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 667bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 668bdfebd84SRoberto Agostino Vitillo BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 669bdfebd84SRoberto Agostino Vitillo BRANCH_END 670bdfebd84SRoberto Agostino Vitillo }; 671bdfebd84SRoberto Agostino Vitillo 672bdfebd84SRoberto Agostino Vitillo static int 673a5aabdacSStephane Eranian parse_branch_stack(const struct option *opt, const char *str, int unset) 674bdfebd84SRoberto Agostino Vitillo { 675bdfebd84SRoberto Agostino Vitillo #define ONLY_PLM \ 676bdfebd84SRoberto Agostino Vitillo (PERF_SAMPLE_BRANCH_USER |\ 677bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_KERNEL |\ 678bdfebd84SRoberto Agostino Vitillo PERF_SAMPLE_BRANCH_HV) 679bdfebd84SRoberto Agostino Vitillo 680bdfebd84SRoberto Agostino Vitillo uint64_t *mode = (uint64_t *)opt->value; 681bdfebd84SRoberto Agostino Vitillo const struct branch_mode *br; 682a5aabdacSStephane Eranian char *s, *os = NULL, *p; 683bdfebd84SRoberto Agostino Vitillo int ret = -1; 684bdfebd84SRoberto Agostino Vitillo 685a5aabdacSStephane Eranian if (unset) 686a5aabdacSStephane Eranian return 0; 687bdfebd84SRoberto Agostino Vitillo 688a5aabdacSStephane Eranian /* 689a5aabdacSStephane Eranian * cannot set it twice, -b + --branch-filter for instance 690a5aabdacSStephane Eranian */ 691a5aabdacSStephane Eranian if (*mode) 692a5aabdacSStephane Eranian return -1; 693a5aabdacSStephane Eranian 694a5aabdacSStephane Eranian /* str may be NULL in case no arg is passed to -b */ 695a5aabdacSStephane Eranian if (str) { 696bdfebd84SRoberto Agostino Vitillo /* because str is read-only */ 697bdfebd84SRoberto Agostino Vitillo s = os = strdup(str); 698bdfebd84SRoberto Agostino Vitillo if (!s) 699bdfebd84SRoberto Agostino Vitillo return -1; 700bdfebd84SRoberto Agostino Vitillo 701bdfebd84SRoberto Agostino Vitillo for (;;) { 702bdfebd84SRoberto Agostino Vitillo p = strchr(s, ','); 703bdfebd84SRoberto Agostino Vitillo if (p) 704bdfebd84SRoberto Agostino Vitillo *p = '\0'; 705bdfebd84SRoberto Agostino Vitillo 706bdfebd84SRoberto Agostino Vitillo for (br = branch_modes; br->name; br++) { 707bdfebd84SRoberto Agostino Vitillo if (!strcasecmp(s, br->name)) 708bdfebd84SRoberto Agostino Vitillo break; 709bdfebd84SRoberto Agostino Vitillo } 710a5aabdacSStephane Eranian if (!br->name) { 711a5aabdacSStephane Eranian ui__warning("unknown branch filter %s," 712a5aabdacSStephane Eranian " check man page\n", s); 713bdfebd84SRoberto Agostino Vitillo goto error; 714a5aabdacSStephane Eranian } 715bdfebd84SRoberto Agostino Vitillo 716bdfebd84SRoberto Agostino Vitillo *mode |= br->mode; 717bdfebd84SRoberto Agostino Vitillo 718bdfebd84SRoberto Agostino Vitillo if (!p) 719bdfebd84SRoberto Agostino Vitillo break; 720bdfebd84SRoberto Agostino Vitillo 721bdfebd84SRoberto Agostino Vitillo s = p + 1; 722bdfebd84SRoberto Agostino Vitillo } 723a5aabdacSStephane Eranian } 724bdfebd84SRoberto Agostino Vitillo ret = 0; 725bdfebd84SRoberto Agostino Vitillo 726a5aabdacSStephane Eranian /* default to any branch */ 727bdfebd84SRoberto Agostino Vitillo if ((*mode & ~ONLY_PLM) == 0) { 728a5aabdacSStephane Eranian *mode = PERF_SAMPLE_BRANCH_ANY; 729bdfebd84SRoberto Agostino Vitillo } 730bdfebd84SRoberto Agostino Vitillo error: 731bdfebd84SRoberto Agostino Vitillo free(os); 732bdfebd84SRoberto Agostino Vitillo return ret; 733bdfebd84SRoberto Agostino Vitillo } 734bdfebd84SRoberto Agostino Vitillo 73586470930SIngo Molnar static const char * const record_usage[] = { 73686470930SIngo Molnar "perf record [<options>] [<command>]", 73786470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 73886470930SIngo Molnar NULL 73986470930SIngo Molnar }; 74086470930SIngo Molnar 741d20deb64SArnaldo Carvalho de Melo /* 742d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 743d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 744d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 745d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 746d20deb64SArnaldo Carvalho de Melo * 747d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 748d20deb64SArnaldo Carvalho de Melo * 749d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 750d20deb64SArnaldo Carvalho de Melo */ 751d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 752d20deb64SArnaldo Carvalho de Melo .opts = { 753d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 754d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 755d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 756447a6013SArnaldo Carvalho de Melo .freq = 4000, 757d1cb9fceSNamhyung Kim .target = { 758d1cb9fceSNamhyung Kim .uses_mmap = true, 759d1cb9fceSNamhyung Kim }, 760d20deb64SArnaldo Carvalho de Melo }, 761d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 762d20deb64SArnaldo Carvalho de Melo .file_new = true, 763d20deb64SArnaldo Carvalho de Melo }; 7647865e817SFrederic Weisbecker 765d20deb64SArnaldo Carvalho de Melo /* 766d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 767d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 768d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 769d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 770d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 771d20deb64SArnaldo Carvalho de Melo */ 772bca647aaSTom Zanussi const struct option record_options[] = { 773d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 77486470930SIngo Molnar "event selector. use 'perf list' to list available events", 775f120f9d5SJiri Olsa parse_events_option), 776d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 777c171b552SLi Zefan "event filter", parse_filter), 778bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 779d6d901c2SZhang, Yanmin "record events on existing process id"), 780bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 781d6d901c2SZhang, Yanmin "record events on existing thread id"), 782d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 78386470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 784d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 785acac03faSKirill Smelkov "collect data without buffering"), 786d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 787daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 788bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 78986470930SIngo Molnar "system-wide collection from all CPUs"), 790d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 79186470930SIngo Molnar "append to the output file to do incremental profiling"), 792bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 793c45c6ea2SStephane Eranian "list of cpus to monitor"), 794d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 7957865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 796d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 797d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 79886470930SIngo Molnar "output file name"), 799d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 8002e6cdf99SStephane Eranian "child tasks do not inherit counters"), 801d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 802d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 80301c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 804d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 80543bece79SLin Ming "put the counters into a counter group"), 806d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph, 8073efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 808c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 8093da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 810b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 811d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 812649c48a9SPeter Zijlstra "per thread counts"), 813d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 8144bba828dSAnton Blanchard "Sample addresses"), 815d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 8163e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 817d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 818649c48a9SPeter Zijlstra "don't sample"), 819d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 820a1ac1d3cSStephane Eranian "do not update the buildid cache"), 821d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 822baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 823d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 824023695d9SStephane Eranian "monitor event in cgroup name only", 825023695d9SStephane Eranian parse_cgroups), 826bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 827bea03405SNamhyung Kim "user to profile"), 828a5aabdacSStephane Eranian 829a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 830a5aabdacSStephane Eranian "branch any", "sample any taken branches", 831a5aabdacSStephane Eranian parse_branch_stack), 832a5aabdacSStephane Eranian 833a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 834a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 835bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 83686470930SIngo Molnar OPT_END() 83786470930SIngo Molnar }; 83886470930SIngo Molnar 839f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 84086470930SIngo Molnar { 84169aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 84269aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 843d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 844d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 84516ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 84686470930SIngo Molnar 847fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 848fbe96f29SStephane Eranian 8497e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 850361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 851361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 852361c99a6SArnaldo Carvalho de Melo 853d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 854d20deb64SArnaldo Carvalho de Melo 855bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 856a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 857d67356e7SNamhyung Kim if (!argc && perf_target__none(&rec->opts.target)) 858bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 85986470930SIngo Molnar 860d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 8613780f488SNamhyung Kim ui__error("Can't overwrite and append at the same time." 8627865e817SFrederic Weisbecker " You need to choose between -f and -A"); 863bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 864d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 865d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 8667865e817SFrederic Weisbecker } else { 867d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 8687865e817SFrederic Weisbecker } 8697865e817SFrederic Weisbecker 870bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 8713780f488SNamhyung Kim ui__error("cgroup monitoring only available in" 872023695d9SStephane Eranian " system-wide mode\n"); 873023695d9SStephane Eranian usage_with_options(record_usage, record_options); 874023695d9SStephane Eranian } 875023695d9SStephane Eranian 876655000e7SArnaldo Carvalho de Melo symbol__init(); 877baa2f6ceSArnaldo Carvalho de Melo 878ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 879646aaea6SArnaldo Carvalho de Melo pr_warning( 880646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 881ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 882646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 883646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 884646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 885646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 886646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 887ec80fde7SArnaldo Carvalho de Melo 888d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 889a1ac1d3cSStephane Eranian disable_buildid_cache(); 890655000e7SArnaldo Carvalho de Melo 891361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 892361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 89369aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 89469aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 895bbd36e5eSPeter Zijlstra } 89686470930SIngo Molnar 89716ad2ffbSNamhyung Kim err = perf_target__validate(&rec->opts.target); 89816ad2ffbSNamhyung Kim if (err) { 89916ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 90016ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 90116ad2ffbSNamhyung Kim } 9024bd0f2d2SNamhyung Kim 90316ad2ffbSNamhyung Kim err = perf_target__parse_uid(&rec->opts.target); 90416ad2ffbSNamhyung Kim if (err) { 90516ad2ffbSNamhyung Kim int saved_errno = errno; 90616ad2ffbSNamhyung Kim 90716ad2ffbSNamhyung Kim perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 9083780f488SNamhyung Kim ui__error("%s", errbuf); 90916ad2ffbSNamhyung Kim 91016ad2ffbSNamhyung Kim err = -saved_errno; 9110d37aa34SArnaldo Carvalho de Melo goto out_free_fd; 91216ad2ffbSNamhyung Kim } 9130d37aa34SArnaldo Carvalho de Melo 91416ad2ffbSNamhyung Kim err = -ENOMEM; 915b809ac10SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 916dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 91769aad6f1SArnaldo Carvalho de Melo 918361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 919*7289f83cSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos))) 920ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 921d6d901c2SZhang, Yanmin } 9225c581041SArnaldo Carvalho de Melo 923d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 924d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 925d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 926d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 927f9212819SFrederic Weisbecker 9287e4ff9e3SMike Galbraith /* 9297e4ff9e3SMike Galbraith * User specified count overrides default frequency. 9307e4ff9e3SMike Galbraith */ 931d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 932d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 933d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 934d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 9357e4ff9e3SMike Galbraith } else { 9363780f488SNamhyung Kim ui__error("frequency and count are zero, aborting\n"); 93739d17dacSArnaldo Carvalho de Melo err = -EINVAL; 9385c581041SArnaldo Carvalho de Melo goto out_free_fd; 9397e4ff9e3SMike Galbraith } 9407e4ff9e3SMike Galbraith 941d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 94239d17dacSArnaldo Carvalho de Melo out_free_fd: 9437e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 944d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 945d65a458bSArnaldo Carvalho de Melo symbol__exit(); 94639d17dacSArnaldo Carvalho de Melo return err; 94786470930SIngo Molnar } 948