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 38*0f82ebc4SArnaldo Carvalho de Melo static struct perf_record_opts record_opts = { 39*0f82ebc4SArnaldo Carvalho de Melo .target_pid = -1, 40*0f82ebc4SArnaldo Carvalho de Melo .target_tid = -1, 41*0f82ebc4SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 42*0f82ebc4SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 43*0f82ebc4SArnaldo Carvalho de Melo .freq = 1000, 44*0f82ebc4SArnaldo Carvalho de Melo .sample_id_all_avail = true, 45*0f82ebc4SArnaldo Carvalho de Melo }; 4686470930SIngo Molnar 4786470930SIngo Molnar static unsigned int page_size; 48800cd25cSFrederic Weisbecker static unsigned int mmap_pages = UINT_MAX; 4986470930SIngo Molnar static int output; 50529870e3STom Zanussi static int pipe_output = 0; 51d7065adbSFranck Bui-Huu static const char *output_name = NULL; 5243bece79SLin Ming static bool group = false; 531967936dSArnaldo Carvalho de Melo static int realtime_prio = 0; 54933da83aSChris Wilson static pid_t child_pid = -1; 557865e817SFrederic Weisbecker static enum write_mode_t write_mode = WRITE_FORCE; 56a1ac1d3cSStephane Eranian static bool no_buildid = false; 57baa2f6ceSArnaldo Carvalho de Melo static bool no_buildid_cache = false; 58361c99a6SArnaldo Carvalho de Melo static struct perf_evlist *evsel_list; 5986470930SIngo Molnar 6042e59d7dSIngo Molnar static long samples = 0; 6142e59d7dSIngo Molnar static u64 bytes_written = 0; 6286470930SIngo Molnar 63f5970550SPeter Zijlstra static int file_new = 1; 646122e4e4SArnaldo Carvalho de Melo static off_t post_processing_offset; 657c6a1c65SPeter Zijlstra 6694c744b6SArnaldo Carvalho de Melo static struct perf_session *session; 6733e49ea7SAndi Kleen static const char *progname; 68f5970550SPeter Zijlstra 699215545eSTom Zanussi static void advance_output(size_t size) 709215545eSTom Zanussi { 719215545eSTom Zanussi bytes_written += size; 729215545eSTom Zanussi } 739215545eSTom Zanussi 74f5970550SPeter Zijlstra static void write_output(void *buf, size_t size) 75f5970550SPeter Zijlstra { 76f5970550SPeter Zijlstra while (size) { 77f5970550SPeter Zijlstra int ret = write(output, buf, size); 78f5970550SPeter Zijlstra 79f5970550SPeter Zijlstra if (ret < 0) 80f5970550SPeter Zijlstra die("failed to write"); 81f5970550SPeter Zijlstra 82f5970550SPeter Zijlstra size -= ret; 83f5970550SPeter Zijlstra buf += ret; 84f5970550SPeter Zijlstra 85f5970550SPeter Zijlstra bytes_written += ret; 86f5970550SPeter Zijlstra } 87f5970550SPeter Zijlstra } 88f5970550SPeter Zijlstra 898115d60cSArnaldo Carvalho de Melo static int process_synthesized_event(union perf_event *event, 908d50e5b4SArnaldo Carvalho de Melo struct perf_sample *sample __used, 91d8f66248SArnaldo Carvalho de Melo struct perf_session *self __used) 92234fbbf5SArnaldo Carvalho de Melo { 936122e4e4SArnaldo Carvalho de Melo write_output(event, event->header.size); 94234fbbf5SArnaldo Carvalho de Melo return 0; 95234fbbf5SArnaldo Carvalho de Melo } 96234fbbf5SArnaldo Carvalho de Melo 97744bd8aaSArnaldo Carvalho de Melo static void mmap_read(struct perf_mmap *md) 9886470930SIngo Molnar { 99744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 10086470930SIngo Molnar unsigned int old = md->prev; 10186470930SIngo Molnar unsigned char *data = md->base + page_size; 10286470930SIngo Molnar unsigned long size; 10386470930SIngo Molnar void *buf; 10486470930SIngo Molnar 105dc82009aSArnaldo Carvalho de Melo if (old == head) 106dc82009aSArnaldo Carvalho de Melo return; 10786470930SIngo Molnar 10886470930SIngo Molnar samples++; 10986470930SIngo Molnar 11086470930SIngo Molnar size = head - old; 11186470930SIngo Molnar 11286470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 11386470930SIngo Molnar buf = &data[old & md->mask]; 11486470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 11586470930SIngo Molnar old += size; 11686470930SIngo Molnar 1176122e4e4SArnaldo Carvalho de Melo write_output(buf, size); 11886470930SIngo Molnar } 11986470930SIngo Molnar 12086470930SIngo Molnar buf = &data[old & md->mask]; 12186470930SIngo Molnar size = head - old; 12286470930SIngo Molnar old += size; 12386470930SIngo Molnar 1246122e4e4SArnaldo Carvalho de Melo write_output(buf, size); 12586470930SIngo Molnar 12686470930SIngo Molnar md->prev = old; 127115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 12886470930SIngo Molnar } 12986470930SIngo Molnar 13086470930SIngo Molnar static volatile int done = 0; 131f7b7c26eSPeter Zijlstra static volatile int signr = -1; 13233e49ea7SAndi Kleen static volatile int child_finished = 0; 13386470930SIngo Molnar 13486470930SIngo Molnar static void sig_handler(int sig) 13586470930SIngo Molnar { 13633e49ea7SAndi Kleen if (sig == SIGCHLD) 13733e49ea7SAndi Kleen child_finished = 1; 13833e49ea7SAndi Kleen 13986470930SIngo Molnar done = 1; 140f7b7c26eSPeter Zijlstra signr = sig; 141f7b7c26eSPeter Zijlstra } 142f7b7c26eSPeter Zijlstra 143f7b7c26eSPeter Zijlstra static void sig_atexit(void) 144f7b7c26eSPeter Zijlstra { 14533e49ea7SAndi Kleen int status; 14633e49ea7SAndi Kleen 14733e49ea7SAndi Kleen if (child_pid > 0) { 14833e49ea7SAndi Kleen if (!child_finished) 149933da83aSChris Wilson kill(child_pid, SIGTERM); 150933da83aSChris Wilson 15133e49ea7SAndi Kleen wait(&status); 15233e49ea7SAndi Kleen if (WIFSIGNALED(status)) 15333e49ea7SAndi Kleen psignal(WTERMSIG(status), progname); 15433e49ea7SAndi Kleen } 15533e49ea7SAndi Kleen 15618483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 157f7b7c26eSPeter Zijlstra return; 158f7b7c26eSPeter Zijlstra 159f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 160f7b7c26eSPeter Zijlstra kill(getpid(), signr); 16186470930SIngo Molnar } 16286470930SIngo Molnar 163a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 164a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 165a91e5431SArnaldo Carvalho de Melo { 166a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 167a91e5431SArnaldo Carvalho de Melo 168a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 169a91e5431SArnaldo Carvalho de Melo return false; 170a91e5431SArnaldo Carvalho de Melo 171a91e5431SArnaldo Carvalho de Melo pair = list_entry(other->entries.next, struct perf_evsel, node); 172a91e5431SArnaldo Carvalho de Melo 173a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 174a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 175a91e5431SArnaldo Carvalho de Melo return false; 176a91e5431SArnaldo Carvalho de Melo pair = list_entry(pair->node.next, struct perf_evsel, node); 177a91e5431SArnaldo Carvalho de Melo } 178a91e5431SArnaldo Carvalho de Melo 179a91e5431SArnaldo Carvalho de Melo return true; 180a91e5431SArnaldo Carvalho de Melo } 181a91e5431SArnaldo Carvalho de Melo 182dd7927f4SArnaldo Carvalho de Melo static void open_counters(struct perf_evlist *evlist) 183dd7927f4SArnaldo Carvalho de Melo { 184727ab04eSArnaldo Carvalho de Melo struct perf_evsel *pos, *first; 185dd7927f4SArnaldo Carvalho de Melo 186727ab04eSArnaldo Carvalho de Melo first = list_entry(evlist->entries.next, struct perf_evsel, node); 187727ab04eSArnaldo Carvalho de Melo 188*0f82ebc4SArnaldo Carvalho de Melo perf_evlist__config_attrs(evlist, &record_opts); 189*0f82ebc4SArnaldo Carvalho de Melo 190dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 191dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 192727ab04eSArnaldo Carvalho de Melo struct xyarray *group_fd = NULL; 193dd7927f4SArnaldo Carvalho de Melo /* 194dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 195dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 196dd7927f4SArnaldo Carvalho de Melo * 197dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 198dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 199dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 200dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 201dd7927f4SArnaldo Carvalho de Melo * 202dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 203dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 204dd7927f4SArnaldo Carvalho de Melo */ 205dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 206dd7927f4SArnaldo Carvalho de Melo 207727ab04eSArnaldo Carvalho de Melo if (group && pos != first) 208727ab04eSArnaldo Carvalho de Melo group_fd = first->fd; 2099c90a61cSArnaldo Carvalho de Melo retry_sample_id: 210*0f82ebc4SArnaldo Carvalho de Melo attr->sample_id_all = record_opts.sample_id_all_avail ? 1 : 0; 2113da297a6SIngo Molnar try_again: 212727ab04eSArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, 213727ab04eSArnaldo Carvalho de Melo group_fd) < 0) { 21486470930SIngo Molnar int err = errno; 21586470930SIngo Molnar 216c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 217b8631e6eSArnaldo Carvalho de Melo ui__error_paranoid(); 218c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 219*0f82ebc4SArnaldo Carvalho de Melo } else if (err == ENODEV && record_opts.cpu_list) { 220d6d901c2SZhang, Yanmin die("No such device - did you specify" 221d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 222*0f82ebc4SArnaldo Carvalho de Melo } else if (err == EINVAL && record_opts.sample_id_all_avail) { 2239c90a61cSArnaldo Carvalho de Melo /* 2249c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2259c90a61cSArnaldo Carvalho de Melo */ 226*0f82ebc4SArnaldo Carvalho de Melo record_opts.sample_id_all_avail = false; 227*0f82ebc4SArnaldo Carvalho de Melo if (!record_opts.sample_time && !record_opts.raw_samples && !time_needed) 228eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 229eac23d1cSIan Munsie 2309c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 231d6d901c2SZhang, Yanmin } 2323da297a6SIngo Molnar 2333da297a6SIngo Molnar /* 2343da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2353da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 2363da297a6SIngo Molnar * is always available even if no PMU support: 2373da297a6SIngo Molnar */ 2383da297a6SIngo Molnar if (attr->type == PERF_TYPE_HARDWARE 239f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 2403da297a6SIngo Molnar 2413da297a6SIngo Molnar if (verbose) 242ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 243ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 2443da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 245f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 2463da297a6SIngo Molnar goto try_again; 2473da297a6SIngo Molnar } 248ca6a4258SDavid Ahern 249ca6a4258SDavid Ahern if (err == ENOENT) { 250ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 251ca6a4258SDavid Ahern event_name(pos)); 252ca6a4258SDavid Ahern exit(EXIT_FAILURE); 253ca6a4258SDavid Ahern } 254ca6a4258SDavid Ahern 25530c806a0SIngo Molnar printf("\n"); 256d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 257dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 258bfd45118SSimon Kaempflein 259bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 260bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 261d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 262d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 263d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 264d6d901c2SZhang, Yanmin " force-enable it.\n"); 265bfd45118SSimon Kaempflein #endif 266bfd45118SSimon Kaempflein 267cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 2687c6a1c65SPeter Zijlstra } 2697c6a1c65SPeter Zijlstra } 2707c6a1c65SPeter Zijlstra 2710a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 2720a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 2730a102479SFrederic Weisbecker strerror(errno)); 2740a102479SFrederic Weisbecker exit(-1); 2750a102479SFrederic Weisbecker } 2760a102479SFrederic Weisbecker 2777e2ed097SArnaldo Carvalho de Melo if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) 2780a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 2790a27d7f9SArnaldo Carvalho de Melo 280a91e5431SArnaldo Carvalho de Melo if (file_new) 281a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 282a91e5431SArnaldo Carvalho de Melo else { 283a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 284a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 285a91e5431SArnaldo Carvalho de Melo exit(-1); 286dd7927f4SArnaldo Carvalho de Melo } 28786470930SIngo Molnar } 28886470930SIngo Molnar 289a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 290a91e5431SArnaldo Carvalho de Melo } 291a91e5431SArnaldo Carvalho de Melo 2926122e4e4SArnaldo Carvalho de Melo static int process_buildids(void) 2936122e4e4SArnaldo Carvalho de Melo { 2946122e4e4SArnaldo Carvalho de Melo u64 size = lseek(output, 0, SEEK_CUR); 2956122e4e4SArnaldo Carvalho de Melo 2969f591fd7SArnaldo Carvalho de Melo if (size == 0) 2979f591fd7SArnaldo Carvalho de Melo return 0; 2989f591fd7SArnaldo Carvalho de Melo 2996122e4e4SArnaldo Carvalho de Melo session->fd = output; 3006122e4e4SArnaldo Carvalho de Melo return __perf_session__process_events(session, post_processing_offset, 3016122e4e4SArnaldo Carvalho de Melo size - post_processing_offset, 3026122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3036122e4e4SArnaldo Carvalho de Melo } 3046122e4e4SArnaldo Carvalho de Melo 305f5970550SPeter Zijlstra static void atexit_header(void) 306f5970550SPeter Zijlstra { 307c7929e47STom Zanussi if (!pipe_output) { 30894c744b6SArnaldo Carvalho de Melo session->header.data_size += bytes_written; 309f5970550SPeter Zijlstra 310baa2f6ceSArnaldo Carvalho de Melo if (!no_buildid) 3116122e4e4SArnaldo Carvalho de Melo process_buildids(); 312a91e5431SArnaldo Carvalho de Melo perf_session__write_header(session, evsel_list, output, true); 31339d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 314361c99a6SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 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; 32223346f21SArnaldo Carvalho de Melo struct perf_session *psession = 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 */ 3358115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_modules(process_synthesized_event, 33623346f21SArnaldo Carvalho de Melo psession, 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 */ 3458115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 34623346f21SArnaldo Carvalho de Melo psession, machine, "_text"); 347a1645ce1SZhang, Yanmin if (err < 0) 3488115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 3498115d60cSArnaldo Carvalho de Melo psession, machine, 3508115d60cSArnaldo Carvalho de Melo "_stext"); 351a1645ce1SZhang, Yanmin if (err < 0) 352a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 35323346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 354a1645ce1SZhang, Yanmin } 355a1645ce1SZhang, Yanmin 35698402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 35798402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 35898402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 35998402807SFrederic Weisbecker }; 36098402807SFrederic Weisbecker 36198402807SFrederic Weisbecker static void mmap_read_all(void) 36298402807SFrederic Weisbecker { 3630e2e63ddSPeter Zijlstra int i; 36498402807SFrederic Weisbecker 365aece948fSArnaldo Carvalho de Melo for (i = 0; i < evsel_list->nr_mmaps; i++) { 3660a27d7f9SArnaldo Carvalho de Melo if (evsel_list->mmap[i].base) 3670a27d7f9SArnaldo Carvalho de Melo mmap_read(&evsel_list->mmap[i]); 36898402807SFrederic Weisbecker } 36998402807SFrederic Weisbecker 37098402807SFrederic Weisbecker if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 37198402807SFrederic Weisbecker write_output(&finished_round_event, sizeof(finished_round_event)); 37298402807SFrederic Weisbecker } 37398402807SFrederic Weisbecker 374d4db3f16SArnaldo Carvalho de Melo static int __cmd_record(int argc, const char **argv) 37586470930SIngo Molnar { 37686470930SIngo Molnar struct stat st; 37786470930SIngo Molnar int flags; 3784dc0a04bSArnaldo Carvalho de Melo int err; 3798b412664SPeter Zijlstra unsigned long waking = 0; 380856e9660SPeter Zijlstra int child_ready_pipe[2], go_pipe[2]; 38146be604bSZhang, Yanmin const bool forks = argc > 0; 382856e9660SPeter Zijlstra char buf; 38323346f21SArnaldo Carvalho de Melo struct machine *machine; 38486470930SIngo Molnar 38533e49ea7SAndi Kleen progname = argv[0]; 38633e49ea7SAndi Kleen 38786470930SIngo Molnar page_size = sysconf(_SC_PAGE_SIZE); 38886470930SIngo Molnar 389f5970550SPeter Zijlstra atexit(sig_atexit); 390f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 391f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 39218483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 393f5970550SPeter Zijlstra 394d4db3f16SArnaldo Carvalho de Melo if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 395856e9660SPeter Zijlstra perror("failed to create pipes"); 396856e9660SPeter Zijlstra exit(-1); 397856e9660SPeter Zijlstra } 398856e9660SPeter Zijlstra 399d7065adbSFranck Bui-Huu if (!output_name) { 400d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 401*0f82ebc4SArnaldo Carvalho de Melo pipe_output = true; 402d7065adbSFranck Bui-Huu else 403d7065adbSFranck Bui-Huu output_name = "perf.data"; 404d7065adbSFranck Bui-Huu } 405d7065adbSFranck Bui-Huu if (output_name) { 406529870e3STom Zanussi if (!strcmp(output_name, "-")) 407*0f82ebc4SArnaldo Carvalho de Melo pipe_output = true; 408529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 4097865e817SFrederic Weisbecker if (write_mode == WRITE_FORCE) { 410b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 411b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 412b38d3464SArnaldo Carvalho de Melo output_name); 413b38d3464SArnaldo Carvalho de Melo unlink(oldname); 414b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 415b38d3464SArnaldo Carvalho de Melo } 4167865e817SFrederic Weisbecker } else if (write_mode == WRITE_APPEND) { 4177865e817SFrederic Weisbecker write_mode = WRITE_FORCE; 418266e0e21SPierre Habouzit } 419d7065adbSFranck Bui-Huu } 42086470930SIngo Molnar 421f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 4227865e817SFrederic Weisbecker if (write_mode == WRITE_APPEND) 423f5970550SPeter Zijlstra file_new = 0; 42486470930SIngo Molnar else 42586470930SIngo Molnar flags |= O_TRUNC; 42686470930SIngo Molnar 427529870e3STom Zanussi if (pipe_output) 428529870e3STom Zanussi output = STDOUT_FILENO; 429529870e3STom Zanussi else 43086470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 43186470930SIngo Molnar if (output < 0) { 43286470930SIngo Molnar perror("failed to create output file"); 43386470930SIngo Molnar exit(-1); 43486470930SIngo Molnar } 43586470930SIngo Molnar 4367865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 43721ef97f0SIan Munsie write_mode == WRITE_FORCE, false, NULL); 43894c744b6SArnaldo Carvalho de Melo if (session == NULL) { 439a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 440a9a70bbcSArnaldo Carvalho de Melo return -1; 441a9a70bbcSArnaldo Carvalho de Melo } 442a9a70bbcSArnaldo Carvalho de Melo 443baa2f6ceSArnaldo Carvalho de Melo if (!no_buildid) 444baa2f6ceSArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_BUILD_ID); 445baa2f6ceSArnaldo Carvalho de Melo 4464dc0a04bSArnaldo Carvalho de Melo if (!file_new) { 447a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 4484dc0a04bSArnaldo Carvalho de Melo if (err < 0) 44939d17dacSArnaldo Carvalho de Melo goto out_delete_session; 4504dc0a04bSArnaldo Carvalho de Melo } 4514dc0a04bSArnaldo Carvalho de Melo 452361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) 45394c744b6SArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 45403456a15SFrederic Weisbecker 455fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_HOSTNAME); 456fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_OSRELEASE); 457fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_ARCH); 458fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUDESC); 459fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NRCPUS); 460fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_EVENT_DESC); 461fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CMDLINE); 462fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_VERSION); 463fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); 464fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_TOTAL_MEM); 465fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 466fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUID); 467fbe96f29SStephane Eranian 468800cd25cSFrederic Weisbecker /* 512 kiB: default amount of unprivileged mlocked memory */ 469800cd25cSFrederic Weisbecker if (mmap_pages == UINT_MAX) 470800cd25cSFrederic Weisbecker mmap_pages = (512 * 1024) / page_size; 471800cd25cSFrederic Weisbecker 472d4db3f16SArnaldo Carvalho de Melo if (forks) { 47346be604bSZhang, Yanmin child_pid = fork(); 4742fb750e8SBorislav Petkov if (child_pid < 0) { 475856e9660SPeter Zijlstra perror("failed to fork"); 476856e9660SPeter Zijlstra exit(-1); 477856e9660SPeter Zijlstra } 4787c6a1c65SPeter Zijlstra 47946be604bSZhang, Yanmin if (!child_pid) { 480529870e3STom Zanussi if (pipe_output) 481529870e3STom Zanussi dup2(2, 1); 482856e9660SPeter Zijlstra close(child_ready_pipe[0]); 483856e9660SPeter Zijlstra close(go_pipe[1]); 484856e9660SPeter Zijlstra fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 485856e9660SPeter Zijlstra 486856e9660SPeter Zijlstra /* 487856e9660SPeter Zijlstra * Do a dummy execvp to get the PLT entry resolved, 488856e9660SPeter Zijlstra * so we avoid the resolver overhead on the real 489856e9660SPeter Zijlstra * execvp call. 490856e9660SPeter Zijlstra */ 491856e9660SPeter Zijlstra execvp("", (char **)argv); 492856e9660SPeter Zijlstra 493856e9660SPeter Zijlstra /* 494856e9660SPeter Zijlstra * Tell the parent we're ready to go 495856e9660SPeter Zijlstra */ 496856e9660SPeter Zijlstra close(child_ready_pipe[1]); 497856e9660SPeter Zijlstra 498856e9660SPeter Zijlstra /* 499856e9660SPeter Zijlstra * Wait until the parent tells us to go. 500856e9660SPeter Zijlstra */ 501856e9660SPeter Zijlstra if (read(go_pipe[0], &buf, 1) == -1) 502856e9660SPeter Zijlstra perror("unable to read pipe"); 503856e9660SPeter Zijlstra 504856e9660SPeter Zijlstra execvp(argv[0], (char **)argv); 505856e9660SPeter Zijlstra 506856e9660SPeter Zijlstra perror(argv[0]); 50718483b81SArnaldo Carvalho de Melo kill(getppid(), SIGUSR1); 508856e9660SPeter Zijlstra exit(-1); 509856e9660SPeter Zijlstra } 510856e9660SPeter Zijlstra 511*0f82ebc4SArnaldo Carvalho de Melo if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1) 5127e2ed097SArnaldo Carvalho de Melo evsel_list->threads->map[0] = child_pid; 513d6d901c2SZhang, Yanmin 514856e9660SPeter Zijlstra close(child_ready_pipe[1]); 515856e9660SPeter Zijlstra close(go_pipe[0]); 516856e9660SPeter Zijlstra /* 517856e9660SPeter Zijlstra * wait for child to settle 518856e9660SPeter Zijlstra */ 519856e9660SPeter Zijlstra if (read(child_ready_pipe[0], &buf, 1) == -1) { 520856e9660SPeter Zijlstra perror("unable to read pipe"); 521856e9660SPeter Zijlstra exit(-1); 522856e9660SPeter Zijlstra } 523856e9660SPeter Zijlstra close(child_ready_pipe[0]); 524856e9660SPeter Zijlstra } 525856e9660SPeter Zijlstra 526dd7927f4SArnaldo Carvalho de Melo open_counters(evsel_list); 52786470930SIngo Molnar 528712a4b60SArnaldo Carvalho de Melo /* 529712a4b60SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at atexit_header() 530712a4b60SArnaldo Carvalho de Melo */ 531712a4b60SArnaldo Carvalho de Melo atexit(atexit_header); 532712a4b60SArnaldo Carvalho de Melo 533529870e3STom Zanussi if (pipe_output) { 534529870e3STom Zanussi err = perf_header__write_pipe(output); 535529870e3STom Zanussi if (err < 0) 536529870e3STom Zanussi return err; 537529870e3STom Zanussi } else if (file_new) { 538a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 539361c99a6SArnaldo Carvalho de Melo output, false); 540d5eed904SArnaldo Carvalho de Melo if (err < 0) 541d5eed904SArnaldo Carvalho de Melo return err; 542d5eed904SArnaldo Carvalho de Melo } 5437c6a1c65SPeter Zijlstra 5446122e4e4SArnaldo Carvalho de Melo post_processing_offset = lseek(output, 0, SEEK_CUR); 5456122e4e4SArnaldo Carvalho de Melo 5462c46dbb5STom Zanussi if (pipe_output) { 547a91e5431SArnaldo Carvalho de Melo err = perf_session__synthesize_attrs(session, 548a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5492c46dbb5STom Zanussi if (err < 0) { 5502c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5512c46dbb5STom Zanussi return err; 5522c46dbb5STom Zanussi } 553cd19a035STom Zanussi 5548115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(process_synthesized_event, 555cd19a035STom Zanussi session); 556cd19a035STom Zanussi if (err < 0) { 557cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 558cd19a035STom Zanussi return err; 559cd19a035STom Zanussi } 5609215545eSTom Zanussi 561361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 56263e0c771STom Zanussi /* 56363e0c771STom Zanussi * FIXME err <= 0 here actually means that 56463e0c771STom Zanussi * there were no tracepoints so its not really 56563e0c771STom Zanussi * an error, just that we don't need to 56663e0c771STom Zanussi * synthesize anything. We really have to 56763e0c771STom Zanussi * return this more properly and also 56863e0c771STom Zanussi * propagate errors that now are calling die() 56963e0c771STom Zanussi */ 5708115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(output, evsel_list, 5719215545eSTom Zanussi process_synthesized_event, 5729215545eSTom Zanussi session); 57363e0c771STom Zanussi if (err <= 0) { 57463e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 57563e0c771STom Zanussi return err; 57663e0c771STom Zanussi } 5779215545eSTom Zanussi advance_output(err); 5782c46dbb5STom Zanussi } 57963e0c771STom Zanussi } 5802c46dbb5STom Zanussi 58123346f21SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 58223346f21SArnaldo Carvalho de Melo if (!machine) { 583a1645ce1SZhang, Yanmin pr_err("Couldn't find native kernel information.\n"); 584a1645ce1SZhang, Yanmin return -1; 585a1645ce1SZhang, Yanmin } 586a1645ce1SZhang, Yanmin 5878115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 58823346f21SArnaldo Carvalho de Melo session, machine, "_text"); 58970162138SArnaldo Carvalho de Melo if (err < 0) 5908115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 59123346f21SArnaldo Carvalho de Melo session, machine, "_stext"); 592c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 593c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 594c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 595c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 59656b03f3cSArnaldo Carvalho de Melo 5978115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_modules(process_synthesized_event, 59823346f21SArnaldo Carvalho de Melo session, machine); 599c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 600c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 601c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 602c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 603c1a3a4b9SArnaldo Carvalho de Melo 604a1645ce1SZhang, Yanmin if (perf_guest) 6058115d60cSArnaldo Carvalho de Melo perf_session__process_machines(session, 6068115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 607b7cece76SArnaldo Carvalho de Melo 608*0f82ebc4SArnaldo Carvalho de Melo if (!record_opts.system_wide) 6097c940c18SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(evsel_list->threads, 6108115d60cSArnaldo Carvalho de Melo process_synthesized_event, 611d8f66248SArnaldo Carvalho de Melo session); 612234fbbf5SArnaldo Carvalho de Melo else 6138115d60cSArnaldo Carvalho de Melo perf_event__synthesize_threads(process_synthesized_event, 6148115d60cSArnaldo Carvalho de Melo session); 6157c6a1c65SPeter Zijlstra 61686470930SIngo Molnar if (realtime_prio) { 61786470930SIngo Molnar struct sched_param param; 61886470930SIngo Molnar 61986470930SIngo Molnar param.sched_priority = realtime_prio; 62086470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6216beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 62286470930SIngo Molnar exit(-1); 62386470930SIngo Molnar } 62486470930SIngo Molnar } 62586470930SIngo Molnar 626764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 627764e16a3SDavid Ahern 628856e9660SPeter Zijlstra /* 629856e9660SPeter Zijlstra * Let the child rip 630856e9660SPeter Zijlstra */ 631d4db3f16SArnaldo Carvalho de Melo if (forks) 632856e9660SPeter Zijlstra close(go_pipe[1]); 633856e9660SPeter Zijlstra 634649c48a9SPeter Zijlstra for (;;) { 63586470930SIngo Molnar int hits = samples; 63686470930SIngo Molnar 63798402807SFrederic Weisbecker mmap_read_all(); 63886470930SIngo Molnar 639649c48a9SPeter Zijlstra if (hits == samples) { 640649c48a9SPeter Zijlstra if (done) 641649c48a9SPeter Zijlstra break; 6425c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6438b412664SPeter Zijlstra waking++; 6448b412664SPeter Zijlstra } 6458b412664SPeter Zijlstra 6464152ab37SArnaldo Carvalho de Melo if (done) 6474152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6488b412664SPeter Zijlstra } 6498b412664SPeter Zijlstra 65018483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 651b44308f5SArnaldo Carvalho de Melo return 0; 652b44308f5SArnaldo Carvalho de Melo 6538b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 65486470930SIngo Molnar 65586470930SIngo Molnar /* 65686470930SIngo Molnar * Approximate RIP event size: 24 bytes. 65786470930SIngo Molnar */ 65886470930SIngo Molnar fprintf(stderr, 6599486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 66086470930SIngo Molnar (double)bytes_written / 1024.0 / 1024.0, 66186470930SIngo Molnar output_name, 66286470930SIngo Molnar bytes_written / 24); 66386470930SIngo Molnar 66486470930SIngo Molnar return 0; 66539d17dacSArnaldo Carvalho de Melo 66639d17dacSArnaldo Carvalho de Melo out_delete_session: 66739d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 66839d17dacSArnaldo Carvalho de Melo return err; 66986470930SIngo Molnar } 67086470930SIngo Molnar 67186470930SIngo Molnar static const char * const record_usage[] = { 67286470930SIngo Molnar "perf record [<options>] [<command>]", 67386470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 67486470930SIngo Molnar NULL 67586470930SIngo Molnar }; 67686470930SIngo Molnar 6777865e817SFrederic Weisbecker static bool force, append_file; 6787865e817SFrederic Weisbecker 679bca647aaSTom Zanussi const struct option record_options[] = { 680361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 68186470930SIngo Molnar "event selector. use 'perf list' to list available events", 682f120f9d5SJiri Olsa parse_events_option), 683361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &evsel_list, "filter", 684c171b552SLi Zefan "event filter", parse_filter), 685*0f82ebc4SArnaldo Carvalho de Melo OPT_INTEGER('p', "pid", &record_opts.target_pid, 686d6d901c2SZhang, Yanmin "record events on existing process id"), 687*0f82ebc4SArnaldo Carvalho de Melo OPT_INTEGER('t', "tid", &record_opts.target_tid, 688d6d901c2SZhang, Yanmin "record events on existing thread id"), 68986470930SIngo Molnar OPT_INTEGER('r', "realtime", &realtime_prio, 69086470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 691*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('D', "no-delay", &record_opts.no_delay, 692acac03faSKirill Smelkov "collect data without buffering"), 693*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record_opts.raw_samples, 694daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 695*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('a', "all-cpus", &record_opts.system_wide, 69686470930SIngo Molnar "system-wide collection from all CPUs"), 69786470930SIngo Molnar OPT_BOOLEAN('A', "append", &append_file, 69886470930SIngo Molnar "append to the output file to do incremental profiling"), 699*0f82ebc4SArnaldo Carvalho de Melo OPT_STRING('C', "cpu", &record_opts.cpu_list, "cpu", 700c45c6ea2SStephane Eranian "list of cpus to monitor"), 70186470930SIngo Molnar OPT_BOOLEAN('f', "force", &force, 7027865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 703*0f82ebc4SArnaldo Carvalho de Melo OPT_U64('c', "count", &record_opts.user_interval, "event period to sample"), 70486470930SIngo Molnar OPT_STRING('o', "output", &output_name, "file", 70586470930SIngo Molnar "output file name"), 706*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('i', "no-inherit", &record_opts.no_inherit, 7072e6cdf99SStephane Eranian "child tasks do not inherit counters"), 708*0f82ebc4SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record_opts.user_freq, "profile at this frequency"), 7091967936dSArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 71043bece79SLin Ming OPT_BOOLEAN(0, "group", &group, 71143bece79SLin Ming "put the counters into a counter group"), 712*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('g', "call-graph", &record_opts.call_graph, 7133efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 714c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7153da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 716b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 717*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record_opts.inherit_stat, 718649c48a9SPeter Zijlstra "per thread counts"), 719*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('d', "data", &record_opts.sample_address, 7204bba828dSAnton Blanchard "Sample addresses"), 721*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &record_opts.sample_time, "Sample timestamps"), 722*0f82ebc4SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record_opts.no_samples, 723649c48a9SPeter Zijlstra "don't sample"), 724baa2f6ceSArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 725a1ac1d3cSStephane Eranian "do not update the buildid cache"), 726baa2f6ceSArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &no_buildid, 727baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 728023695d9SStephane Eranian OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 729023695d9SStephane Eranian "monitor event in cgroup name only", 730023695d9SStephane Eranian parse_cgroups), 73186470930SIngo Molnar OPT_END() 73286470930SIngo Molnar }; 73386470930SIngo Molnar 734f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 73586470930SIngo Molnar { 73669aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 73769aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 73886470930SIngo Molnar 739fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 740fbe96f29SStephane Eranian 7417e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 742361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 743361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 744361c99a6SArnaldo Carvalho de Melo 745bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 746a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 747*0f82ebc4SArnaldo Carvalho de Melo if (!argc && record_opts.target_pid == -1 && record_opts.target_tid == -1 && 748*0f82ebc4SArnaldo Carvalho de Melo !record_opts.system_wide && !record_opts.cpu_list) 749bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 75086470930SIngo Molnar 7517865e817SFrederic Weisbecker if (force && append_file) { 7527865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 7537865e817SFrederic Weisbecker " You need to choose between -f and -A"); 754bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 7557865e817SFrederic Weisbecker } else if (append_file) { 7567865e817SFrederic Weisbecker write_mode = WRITE_APPEND; 7577865e817SFrederic Weisbecker } else { 7587865e817SFrederic Weisbecker write_mode = WRITE_FORCE; 7597865e817SFrederic Weisbecker } 7607865e817SFrederic Weisbecker 761*0f82ebc4SArnaldo Carvalho de Melo if (nr_cgroups && !record_opts.system_wide) { 762023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 763023695d9SStephane Eranian " system-wide mode\n"); 764023695d9SStephane Eranian usage_with_options(record_usage, record_options); 765023695d9SStephane Eranian } 766023695d9SStephane Eranian 767655000e7SArnaldo Carvalho de Melo symbol__init(); 768baa2f6ceSArnaldo Carvalho de Melo 769ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 770646aaea6SArnaldo Carvalho de Melo pr_warning( 771646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 772ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 773646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 774646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 775646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 776646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 777646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 778ec80fde7SArnaldo Carvalho de Melo 779baa2f6ceSArnaldo Carvalho de Melo if (no_buildid_cache || no_buildid) 780a1ac1d3cSStephane Eranian disable_buildid_cache(); 781655000e7SArnaldo Carvalho de Melo 782361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 783361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 78469aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 78569aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 786bbd36e5eSPeter Zijlstra } 78786470930SIngo Molnar 788*0f82ebc4SArnaldo Carvalho de Melo if (record_opts.target_pid != -1) 789*0f82ebc4SArnaldo Carvalho de Melo record_opts.target_tid = record_opts.target_pid; 790d6d901c2SZhang, Yanmin 791*0f82ebc4SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, record_opts.target_pid, 792*0f82ebc4SArnaldo Carvalho de Melo record_opts.target_tid, record_opts.cpu_list) < 0) 793dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 79469aad6f1SArnaldo Carvalho de Melo 795361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 7967e2ed097SArnaldo Carvalho de Melo if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, 7977e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr) < 0) 79869aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 799ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 800ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 801d6d901c2SZhang, Yanmin } 8025c581041SArnaldo Carvalho de Melo 8037e2ed097SArnaldo Carvalho de Melo if (perf_evlist__alloc_pollfd(evsel_list) < 0) 80439d17dacSArnaldo Carvalho de Melo goto out_free_fd; 805d6d901c2SZhang, Yanmin 806*0f82ebc4SArnaldo Carvalho de Melo if (record_opts.user_interval != ULLONG_MAX) 807*0f82ebc4SArnaldo Carvalho de Melo record_opts.default_interval = record_opts.user_interval; 808*0f82ebc4SArnaldo Carvalho de Melo if (record_opts.user_freq != UINT_MAX) 809*0f82ebc4SArnaldo Carvalho de Melo record_opts.freq = record_opts.user_freq; 810f9212819SFrederic Weisbecker 8117e4ff9e3SMike Galbraith /* 8127e4ff9e3SMike Galbraith * User specified count overrides default frequency. 8137e4ff9e3SMike Galbraith */ 814*0f82ebc4SArnaldo Carvalho de Melo if (record_opts.default_interval) 815*0f82ebc4SArnaldo Carvalho de Melo record_opts.freq = 0; 816*0f82ebc4SArnaldo Carvalho de Melo else if (record_opts.freq) { 817*0f82ebc4SArnaldo Carvalho de Melo record_opts.default_interval = record_opts.freq; 8187e4ff9e3SMike Galbraith } else { 8197e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 82039d17dacSArnaldo Carvalho de Melo err = -EINVAL; 8215c581041SArnaldo Carvalho de Melo goto out_free_fd; 8227e4ff9e3SMike Galbraith } 8237e4ff9e3SMike Galbraith 82439d17dacSArnaldo Carvalho de Melo err = __cmd_record(argc, argv); 82539d17dacSArnaldo Carvalho de Melo out_free_fd: 8267e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 827d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 828d65a458bSArnaldo Carvalho de Melo symbol__exit(); 82939d17dacSArnaldo Carvalho de Melo return err; 83086470930SIngo Molnar } 831