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" 258d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 26a12b51c4SPaul Mackerras #include "util/cpumap.h" 27fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 287c6a1c65SPeter Zijlstra 2986470930SIngo Molnar #include <unistd.h> 3086470930SIngo Molnar #include <sched.h> 31a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 3286470930SIngo Molnar 337865e817SFrederic Weisbecker enum write_mode_t { 347865e817SFrederic Weisbecker WRITE_FORCE, 357865e817SFrederic Weisbecker WRITE_APPEND 367865e817SFrederic Weisbecker }; 377865e817SFrederic Weisbecker 38d20deb64SArnaldo Carvalho de Melo struct perf_record { 39d20deb64SArnaldo Carvalho de Melo struct perf_event_ops ops; 40d20deb64SArnaldo Carvalho de Melo struct perf_record_opts opts; 41d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 42d20deb64SArnaldo Carvalho de Melo const char *output_name; 43d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 44d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 45d20deb64SArnaldo Carvalho de Melo const char *progname; 46d20deb64SArnaldo Carvalho de Melo int output; 47d20deb64SArnaldo Carvalho de Melo unsigned int page_size; 48d20deb64SArnaldo Carvalho de Melo int realtime_prio; 49d20deb64SArnaldo Carvalho de Melo enum write_mode_t write_mode; 50d20deb64SArnaldo Carvalho de Melo bool no_buildid; 51d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 52d20deb64SArnaldo Carvalho de Melo bool force; 53d20deb64SArnaldo Carvalho de Melo bool file_new; 54d20deb64SArnaldo Carvalho de Melo bool append_file; 55d20deb64SArnaldo Carvalho de Melo long samples; 56d20deb64SArnaldo Carvalho de Melo off_t post_processing_offset; 570f82ebc4SArnaldo Carvalho de Melo }; 5886470930SIngo Molnar 59d20deb64SArnaldo Carvalho de Melo static void advance_output(struct perf_record *rec, size_t size) 609215545eSTom Zanussi { 61d20deb64SArnaldo Carvalho de Melo rec->bytes_written += size; 629215545eSTom Zanussi } 639215545eSTom Zanussi 64d20deb64SArnaldo Carvalho de Melo static void write_output(struct perf_record *rec, void *buf, size_t size) 65f5970550SPeter Zijlstra { 66f5970550SPeter Zijlstra while (size) { 67d20deb64SArnaldo Carvalho de Melo int ret = write(rec->output, buf, size); 68f5970550SPeter Zijlstra 69f5970550SPeter Zijlstra if (ret < 0) 70f5970550SPeter Zijlstra die("failed to write"); 71f5970550SPeter Zijlstra 72f5970550SPeter Zijlstra size -= ret; 73f5970550SPeter Zijlstra buf += ret; 74f5970550SPeter Zijlstra 75d20deb64SArnaldo Carvalho de Melo rec->bytes_written += ret; 76f5970550SPeter Zijlstra } 77f5970550SPeter Zijlstra } 78f5970550SPeter Zijlstra 79d20deb64SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_event_ops *ops, 80d20deb64SArnaldo Carvalho de Melo union perf_event *event, 818d50e5b4SArnaldo Carvalho de Melo struct perf_sample *sample __used, 82*743eb868SArnaldo Carvalho de Melo struct machine *machine __used) 83234fbbf5SArnaldo Carvalho de Melo { 84d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = container_of(ops, struct perf_record, ops); 85d20deb64SArnaldo Carvalho de Melo write_output(rec, event, event->header.size); 86234fbbf5SArnaldo Carvalho de Melo return 0; 87234fbbf5SArnaldo Carvalho de Melo } 88234fbbf5SArnaldo Carvalho de Melo 89d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read(struct perf_record *rec, 90d20deb64SArnaldo Carvalho de Melo struct perf_mmap *md) 9186470930SIngo Molnar { 92744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 9386470930SIngo Molnar unsigned int old = md->prev; 94d20deb64SArnaldo Carvalho de Melo unsigned char *data = md->base + rec->page_size; 9586470930SIngo Molnar unsigned long size; 9686470930SIngo Molnar void *buf; 9786470930SIngo Molnar 98dc82009aSArnaldo Carvalho de Melo if (old == head) 99dc82009aSArnaldo Carvalho de Melo return; 10086470930SIngo Molnar 101d20deb64SArnaldo Carvalho de Melo rec->samples++; 10286470930SIngo Molnar 10386470930SIngo Molnar size = head - old; 10486470930SIngo Molnar 10586470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 10686470930SIngo Molnar buf = &data[old & md->mask]; 10786470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 10886470930SIngo Molnar old += size; 10986470930SIngo Molnar 110d20deb64SArnaldo Carvalho de Melo write_output(rec, buf, size); 11186470930SIngo Molnar } 11286470930SIngo Molnar 11386470930SIngo Molnar buf = &data[old & md->mask]; 11486470930SIngo Molnar size = head - old; 11586470930SIngo Molnar old += size; 11686470930SIngo Molnar 117d20deb64SArnaldo Carvalho de Melo write_output(rec, buf, size); 11886470930SIngo Molnar 11986470930SIngo Molnar md->prev = old; 120115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 12186470930SIngo Molnar } 12286470930SIngo Molnar 12386470930SIngo Molnar static volatile int done = 0; 124f7b7c26eSPeter Zijlstra static volatile int signr = -1; 12533e49ea7SAndi Kleen static volatile int child_finished = 0; 12686470930SIngo Molnar 12786470930SIngo Molnar static void sig_handler(int sig) 12886470930SIngo Molnar { 12933e49ea7SAndi Kleen if (sig == SIGCHLD) 13033e49ea7SAndi Kleen child_finished = 1; 13133e49ea7SAndi Kleen 13286470930SIngo Molnar done = 1; 133f7b7c26eSPeter Zijlstra signr = sig; 134f7b7c26eSPeter Zijlstra } 135f7b7c26eSPeter Zijlstra 136d20deb64SArnaldo Carvalho de Melo static void perf_record__sig_exit(int exit_status __used, void *arg) 137f7b7c26eSPeter Zijlstra { 138d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 13933e49ea7SAndi Kleen int status; 14033e49ea7SAndi Kleen 141d20deb64SArnaldo Carvalho de Melo if (rec->evlist->workload.pid > 0) { 14233e49ea7SAndi Kleen if (!child_finished) 143d20deb64SArnaldo Carvalho de Melo kill(rec->evlist->workload.pid, SIGTERM); 144933da83aSChris Wilson 14533e49ea7SAndi Kleen wait(&status); 14633e49ea7SAndi Kleen if (WIFSIGNALED(status)) 147d20deb64SArnaldo Carvalho de Melo psignal(WTERMSIG(status), rec->progname); 14833e49ea7SAndi Kleen } 14933e49ea7SAndi Kleen 15018483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 151f7b7c26eSPeter Zijlstra return; 152f7b7c26eSPeter Zijlstra 153f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 154f7b7c26eSPeter Zijlstra kill(getpid(), signr); 15586470930SIngo Molnar } 15686470930SIngo Molnar 157a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 158a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 159a91e5431SArnaldo Carvalho de Melo { 160a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 161a91e5431SArnaldo Carvalho de Melo 162a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 163a91e5431SArnaldo Carvalho de Melo return false; 164a91e5431SArnaldo Carvalho de Melo 165a91e5431SArnaldo Carvalho de Melo pair = list_entry(other->entries.next, struct perf_evsel, node); 166a91e5431SArnaldo Carvalho de Melo 167a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 168a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 169a91e5431SArnaldo Carvalho de Melo return false; 170a91e5431SArnaldo Carvalho de Melo pair = list_entry(pair->node.next, struct perf_evsel, node); 171a91e5431SArnaldo Carvalho de Melo } 172a91e5431SArnaldo Carvalho de Melo 173a91e5431SArnaldo Carvalho de Melo return true; 174a91e5431SArnaldo Carvalho de Melo } 175a91e5431SArnaldo Carvalho de Melo 176d20deb64SArnaldo Carvalho de Melo static void perf_record__open(struct perf_record *rec) 177dd7927f4SArnaldo Carvalho de Melo { 178727ab04eSArnaldo Carvalho de Melo struct perf_evsel *pos, *first; 179d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 180d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 181d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 182dd7927f4SArnaldo Carvalho de Melo 183727ab04eSArnaldo Carvalho de Melo first = list_entry(evlist->entries.next, struct perf_evsel, node); 184727ab04eSArnaldo Carvalho de Melo 185d20deb64SArnaldo Carvalho de Melo perf_evlist__config_attrs(evlist, opts); 1860f82ebc4SArnaldo Carvalho de Melo 187dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 188dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 189727ab04eSArnaldo Carvalho de Melo struct xyarray *group_fd = NULL; 190dd7927f4SArnaldo Carvalho de Melo /* 191dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 192dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 193dd7927f4SArnaldo Carvalho de Melo * 194dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 195dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 196dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 197dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 198dd7927f4SArnaldo Carvalho de Melo * 199dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 200dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 201dd7927f4SArnaldo Carvalho de Melo */ 202dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 203dd7927f4SArnaldo Carvalho de Melo 204d20deb64SArnaldo Carvalho de Melo if (opts->group && pos != first) 205727ab04eSArnaldo Carvalho de Melo group_fd = first->fd; 2069c90a61cSArnaldo Carvalho de Melo retry_sample_id: 207d20deb64SArnaldo Carvalho de Melo attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 2083da297a6SIngo Molnar try_again: 209ed80f581SArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 210d20deb64SArnaldo Carvalho de Melo opts->group, group_fd) < 0) { 21186470930SIngo Molnar int err = errno; 21286470930SIngo Molnar 213c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 214b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 215c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 216d20deb64SArnaldo Carvalho de Melo } else if (err == ENODEV && opts->cpu_list) { 217d6d901c2SZhang, Yanmin die("No such device - did you specify" 218d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 219d20deb64SArnaldo Carvalho de Melo } else if (err == EINVAL && opts->sample_id_all_avail) { 2209c90a61cSArnaldo Carvalho de Melo /* 2219c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2229c90a61cSArnaldo Carvalho de Melo */ 223d20deb64SArnaldo Carvalho de Melo opts->sample_id_all_avail = false; 224d20deb64SArnaldo Carvalho de Melo if (!opts->sample_time && !opts->raw_samples && !time_needed) 225eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 226eac23d1cSIan Munsie 2279c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 228d6d901c2SZhang, Yanmin } 2293da297a6SIngo Molnar 2303da297a6SIngo Molnar /* 2313da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2323da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 2333da297a6SIngo Molnar * is always available even if no PMU support: 2343da297a6SIngo Molnar */ 2353da297a6SIngo Molnar if (attr->type == PERF_TYPE_HARDWARE 236f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2373da297a6SIngo Molnar 2383da297a6SIngo Molnar if (verbose) 239ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 240ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2413da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 242f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 2433da297a6SIngo Molnar goto try_again; 2443da297a6SIngo Molnar } 245ca6a4258SDavid Ahern 246ca6a4258SDavid Ahern if (err == ENOENT) { 247ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 248ca6a4258SDavid Ahern event_name(pos)); 249ca6a4258SDavid Ahern exit(EXIT_FAILURE); 250ca6a4258SDavid Ahern } 251ca6a4258SDavid Ahern 25230c806a0SIngo Molnar printf("\n"); 253d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 254dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 255bfd45118SSimon Kaempflein 256bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 257bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 258d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 259d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 260d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 261d6d901c2SZhang, Yanmin " force-enable it.\n"); 262bfd45118SSimon Kaempflein #endif 263bfd45118SSimon Kaempflein 264cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 2657c6a1c65SPeter Zijlstra } 2667c6a1c65SPeter Zijlstra } 2677c6a1c65SPeter Zijlstra 2680a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 2690a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2700a102479SFrederic Weisbecker strerror(errno)); 2710a102479SFrederic Weisbecker exit(-1); 2720a102479SFrederic Weisbecker } 2730a102479SFrederic Weisbecker 274d20deb64SArnaldo Carvalho de Melo if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) 2750a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 2760a27d7f9SArnaldo Carvalho de Melo 277d20deb64SArnaldo Carvalho de Melo if (rec->file_new) 278a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 279a91e5431SArnaldo Carvalho de Melo else { 280a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 281a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 282a91e5431SArnaldo Carvalho de Melo exit(-1); 283dd7927f4SArnaldo Carvalho de Melo } 28486470930SIngo Molnar } 28586470930SIngo Molnar 286a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 287a91e5431SArnaldo Carvalho de Melo } 288a91e5431SArnaldo Carvalho de Melo 289d20deb64SArnaldo Carvalho de Melo static int process_buildids(struct perf_record *rec) 2906122e4e4SArnaldo Carvalho de Melo { 291d20deb64SArnaldo Carvalho de Melo u64 size = lseek(rec->output, 0, SEEK_CUR); 2926122e4e4SArnaldo Carvalho de Melo 2939f591fd7SArnaldo Carvalho de Melo if (size == 0) 2949f591fd7SArnaldo Carvalho de Melo return 0; 2959f591fd7SArnaldo Carvalho de Melo 296d20deb64SArnaldo Carvalho de Melo rec->session->fd = rec->output; 297d20deb64SArnaldo Carvalho de Melo return __perf_session__process_events(rec->session, rec->post_processing_offset, 298d20deb64SArnaldo Carvalho de Melo size - rec->post_processing_offset, 2996122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3006122e4e4SArnaldo Carvalho de Melo } 3016122e4e4SArnaldo Carvalho de Melo 302d20deb64SArnaldo Carvalho de Melo static void perf_record__exit(int status __used, void *arg) 303f5970550SPeter Zijlstra { 304d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = arg; 305f5970550SPeter Zijlstra 306d20deb64SArnaldo Carvalho de Melo if (!rec->opts.pipe_output) { 307d20deb64SArnaldo Carvalho de Melo rec->session->header.data_size += rec->bytes_written; 308d20deb64SArnaldo Carvalho de Melo 309d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 310d20deb64SArnaldo Carvalho de Melo process_buildids(rec); 311d20deb64SArnaldo Carvalho de Melo perf_session__write_header(rec->session, rec->evlist, 312d20deb64SArnaldo Carvalho de Melo rec->output, true); 313d20deb64SArnaldo Carvalho de Melo perf_session__delete(rec->session); 314d20deb64SArnaldo Carvalho de Melo perf_evlist__delete(rec->evlist); 315d65a458bSArnaldo Carvalho de Melo symbol__exit(); 316c7929e47STom Zanussi } 317f5970550SPeter Zijlstra } 318f5970550SPeter Zijlstra 3198115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 320a1645ce1SZhang, Yanmin { 321a1645ce1SZhang, Yanmin int err; 322d20deb64SArnaldo Carvalho de Melo struct perf_event_ops *ops = data; 323a1645ce1SZhang, Yanmin 32423346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 325a1645ce1SZhang, Yanmin return; 326a1645ce1SZhang, Yanmin 327a1645ce1SZhang, Yanmin /* 328a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 329a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 330a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 331a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 332a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 333a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 334a1645ce1SZhang, Yanmin */ 335d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(ops, process_synthesized_event, 336*743eb868SArnaldo Carvalho de Melo machine); 337a1645ce1SZhang, Yanmin if (err < 0) 338a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 33923346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 340a1645ce1SZhang, Yanmin 341a1645ce1SZhang, Yanmin /* 342a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 343a1645ce1SZhang, Yanmin * have no _text sometimes. 344a1645ce1SZhang, Yanmin */ 345d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event, 346*743eb868SArnaldo Carvalho de Melo machine, "_text"); 347a1645ce1SZhang, Yanmin if (err < 0) 348d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event, 349*743eb868SArnaldo Carvalho de Melo machine, "_stext"); 350a1645ce1SZhang, Yanmin if (err < 0) 351a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 35223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 353a1645ce1SZhang, Yanmin } 354a1645ce1SZhang, Yanmin 35598402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 35698402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 35798402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 35898402807SFrederic Weisbecker }; 35998402807SFrederic Weisbecker 360d20deb64SArnaldo Carvalho de Melo static void perf_record__mmap_read_all(struct perf_record *rec) 36198402807SFrederic Weisbecker { 3620e2e63ddSPeter Zijlstra int i; 36398402807SFrederic Weisbecker 364d20deb64SArnaldo Carvalho de Melo for (i = 0; i < rec->evlist->nr_mmaps; i++) { 365d20deb64SArnaldo Carvalho de Melo if (rec->evlist->mmap[i].base) 366d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read(rec, &rec->evlist->mmap[i]); 36798402807SFrederic Weisbecker } 36898402807SFrederic Weisbecker 369d20deb64SArnaldo Carvalho de Melo if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO)) 370d20deb64SArnaldo Carvalho de Melo write_output(rec, &finished_round_event, sizeof(finished_round_event)); 37198402807SFrederic Weisbecker } 37298402807SFrederic Weisbecker 373d20deb64SArnaldo Carvalho de Melo static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 37486470930SIngo Molnar { 37586470930SIngo Molnar struct stat st; 37686470930SIngo Molnar int flags; 377d20deb64SArnaldo Carvalho de Melo int err, output; 3788b412664SPeter Zijlstra unsigned long waking = 0; 37946be604bSZhang, Yanmin const bool forks = argc > 0; 38023346f21SArnaldo Carvalho de Melo struct machine *machine; 381d20deb64SArnaldo Carvalho de Melo struct perf_event_ops *ops = &rec->ops; 382d20deb64SArnaldo Carvalho de Melo struct perf_record_opts *opts = &rec->opts; 383d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list = rec->evlist; 384d20deb64SArnaldo Carvalho de Melo const char *output_name = rec->output_name; 385d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 38686470930SIngo Molnar 387d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 38833e49ea7SAndi Kleen 389d20deb64SArnaldo Carvalho de Melo rec->page_size = sysconf(_SC_PAGE_SIZE); 39086470930SIngo Molnar 391d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__sig_exit, rec); 392f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 393f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 39418483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 395f5970550SPeter Zijlstra 396d7065adbSFranck Bui-Huu if (!output_name) { 397d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 398d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 399d7065adbSFranck Bui-Huu else 400d20deb64SArnaldo Carvalho de Melo rec->output_name = output_name = "perf.data"; 401d7065adbSFranck Bui-Huu } 402d7065adbSFranck Bui-Huu if (output_name) { 403529870e3STom Zanussi if (!strcmp(output_name, "-")) 404d20deb64SArnaldo Carvalho de Melo opts->pipe_output = true; 405529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 406d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_FORCE) { 407b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 408b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 409b38d3464SArnaldo Carvalho de Melo output_name); 410b38d3464SArnaldo Carvalho de Melo unlink(oldname); 411b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 412b38d3464SArnaldo Carvalho de Melo } 413d20deb64SArnaldo Carvalho de Melo } else if (rec->write_mode == WRITE_APPEND) { 414d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 415266e0e21SPierre Habouzit } 416d7065adbSFranck Bui-Huu } 41786470930SIngo Molnar 418f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 419d20deb64SArnaldo Carvalho de Melo if (rec->write_mode == WRITE_APPEND) 420d20deb64SArnaldo Carvalho de Melo rec->file_new = 0; 42186470930SIngo Molnar else 42286470930SIngo Molnar flags |= O_TRUNC; 42386470930SIngo Molnar 424d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) 425529870e3STom Zanussi output = STDOUT_FILENO; 426529870e3STom Zanussi else 42786470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 42886470930SIngo Molnar if (output < 0) { 42986470930SIngo Molnar perror("failed to create output file"); 43086470930SIngo Molnar exit(-1); 43186470930SIngo Molnar } 43286470930SIngo Molnar 433d20deb64SArnaldo Carvalho de Melo rec->output = output; 434d20deb64SArnaldo Carvalho de Melo 4357865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 436d20deb64SArnaldo Carvalho de Melo rec->write_mode == WRITE_FORCE, false, NULL); 43794c744b6SArnaldo Carvalho de Melo if (session == NULL) { 438a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 439a9a70bbcSArnaldo Carvalho de Melo return -1; 440a9a70bbcSArnaldo Carvalho de Melo } 441a9a70bbcSArnaldo Carvalho de Melo 442d20deb64SArnaldo Carvalho de Melo rec->session = session; 443d20deb64SArnaldo Carvalho de Melo 444d20deb64SArnaldo Carvalho de Melo if (!rec->no_buildid) 445baa2f6ceSArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_BUILD_ID); 446baa2f6ceSArnaldo Carvalho de Melo 447d20deb64SArnaldo Carvalho de Melo if (!rec->file_new) { 448a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4494dc0a04bSArnaldo Carvalho de Melo if (err < 0) 45039d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4514dc0a04bSArnaldo Carvalho de Melo } 4524dc0a04bSArnaldo Carvalho de Melo 453361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) 45494c744b6SArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 45503456a15SFrederic Weisbecker 456fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_HOSTNAME); 457fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_OSRELEASE); 458fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_ARCH); 459fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUDESC); 460fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NRCPUS); 461fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_EVENT_DESC); 462fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CMDLINE); 463fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_VERSION); 464fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); 465fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_TOTAL_MEM); 466fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 467fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUID); 468fbe96f29SStephane Eranian 469d4db3f16SArnaldo Carvalho de Melo if (forks) { 470d20deb64SArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(evsel_list, opts, argv); 47135b9d88eSArnaldo Carvalho de Melo if (err < 0) { 47235b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 47335b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 474856e9660SPeter Zijlstra } 475856e9660SPeter Zijlstra } 476856e9660SPeter Zijlstra 477d20deb64SArnaldo Carvalho de Melo perf_record__open(rec); 47886470930SIngo Molnar 479712a4b60SArnaldo Carvalho de Melo /* 480d20deb64SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at perf_record__exit() 481712a4b60SArnaldo Carvalho de Melo */ 482d20deb64SArnaldo Carvalho de Melo on_exit(perf_record__exit, rec); 483712a4b60SArnaldo Carvalho de Melo 484d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 485529870e3STom Zanussi err = perf_header__write_pipe(output); 486529870e3STom Zanussi if (err < 0) 487529870e3STom Zanussi return err; 488d20deb64SArnaldo Carvalho de Melo } else if (rec->file_new) { 489a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 490361c99a6SArnaldo Carvalho de Melo output, false); 491d5eed904SArnaldo Carvalho de Melo if (err < 0) 492d5eed904SArnaldo Carvalho de Melo return err; 493d5eed904SArnaldo Carvalho de Melo } 4947c6a1c65SPeter Zijlstra 495d20deb64SArnaldo Carvalho de Melo rec->post_processing_offset = lseek(output, 0, SEEK_CUR); 4966122e4e4SArnaldo Carvalho de Melo 497*743eb868SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 498*743eb868SArnaldo Carvalho de Melo if (!machine) { 499*743eb868SArnaldo Carvalho de Melo pr_err("Couldn't find native kernel information.\n"); 500*743eb868SArnaldo Carvalho de Melo return -1; 501*743eb868SArnaldo Carvalho de Melo } 502*743eb868SArnaldo Carvalho de Melo 503d20deb64SArnaldo Carvalho de Melo if (opts->pipe_output) { 504d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_attrs(ops, session, 505a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5062c46dbb5STom Zanussi if (err < 0) { 5072c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5082c46dbb5STom Zanussi return err; 5092c46dbb5STom Zanussi } 510cd19a035STom Zanussi 511d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(ops, process_synthesized_event, 512*743eb868SArnaldo Carvalho de Melo machine); 513cd19a035STom Zanussi if (err < 0) { 514cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 515cd19a035STom Zanussi return err; 516cd19a035STom Zanussi } 5179215545eSTom Zanussi 518361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 51963e0c771STom Zanussi /* 52063e0c771STom Zanussi * FIXME err <= 0 here actually means that 52163e0c771STom Zanussi * there were no tracepoints so its not really 52263e0c771STom Zanussi * an error, just that we don't need to 52363e0c771STom Zanussi * synthesize anything. We really have to 52463e0c771STom Zanussi * return this more properly and also 52563e0c771STom Zanussi * propagate errors that now are calling die() 52663e0c771STom Zanussi */ 527d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(ops, output, evsel_list, 528*743eb868SArnaldo Carvalho de Melo process_synthesized_event); 52963e0c771STom Zanussi if (err <= 0) { 53063e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 53163e0c771STom Zanussi return err; 53263e0c771STom Zanussi } 533d20deb64SArnaldo Carvalho de Melo advance_output(rec, err); 5342c46dbb5STom Zanussi } 53563e0c771STom Zanussi } 5362c46dbb5STom Zanussi 537d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event, 538*743eb868SArnaldo Carvalho de Melo machine, "_text"); 53970162138SArnaldo Carvalho de Melo if (err < 0) 540d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(ops, process_synthesized_event, 541*743eb868SArnaldo Carvalho de Melo machine, "_stext"); 542c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 543c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 544c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 545c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 54656b03f3cSArnaldo Carvalho de Melo 547d20deb64SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(ops, process_synthesized_event, 548*743eb868SArnaldo Carvalho de Melo machine); 549c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 550c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 551c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 552c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 553c1a3a4b9SArnaldo Carvalho de Melo 554a1645ce1SZhang, Yanmin if (perf_guest) 555d20deb64SArnaldo Carvalho de Melo perf_session__process_machines(session, ops, 5568115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 557b7cece76SArnaldo Carvalho de Melo 558d20deb64SArnaldo Carvalho de Melo if (!opts->system_wide) 559d20deb64SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(ops, evsel_list->threads, 5608115d60cSArnaldo Carvalho de Melo process_synthesized_event, 561*743eb868SArnaldo Carvalho de Melo machine); 562234fbbf5SArnaldo Carvalho de Melo else 563d20deb64SArnaldo Carvalho de Melo perf_event__synthesize_threads(ops, process_synthesized_event, 564*743eb868SArnaldo Carvalho de Melo machine); 5657c6a1c65SPeter Zijlstra 566d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 56786470930SIngo Molnar struct sched_param param; 56886470930SIngo Molnar 569d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 57086470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 5716beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 57286470930SIngo Molnar exit(-1); 57386470930SIngo Molnar } 57486470930SIngo Molnar } 57586470930SIngo Molnar 576764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 577764e16a3SDavid Ahern 578856e9660SPeter Zijlstra /* 579856e9660SPeter Zijlstra * Let the child rip 580856e9660SPeter Zijlstra */ 581d4db3f16SArnaldo Carvalho de Melo if (forks) 58235b9d88eSArnaldo Carvalho de Melo perf_evlist__start_workload(evsel_list); 583856e9660SPeter Zijlstra 584649c48a9SPeter Zijlstra for (;;) { 585d20deb64SArnaldo Carvalho de Melo int hits = rec->samples; 58686470930SIngo Molnar 587d20deb64SArnaldo Carvalho de Melo perf_record__mmap_read_all(rec); 58886470930SIngo Molnar 589d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 590649c48a9SPeter Zijlstra if (done) 591649c48a9SPeter Zijlstra break; 5925c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 5938b412664SPeter Zijlstra waking++; 5948b412664SPeter Zijlstra } 5958b412664SPeter Zijlstra 5964152ab37SArnaldo Carvalho de Melo if (done) 5974152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 5988b412664SPeter Zijlstra } 5998b412664SPeter Zijlstra 60018483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 601b44308f5SArnaldo Carvalho de Melo return 0; 602b44308f5SArnaldo Carvalho de Melo 6038b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 60486470930SIngo Molnar 60586470930SIngo Molnar /* 60686470930SIngo Molnar * Approximate RIP event size: 24 bytes. 60786470930SIngo Molnar */ 60886470930SIngo Molnar fprintf(stderr, 6099486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 610d20deb64SArnaldo Carvalho de Melo (double)rec->bytes_written / 1024.0 / 1024.0, 61186470930SIngo Molnar output_name, 612d20deb64SArnaldo Carvalho de Melo rec->bytes_written / 24); 61386470930SIngo Molnar 61486470930SIngo Molnar return 0; 61539d17dacSArnaldo Carvalho de Melo 61639d17dacSArnaldo Carvalho de Melo out_delete_session: 61739d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 61839d17dacSArnaldo Carvalho de Melo return err; 61986470930SIngo Molnar } 62086470930SIngo Molnar 62186470930SIngo Molnar static const char * const record_usage[] = { 62286470930SIngo Molnar "perf record [<options>] [<command>]", 62386470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 62486470930SIngo Molnar NULL 62586470930SIngo Molnar }; 62686470930SIngo Molnar 627d20deb64SArnaldo Carvalho de Melo /* 628d20deb64SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 629d20deb64SArnaldo Carvalho de Melo * because we need to have access to it in perf_record__exit, that is called 630d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 631d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 632d20deb64SArnaldo Carvalho de Melo * 633d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 634d20deb64SArnaldo Carvalho de Melo * 635d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 636d20deb64SArnaldo Carvalho de Melo */ 637d20deb64SArnaldo Carvalho de Melo static struct perf_record record = { 638d20deb64SArnaldo Carvalho de Melo .opts = { 639d20deb64SArnaldo Carvalho de Melo .target_pid = -1, 640d20deb64SArnaldo Carvalho de Melo .target_tid = -1, 641d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 642d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 643d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 644d20deb64SArnaldo Carvalho de Melo .freq = 1000, 645d20deb64SArnaldo Carvalho de Melo .sample_id_all_avail = true, 646d20deb64SArnaldo Carvalho de Melo }, 647d20deb64SArnaldo Carvalho de Melo .write_mode = WRITE_FORCE, 648d20deb64SArnaldo Carvalho de Melo .file_new = true, 649d20deb64SArnaldo Carvalho de Melo }; 6507865e817SFrederic Weisbecker 651d20deb64SArnaldo Carvalho de Melo /* 652d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 653d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 654d20deb64SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use perf_record_opts, 655d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 656d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 657d20deb64SArnaldo Carvalho de Melo */ 658bca647aaSTom Zanussi const struct option record_options[] = { 659d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 66086470930SIngo Molnar "event selector. use 'perf list' to list available events", 661f120f9d5SJiri Olsa parse_events_option), 662d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 663c171b552SLi Zefan "event filter", parse_filter), 664d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('p', "pid", &record.opts.target_pid, 665d6d901c2SZhang, Yanmin "record events on existing process id"), 666d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('t', "tid", &record.opts.target_tid, 667d6d901c2SZhang, Yanmin "record events on existing thread id"), 668d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 66986470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 670d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 671acac03faSKirill Smelkov "collect data without buffering"), 672d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 673daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 674d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide, 67586470930SIngo Molnar "system-wide collection from all CPUs"), 676d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('A', "append", &record.append_file, 67786470930SIngo Molnar "append to the output file to do incremental profiling"), 678d20deb64SArnaldo Carvalho de Melo OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu", 679c45c6ea2SStephane Eranian "list of cpus to monitor"), 680d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('f', "force", &record.force, 6817865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 682d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 683d20deb64SArnaldo Carvalho de Melo OPT_STRING('o', "output", &record.output_name, "file", 68486470930SIngo Molnar "output file name"), 685d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 6862e6cdf99SStephane Eranian "child tasks do not inherit counters"), 687d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 688d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 68901c2d99bSArnaldo Carvalho de Melo "number of mmap data pages"), 690d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 69143bece79SLin Ming "put the counters into a counter group"), 692d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph, 6933efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 694c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 6953da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 696b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 697d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 698649c48a9SPeter Zijlstra "per thread counts"), 699d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record.opts.sample_address, 7004bba828dSAnton Blanchard "Sample addresses"), 701d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"), 702d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 703649c48a9SPeter Zijlstra "don't sample"), 704d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, 705a1ac1d3cSStephane Eranian "do not update the buildid cache"), 706d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, 707baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 708d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 709023695d9SStephane Eranian "monitor event in cgroup name only", 710023695d9SStephane Eranian parse_cgroups), 71186470930SIngo Molnar OPT_END() 71286470930SIngo Molnar }; 71386470930SIngo Molnar 714f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 71586470930SIngo Molnar { 71669aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 71769aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 718d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evsel_list; 719d20deb64SArnaldo Carvalho de Melo struct perf_record *rec = &record; 72086470930SIngo Molnar 721fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 722fbe96f29SStephane Eranian 7237e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 724361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 725361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 726361c99a6SArnaldo Carvalho de Melo 727d20deb64SArnaldo Carvalho de Melo rec->evlist = evsel_list; 728d20deb64SArnaldo Carvalho de Melo 729bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 730a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 731d20deb64SArnaldo Carvalho de Melo if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 732d20deb64SArnaldo Carvalho de Melo !rec->opts.system_wide && !rec->opts.cpu_list) 733bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 73486470930SIngo Molnar 735d20deb64SArnaldo Carvalho de Melo if (rec->force && rec->append_file) { 7367865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 7377865e817SFrederic Weisbecker " You need to choose between -f and -A"); 738bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 739d20deb64SArnaldo Carvalho de Melo } else if (rec->append_file) { 740d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_APPEND; 7417865e817SFrederic Weisbecker } else { 742d20deb64SArnaldo Carvalho de Melo rec->write_mode = WRITE_FORCE; 7437865e817SFrederic Weisbecker } 7447865e817SFrederic Weisbecker 745d20deb64SArnaldo Carvalho de Melo if (nr_cgroups && !rec->opts.system_wide) { 746023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 747023695d9SStephane Eranian " system-wide mode\n"); 748023695d9SStephane Eranian usage_with_options(record_usage, record_options); 749023695d9SStephane Eranian } 750023695d9SStephane Eranian 751655000e7SArnaldo Carvalho de Melo symbol__init(); 752baa2f6ceSArnaldo Carvalho de Melo 753ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 754646aaea6SArnaldo Carvalho de Melo pr_warning( 755646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 756ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 757646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 758646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 759646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 760646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 761646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 762ec80fde7SArnaldo Carvalho de Melo 763d20deb64SArnaldo Carvalho de Melo if (rec->no_buildid_cache || rec->no_buildid) 764a1ac1d3cSStephane Eranian disable_buildid_cache(); 765655000e7SArnaldo Carvalho de Melo 766361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 767361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 76869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 76969aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 770bbd36e5eSPeter Zijlstra } 77186470930SIngo Molnar 772d20deb64SArnaldo Carvalho de Melo if (rec->opts.target_pid != -1) 773d20deb64SArnaldo Carvalho de Melo rec->opts.target_tid = rec->opts.target_pid; 774d6d901c2SZhang, Yanmin 775d20deb64SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 776d20deb64SArnaldo Carvalho de Melo rec->opts.target_tid, rec->opts.cpu_list) < 0) 777dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 77869aad6f1SArnaldo Carvalho de Melo 779361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 7807e2ed097SArnaldo Carvalho de Melo if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, 7817e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr) < 0) 78269aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 783ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 784ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 785d6d901c2SZhang, Yanmin } 7865c581041SArnaldo Carvalho de Melo 7877e2ed097SArnaldo Carvalho de Melo if (perf_evlist__alloc_pollfd(evsel_list) < 0) 78839d17dacSArnaldo Carvalho de Melo goto out_free_fd; 789d6d901c2SZhang, Yanmin 790d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_interval != ULLONG_MAX) 791d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.user_interval; 792d20deb64SArnaldo Carvalho de Melo if (rec->opts.user_freq != UINT_MAX) 793d20deb64SArnaldo Carvalho de Melo rec->opts.freq = rec->opts.user_freq; 794f9212819SFrederic Weisbecker 7957e4ff9e3SMike Galbraith /* 7967e4ff9e3SMike Galbraith * User specified count overrides default frequency. 7977e4ff9e3SMike Galbraith */ 798d20deb64SArnaldo Carvalho de Melo if (rec->opts.default_interval) 799d20deb64SArnaldo Carvalho de Melo rec->opts.freq = 0; 800d20deb64SArnaldo Carvalho de Melo else if (rec->opts.freq) { 801d20deb64SArnaldo Carvalho de Melo rec->opts.default_interval = rec->opts.freq; 8027e4ff9e3SMike Galbraith } else { 8037e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 80439d17dacSArnaldo Carvalho de Melo err = -EINVAL; 8055c581041SArnaldo Carvalho de Melo goto out_free_fd; 8067e4ff9e3SMike Galbraith } 8077e4ff9e3SMike Galbraith 808d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 80939d17dacSArnaldo Carvalho de Melo out_free_fd: 8107e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 811d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 812d65a458bSArnaldo Carvalho de Melo symbol__exit(); 81339d17dacSArnaldo Carvalho de Melo return err; 81486470930SIngo Molnar } 815