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; 2079c90a61cSArnaldo Carvalho de Melo retry_sample_id: 208d20deb64SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 2093da297a6SIngo Molnar try_again: 210ed80f581SArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 211d20deb64SArnaldo Carvalho de Melo opts->group, group_fd) < 0) { 21286470930SIngo Molnar int err = errno; 21386470930SIngo Molnar 214c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 215b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 216c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 217d20deb64SArnaldo Carvalho de Melo } else if (err == ENODEV && opts->cpu_list) { 218d6d901c2SZhang, Yanmin die("No such device - did you specify" 219d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 220d20deb64SArnaldo Carvalho de Melo } else if (err == EINVAL && opts->sample_id_all_avail) { 2219c90a61cSArnaldo Carvalho de Melo /* 2229c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2239c90a61cSArnaldo Carvalho de Melo */ 224d20deb64SArnaldo Carvalho de Melo opts->sample_id_all_avail = false; 225d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 226eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 227eac23d1cSIan Munsie 2289c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 229d6d901c2SZhang, Yanmin } 2303da297a6SIngo Molnar 2313da297a6SIngo Molnar /* 2323da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2333da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 2343da297a6SIngo Molnar * is always available even if no PMU support: 2353da297a6SIngo Molnar */ 2363da297a6SIngo Molnar if (attr->type == PERF_TYPE_HARDWARE 237f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2383da297a6SIngo Molnar 2393da297a6SIngo Molnar if (verbose) 240ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 241ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2423da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 243f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 2443da297a6SIngo Molnar goto try_again; 2453da297a6SIngo Molnar } 246ca6a4258SDavid Ahern 247ca6a4258SDavid Ahern if (err == ENOENT) { 248ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 249ca6a4258SDavid Ahern event_name(pos)); 250ca6a4258SDavid Ahern exit(EXIT_FAILURE); 251ca6a4258SDavid Ahern } 252ca6a4258SDavid Ahern 25330c806a0SIngo Molnar printf("\n"); 254d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 255dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 256bfd45118SSimon Kaempflein 257bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 258bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 259d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 260d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 261d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 262d6d901c2SZhang, Yanmin " force-enable it.\n"); 263bfd45118SSimon Kaempflein #endif 264bfd45118SSimon Kaempflein 265cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 2667c6a1c65SPeter Zijlstra } 2677c6a1c65SPeter Zijlstra } 2687c6a1c65SPeter Zijlstra 2690a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 2700a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2710a102479SFrederic Weisbecker strerror(errno)); 2720a102479SFrederic Weisbecker exit(-1); 2730a102479SFrederic Weisbecker } 2740a102479SFrederic Weisbecker 275*18e60939SNelson Elhage if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 276*18e60939SNelson Elhage if (errno == EPERM) 277*18e60939SNelson Elhage die("Permission error mapping pages.\n" 278*18e60939SNelson Elhage "Consider increasing " 279*18e60939SNelson Elhage "/proc/sys/kernel/perf_event_mlock_kb,\n" 280*18e60939SNelson Elhage "or try again with a smaller value of -m/--mmap_pages.\n" 281*18e60939SNelson Elhage "(current value: %d)\n", opts->mmap_pages); 2820a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 283*18e60939SNelson Elhage } 2840a27d7f9SArnaldo Carvalho de Melo 285d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 286a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 287a91e5431SArnaldo Carvalho de Melo else { 288a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 289a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 290a91e5431SArnaldo Carvalho de Melo exit(-1); 291dd7927f4SArnaldo Carvalho de Melo } 29286470930SIngo Molnar } 29386470930SIngo Molnar 294a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 295a91e5431SArnaldo Carvalho de Melo } 296a91e5431SArnaldo Carvalho de Melo 297d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 2986122e4e4SArnaldo Carvalho de Melo { 299d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 3006122e4e4SArnaldo Carvalho de Melo 3019f591fd7SArnaldo Carvalho de Melo if (size == 0) 3029f591fd7SArnaldo Carvalho de Melo return 0; 3039f591fd7SArnaldo Carvalho de Melo 304d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 305d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 306d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 3076122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3086122e4e4SArnaldo Carvalho de Melo } 3096122e4e4SArnaldo Carvalho de Melo 310d20deb64SArnaldo Carvalho de Melo static void perf_record__exit(int status __used, void *arg) 311f5970550SPeter Zijlstra { 312d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 313f5970550SPeter Zijlstra 314d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 315d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 316d20deb64SArnaldo Carvalho de Melo 317d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 318d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 319d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 320d20deb64SArnaldo Carvalho de Melo rec->output, true); 321d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 322d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 323d65a458bSArnaldo Carvalho de Melo symbol__exit(); 324c7929e47STom Zanussi } 325f5970550SPeter Zijlstra } 326f5970550SPeter Zijlstra 3278115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 328a1645ce1SZhang, Yanmin { 329a1645ce1SZhang, Yanmin int err; 33045694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 331a1645ce1SZhang, Yanmin 33223346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 333a1645ce1SZhang, Yanmin return; 334a1645ce1SZhang, Yanmin 335a1645ce1SZhang, Yanmin /* 336a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 337a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 338a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 339a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 340a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 341a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 342a1645ce1SZhang, Yanmin */ 34345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 344743eb868SArnaldo Carvalho de Melo machine); 345a1645ce1SZhang, Yanmin if (err < 0) 346a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 34723346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 348a1645ce1SZhang, Yanmin 349a1645ce1SZhang, Yanmin /* 350a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 351a1645ce1SZhang, Yanmin * have no _text sometimes. 352a1645ce1SZhang, Yanmin */ 35345694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 354743eb868SArnaldo Carvalho de Melo machine, "_text"); 355a1645ce1SZhang, Yanmin if (err < 0) 35645694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 357743eb868SArnaldo Carvalho de Melo machine, "_stext"); 358a1645ce1SZhang, Yanmin if (err < 0) 359a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 36023346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 361a1645ce1SZhang, Yanmin } 362a1645ce1SZhang, Yanmin 36398402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 36498402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 36598402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 36698402807SFrederic Weisbecker }; 36798402807SFrederic Weisbecker 368d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read_all(struct perf_record *rec) 36998402807SFrederic Weisbecker { 3700e2e63ddSPeter Zijlstra int i; 37198402807SFrederic Weisbecker 372d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 373d20deb64SArnaldo Carvalho de Melo if (rec->evlist->mmap[i].base) 374d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read(rec, &rec->evlist->mmap[i]); 37598402807SFrederic Weisbecker } 37698402807SFrederic Weisbecker 377d20deb64SArnaldo Carvalho de Melo if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO)) 378d20deb64SArnaldo Carvalho de Melo write_output(rec, &finished_round_event, sizeof(finished_round_event)); 37998402807SFrederic Weisbecker } 38098402807SFrederic Weisbecker 381d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 38286470930SIngo Molnar { 38386470930SIngo Molnar struct stat st; 38486470930SIngo Molnar int flags; 385d20deb64SArnaldo Carvalho de Melo int err, output; 3868b412664SPeter Zijlstra unsigned long waking = 0; 38746be604bSZhang, Yanmin const bool forks = argc > 0; 38823346f21SArnaldo Carvalho de Melo struct machine *machine; 38945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 390d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 391d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 392d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 393d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 39486470930SIngo Molnar 395d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 39633e49ea7SAndi Kleen 397d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 39886470930SIngo Molnar 399d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 400f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 401f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 40218483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 403f5970550SPeter Zijlstra 404d7065adbSFranck Bui-Huu if (!output_name) { 405d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 406d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 407d7065adbSFranck Bui-Huu else 408d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 409d7065adbSFranck Bui-Huu } 410d7065adbSFranck Bui-Huu if (output_name) { 411529870e3STom Zanussi if (!strcmp(output_name, "-")) 412d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 413529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 414d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 415b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 416b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 417b38d3464SArnaldo Carvalho de Melo output_name); 418b38d3464SArnaldo Carvalho de Melo unlink(oldname); 419b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 420b38d3464SArnaldo Carvalho de Melo } 421d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 422d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 423266e0e21SPierre Habouzit } 424d7065adbSFranck Bui-Huu } 42586470930SIngo Molnar 426f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 427d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 428d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 42986470930SIngo Molnar else 43086470930SIngo Molnar flags |= O_TRUNC; 43186470930SIngo Molnar 432d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 433529870e3STom Zanussi output = STDOUT_FILENO; 434529870e3STom Zanussi else 43586470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 43686470930SIngo Molnar if (output < 0) { 43786470930SIngo Molnar perror("failed to create output file"); 43886470930SIngo Molnar exit(-1); 43986470930SIngo Molnar } 44086470930SIngo Molnar 441d20deb64SArnaldo Carvalho de Melo rec->output = output; 442d20deb64SArnaldo Carvalho de Melo 4437865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 444d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 44594c744b6SArnaldo Carvalho de Melo if (session == NULL) { 446a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 447a9a70bbcSArnaldo Carvalho de Melo return -1; 448a9a70bbcSArnaldo Carvalho de Melo } 449a9a70bbcSArnaldo Carvalho de Melo 450d20deb64SArnaldo Carvalho de Melo rec->session = session; 451d20deb64SArnaldo Carvalho de Melo 452d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 453baa2f6ceSArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_BUILD_ID); 454baa2f6ceSArnaldo Carvalho de Melo 455d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 456a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4574dc0a04bSArnaldo Carvalho de Melo if (err < 0) 45839d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4594dc0a04bSArnaldo Carvalho de Melo } 4604dc0a04bSArnaldo Carvalho de Melo 461361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) 46294c744b6SArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 46303456a15SFrederic Weisbecker 464fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_HOSTNAME); 465fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_OSRELEASE); 466fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_ARCH); 467fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUDESC); 468fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NRCPUS); 469fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_EVENT_DESC); 470fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CMDLINE); 471fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_VERSION); 472fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); 473fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_TOTAL_MEM); 474fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 475fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUID); 476fbe96f29SStephane Eranian 477d4db3f16SArnaldo Carvalho de Melo if (forks) { 478d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 47935b9d88eSArnaldo Carvalho de Melo if (err < 0) { 48035b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 48135b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 482856e9660SPeter Zijlstra } 483856e9660SPeter Zijlstra } 484856e9660SPeter Zijlstra 485d20deb64SArnaldo Carvalho de Melo perf_record__open(rec); 48686470930SIngo Molnar 487712a4b60SArnaldo Carvalho de Melo /* 488d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 489712a4b60SArnaldo Carvalho de Melo */ 490d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 491712a4b60SArnaldo Carvalho de Melo 492d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 493529870e3STom Zanussi err = perf_header__write_pipe(output); 494529870e3STom Zanussi if (err < 0) 495529870e3STom Zanussi return err; 496d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 497a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 498361c99a6SArnaldo Carvalho de Melo output, false); 499d5eed904SArnaldo Carvalho de Melo if (err < 0) 500d5eed904SArnaldo Carvalho de Melo return err; 501d5eed904SArnaldo Carvalho de Melo } 5027c6a1c65SPeter Zijlstra 503d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 5046122e4e4SArnaldo Carvalho de Melo 505743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 506743eb868SArnaldo Carvalho de Melo if (!machine) { 507743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 508743eb868SArnaldo Carvalho de Melo return -1; 509743eb868SArnaldo Carvalho de Melo } 510743eb868SArnaldo Carvalho de Melo 511d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 51245694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(tool, session, 513a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5142c46dbb5STom Zanussi if (err < 0) { 5152c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5162c46dbb5STom Zanussi return err; 5172c46dbb5STom Zanussi } 518cd19a035STom Zanussi 51945694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(tool, process_synthesized_event, 520743eb868SArnaldo Carvalho de Melo machine); 521cd19a035STom Zanussi if (err < 0) { 522cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 523cd19a035STom Zanussi return err; 524cd19a035STom Zanussi } 5259215545eSTom Zanussi 526361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 52763e0c771STom Zanussi /* 52863e0c771STom Zanussi * FIXME err <= 0 here actually means that 52963e0c771STom Zanussi * there were no tracepoints so its not really 53063e0c771STom Zanussi * an error, just that we don't need to 53163e0c771STom Zanussi * synthesize anything. We really have to 53263e0c771STom Zanussi * return this more properly and also 53363e0c771STom Zanussi * propagate errors that now are calling die() 53463e0c771STom Zanussi */ 53545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 536743eb868SArnaldo Carvalho de Melo process_synthesized_event); 53763e0c771STom Zanussi if (err <= 0) { 53863e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 53963e0c771STom Zanussi return err; 54063e0c771STom Zanussi } 541d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 5422c46dbb5STom Zanussi } 54363e0c771STom Zanussi } 5442c46dbb5STom Zanussi 54545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 546743eb868SArnaldo Carvalho de Melo machine, "_text"); 54770162138SArnaldo Carvalho de Melo if (err < 0) 54845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 549743eb868SArnaldo Carvalho de Melo machine, "_stext"); 550c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 551c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 552c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 553c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 55456b03f3cSArnaldo Carvalho de Melo 55545694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 556743eb868SArnaldo Carvalho de Melo machine); 557c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 558c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 559c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 560c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 561c1a3a4b9SArnaldo Carvalho de Melo 562a1645ce1SZhang, Yanmin if (perf_guest) 56345694aa7SArnaldo Carvalho de Melo perf_session__process_machines(session, tool, 5648115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 565b7cece76SArnaldo Carvalho de Melo 566d20deb64SArnaldo Carvalho de Melo if (!opts->system_wide) 56745694aa7SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(tool, evsel_list->threads, 5688115d60cSArnaldo Carvalho de Melo process_synthesized_event, 569743eb868SArnaldo Carvalho de Melo machine); 570234fbbf5SArnaldo Carvalho de Melo else 57145694aa7SArnaldo Carvalho de Melo perf_event__synthesize_threads(tool, process_synthesized_event, 572743eb868SArnaldo Carvalho de Melo machine); 5737c6a1c65SPeter Zijlstra 574d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 57586470930SIngo Molnar struct sched_param param; 57686470930SIngo Molnar 577d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 57886470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5796beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 58086470930SIngo Molnar exit(-1); 58186470930SIngo Molnar } 58286470930SIngo Molnar } 58386470930SIngo Molnar 584764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 585764e16a3SDavid Ahern 586856e9660SPeter Zijlstra /* 587856e9660SPeter Zijlstra * Let the child rip 588856e9660SPeter Zijlstra */ 589d4db3f16SArnaldo Carvalho de Melo if (forks) 59035b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 591856e9660SPeter Zijlstra 592649c48a9SPeter Zijlstra for (;;) { 593d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 59486470930SIngo Molnar 595d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read_all(rec); 59686470930SIngo Molnar 597d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 598649c48a9SPeter Zijlstra if (done) 599649c48a9SPeter Zijlstra break; 6005c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6018b412664SPeter Zijlstra waking++; 6028b412664SPeter Zijlstra } 6038b412664SPeter Zijlstra 6044152ab37SArnaldo Carvalho de Melo if (done) 6054152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6068b412664SPeter Zijlstra } 6078b412664SPeter Zijlstra 60818483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 609b44308f5SArnaldo Carvalho de Melo return 0; 610b44308f5SArnaldo Carvalho de Melo 6118b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 61286470930SIngo Molnar 61386470930SIngo Molnar /* 61486470930SIngo Molnar * Approximate RIP event size: 24 bytes. 61586470930SIngo Molnar */ 61686470930SIngo Molnar fprintf(stderr, 6179486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 618d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 61986470930SIngo Molnar output_name, 620d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 62186470930SIngo Molnar 62286470930SIngo Molnar return 0; 62339d17dacSArnaldo Carvalho de Melo 62439d17dacSArnaldo Carvalho de Melo out_delete_session: 62539d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 62639d17dacSArnaldo Carvalho de Melo return err; 62786470930SIngo Molnar } 62886470930SIngo Molnar 62986470930SIngo Molnar static const char * const record_usage[] = { 63086470930SIngo Molnar "perf record [<options>] [<command>]", 63186470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 63286470930SIngo Molnar NULL 63386470930SIngo Molnar }; 63486470930SIngo Molnar 635d20deb64SArnaldo Carvalho de Melo /* 636d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 637d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 638d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 639d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 640d20deb64SArnaldo Carvalho de Melo * 641d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 642d20deb64SArnaldo Carvalho de Melo * 643d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 644d20deb64SArnaldo Carvalho de Melo */ 645d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 646d20deb64SArnaldo Carvalho de Melo .opts = { 647d20deb64SArnaldo Carvalho de Melo .target_pid = -1, 648d20deb64SArnaldo Carvalho de Melo .target_tid = -1, 649d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 650d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 651d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 652d20deb64SArnaldo Carvalho de Melo .freq = 1000, 653d20deb64SArnaldo Carvalho de Melo .sample_id_all_avail = true, 654d20deb64SArnaldo Carvalho de Melo }, 655d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 656d20deb64SArnaldo Carvalho de Melo .file_new = true, 657d20deb64SArnaldo Carvalho de Melo }; 6587865e817SFrederic Weisbecker 659d20deb64SArnaldo Carvalho de Melo /* 660d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 661d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 662d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 663d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 664d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 665d20deb64SArnaldo Carvalho de Melo */ 666bca647aaSTom Zanussi const struct option record_options[] = { 667d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 66886470930SIngo Molnar "event selector. use 'perf list' to list available events", 669f120f9d5SJiri Olsa parse_events_option), 670d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 671c171b552SLi Zefan "event filter", parse_filter), 672d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('p', "pid", &record.opts.target_pid, 673d6d901c2SZhang, Yanmin "record events on existing process id"), 674d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('t', "tid", &record.opts.target_tid, 675d6d901c2SZhang, Yanmin "record events on existing thread id"), 676d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 67786470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 678d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 679acac03faSKirill Smelkov "collect data without buffering"), 680d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 681daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 682d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide, 68386470930SIngo Molnar "system-wide collection from all CPUs"), 684d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 68586470930SIngo Molnar "append to the output file to do incremental profiling"), 686d20deb64SArnaldo Carvalho de Melo OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu", 687c45c6ea2SStephane Eranian "list of cpus to monitor"), 688d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 6897865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 690d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 691d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 69286470930SIngo Molnar "output file name"), 693d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 6942e6cdf99SStephane Eranian "child tasks do not inherit counters"), 695d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 696d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 69701c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 698d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 69943bece79SLin Ming "put the counters into a counter group"), 700d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph, 7013efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 702c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7033da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 704b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 705d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 706649c48a9SPeter Zijlstra "per thread counts"), 707d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 7084bba828dSAnton Blanchard "Sample addresses"), 709d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 7103e76ac78SAndrew Vagin OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"), 711d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 712649c48a9SPeter Zijlstra "don't sample"), 713d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 714a1ac1d3cSStephane Eranian "do not update the buildid cache"), 715d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 716baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 717d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 718023695d9SStephane Eranian "monitor event in cgroup name only", 719023695d9SStephane Eranian parse_cgroups), 72086470930SIngo Molnar OPT_END() 72186470930SIngo Molnar }; 72286470930SIngo Molnar 723f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 72486470930SIngo Molnar { 72569aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 72669aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 727d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 728d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 72986470930SIngo Molnar 730fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 731fbe96f29SStephane Eranian 7327e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 733361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 734361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 735361c99a6SArnaldo Carvalho de Melo 736d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 737d20deb64SArnaldo Carvalho de Melo 738bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 739a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 740d20deb64SArnaldo Carvalho de Melo if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 741d20deb64SArnaldo Carvalho de Melo !rec->opts.system_wide && !rec->opts.cpu_list) 742bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 74386470930SIngo Molnar 744d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 7457865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 7467865e817SFrederic Weisbecker " You need to choose between -f and -A"); 747bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 748d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 749d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 7507865e817SFrederic Weisbecker } else { 751d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 7527865e817SFrederic Weisbecker } 7537865e817SFrederic Weisbecker 754d20deb64SArnaldo Carvalho de Melo if (nr_cgroups && !rec->opts.system_wide) { 755023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 756023695d9SStephane Eranian " system-wide mode\n"); 757023695d9SStephane Eranian usage_with_options(record_usage, record_options); 758023695d9SStephane Eranian } 759023695d9SStephane Eranian 760655000e7SArnaldo Carvalho de Melo symbol__init(); 761baa2f6ceSArnaldo Carvalho de Melo 762ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 763646aaea6SArnaldo Carvalho de Melo pr_warning( 764646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 765ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 766646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 767646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 768646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 769646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 770646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 771ec80fde7SArnaldo Carvalho de Melo 772d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 773a1ac1d3cSStephane Eranian disable_buildid_cache(); 774655000e7SArnaldo Carvalho de Melo 775361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 776361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 77769aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 77869aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 779bbd36e5eSPeter Zijlstra } 78086470930SIngo Molnar 781d20deb64SArnaldo Carvalho de Melo if (rec->opts.target_pid != -1) 782d20deb64SArnaldo Carvalho de Melo rec->opts.target_tid = rec->opts.target_pid; 783d6d901c2SZhang, Yanmin 784d20deb64SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 785d20deb64SArnaldo Carvalho de Melo rec->opts.target_tid, rec->opts.cpu_list) < 0) 786dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 78769aad6f1SArnaldo Carvalho de Melo 788361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 789ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 790ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 791d6d901c2SZhang, Yanmin } 7925c581041SArnaldo Carvalho de Melo 793d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 794d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 795d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 796d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 797f9212819SFrederic Weisbecker 7987e4ff9e3SMike Galbraith /* 7997e4ff9e3SMike Galbraith * User specified count overrides default frequency. 8007e4ff9e3SMike Galbraith */ 801d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 802d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 803d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 804d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 8057e4ff9e3SMike Galbraith } else { 8067e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 80739d17dacSArnaldo Carvalho de Melo err = -EINVAL; 8085c581041SArnaldo Carvalho de Melo goto out_free_fd; 8097e4ff9e3SMike Galbraith } 8107e4ff9e3SMike Galbraith 811d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 81239d17dacSArnaldo Carvalho de Melo out_free_fd: 8137e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 814d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 815d65a458bSArnaldo Carvalho de Melo symbol__exit(); 81639d17dacSArnaldo Carvalho de Melo return err; 81786470930SIngo Molnar } 818