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 383de29cabSStephane Eranian static u64 user_interval = ULLONG_MAX; 393de29cabSStephane Eranian static u64 default_interval = 0; 4086470930SIngo Molnar 4186470930SIngo Molnar static unsigned int page_size; 42800cd25cSFrederic Weisbecker static unsigned int mmap_pages = UINT_MAX; 43f9212819SFrederic Weisbecker static unsigned int user_freq = UINT_MAX; 4442e59d7dSIngo Molnar static int freq = 1000; 4586470930SIngo Molnar static int output; 46529870e3STom Zanussi static int pipe_output = 0; 47d7065adbSFranck Bui-Huu static const char *output_name = NULL; 4843bece79SLin Ming static bool group = false; 491967936dSArnaldo Carvalho de Melo static int realtime_prio = 0; 50acac03faSKirill Smelkov static bool nodelay = false; 51c0555642SIan Munsie static bool raw_samples = false; 529c90a61cSArnaldo Carvalho de Melo static bool sample_id_all_avail = true; 53c0555642SIan Munsie static bool system_wide = false; 5486470930SIngo Molnar static pid_t target_pid = -1; 55d6d901c2SZhang, Yanmin static pid_t target_tid = -1; 56933da83aSChris Wilson static pid_t child_pid = -1; 572e6cdf99SStephane Eranian static bool no_inherit = false; 587865e817SFrederic Weisbecker static enum write_mode_t write_mode = WRITE_FORCE; 59c0555642SIan Munsie static bool call_graph = false; 60c0555642SIan Munsie static bool inherit_stat = false; 61c0555642SIan Munsie static bool no_samples = false; 62c0555642SIan Munsie static bool sample_address = false; 639c90a61cSArnaldo Carvalho de Melo static bool sample_time = false; 64a1ac1d3cSStephane Eranian static bool no_buildid = false; 65baa2f6ceSArnaldo Carvalho de Melo static bool no_buildid_cache = false; 66361c99a6SArnaldo Carvalho de Melo static struct perf_evlist *evsel_list; 6786470930SIngo Molnar 6842e59d7dSIngo Molnar static long samples = 0; 6942e59d7dSIngo Molnar static u64 bytes_written = 0; 7086470930SIngo Molnar 71f5970550SPeter Zijlstra static int file_new = 1; 726122e4e4SArnaldo Carvalho de Melo static off_t post_processing_offset; 737c6a1c65SPeter Zijlstra 7494c744b6SArnaldo Carvalho de Melo static struct perf_session *session; 75c45c6ea2SStephane Eranian static const char *cpu_list; 7633e49ea7SAndi Kleen static const char *progname; 77f5970550SPeter Zijlstra 789215545eSTom Zanussi static void advance_output(size_t size) 799215545eSTom Zanussi { 809215545eSTom Zanussi bytes_written += size; 819215545eSTom Zanussi } 829215545eSTom Zanussi 83f5970550SPeter Zijlstra static void write_output(void *buf, size_t size) 84f5970550SPeter Zijlstra { 85f5970550SPeter Zijlstra while (size) { 86f5970550SPeter Zijlstra int ret = write(output, buf, size); 87f5970550SPeter Zijlstra 88f5970550SPeter Zijlstra if (ret < 0) 89f5970550SPeter Zijlstra die("failed to write"); 90f5970550SPeter Zijlstra 91f5970550SPeter Zijlstra size -= ret; 92f5970550SPeter Zijlstra buf += ret; 93f5970550SPeter Zijlstra 94f5970550SPeter Zijlstra bytes_written += ret; 95f5970550SPeter Zijlstra } 96f5970550SPeter Zijlstra } 97f5970550SPeter Zijlstra 988115d60cSArnaldo Carvalho de Melo static int process_synthesized_event(union perf_event *event, 998d50e5b4SArnaldo Carvalho de Melo struct perf_sample *sample __used, 100d8f66248SArnaldo Carvalho de Melo struct perf_session *self __used) 101234fbbf5SArnaldo Carvalho de Melo { 1026122e4e4SArnaldo Carvalho de Melo write_output(event, event->header.size); 103234fbbf5SArnaldo Carvalho de Melo return 0; 104234fbbf5SArnaldo Carvalho de Melo } 105234fbbf5SArnaldo Carvalho de Melo 106744bd8aaSArnaldo Carvalho de Melo static void mmap_read(struct perf_mmap *md) 10786470930SIngo Molnar { 108744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 10986470930SIngo Molnar unsigned int old = md->prev; 11086470930SIngo Molnar unsigned char *data = md->base + page_size; 11186470930SIngo Molnar unsigned long size; 11286470930SIngo Molnar void *buf; 11386470930SIngo Molnar 114dc82009aSArnaldo Carvalho de Melo if (old == head) 115dc82009aSArnaldo Carvalho de Melo return; 11686470930SIngo Molnar 11786470930SIngo Molnar samples++; 11886470930SIngo Molnar 11986470930SIngo Molnar size = head - old; 12086470930SIngo Molnar 12186470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 12286470930SIngo Molnar buf = &data[old & md->mask]; 12386470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 12486470930SIngo Molnar old += size; 12586470930SIngo Molnar 1266122e4e4SArnaldo Carvalho de Melo write_output(buf, size); 12786470930SIngo Molnar } 12886470930SIngo Molnar 12986470930SIngo Molnar buf = &data[old & md->mask]; 13086470930SIngo Molnar size = head - old; 13186470930SIngo Molnar old += size; 13286470930SIngo Molnar 1336122e4e4SArnaldo Carvalho de Melo write_output(buf, size); 13486470930SIngo Molnar 13586470930SIngo Molnar md->prev = old; 136115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 13786470930SIngo Molnar } 13886470930SIngo Molnar 13986470930SIngo Molnar static volatile int done = 0; 140f7b7c26eSPeter Zijlstra static volatile int signr = -1; 14133e49ea7SAndi Kleen static volatile int child_finished = 0; 14286470930SIngo Molnar 14386470930SIngo Molnar static void sig_handler(int sig) 14486470930SIngo Molnar { 14533e49ea7SAndi Kleen if (sig == SIGCHLD) 14633e49ea7SAndi Kleen child_finished = 1; 14733e49ea7SAndi Kleen 14886470930SIngo Molnar done = 1; 149f7b7c26eSPeter Zijlstra signr = sig; 150f7b7c26eSPeter Zijlstra } 151f7b7c26eSPeter Zijlstra 152f7b7c26eSPeter Zijlstra static void sig_atexit(void) 153f7b7c26eSPeter Zijlstra { 15433e49ea7SAndi Kleen int status; 15533e49ea7SAndi Kleen 15633e49ea7SAndi Kleen if (child_pid > 0) { 15733e49ea7SAndi Kleen if (!child_finished) 158933da83aSChris Wilson kill(child_pid, SIGTERM); 159933da83aSChris Wilson 16033e49ea7SAndi Kleen wait(&status); 16133e49ea7SAndi Kleen if (WIFSIGNALED(status)) 16233e49ea7SAndi Kleen psignal(WTERMSIG(status), progname); 16333e49ea7SAndi Kleen } 16433e49ea7SAndi Kleen 16518483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 166f7b7c26eSPeter Zijlstra return; 167f7b7c26eSPeter Zijlstra 168f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 169f7b7c26eSPeter Zijlstra kill(getpid(), signr); 17086470930SIngo Molnar } 17186470930SIngo Molnar 172dd7927f4SArnaldo Carvalho de Melo static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) 173dd7927f4SArnaldo Carvalho de Melo { 174dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &evsel->attr; 175dd7927f4SArnaldo Carvalho de Melo int track = !evsel->idx; /* only the first counter needs these */ 1767c6a1c65SPeter Zijlstra 177764e16a3SDavid Ahern attr->disabled = 1; 1785d2cd909SArnaldo Carvalho de Melo attr->inherit = !no_inherit; 1797c6a1c65SPeter Zijlstra attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 1807c6a1c65SPeter Zijlstra PERF_FORMAT_TOTAL_TIME_RUNNING | 1817c6a1c65SPeter Zijlstra PERF_FORMAT_ID; 18286470930SIngo Molnar 1833a9f131fSFrederic Weisbecker attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1843efa1cc9SIngo Molnar 185361c99a6SArnaldo Carvalho de Melo if (evlist->nr_entries > 1) 1868907fd60SEric B Munson attr->sample_type |= PERF_SAMPLE_ID; 1878907fd60SEric B Munson 188f9212819SFrederic Weisbecker /* 189f9212819SFrederic Weisbecker * We default some events to a 1 default interval. But keep 190f9212819SFrederic Weisbecker * it a weak assumption overridable by the user. 191f9212819SFrederic Weisbecker */ 192f9212819SFrederic Weisbecker if (!attr->sample_period || (user_freq != UINT_MAX && 1933de29cabSStephane Eranian user_interval != ULLONG_MAX)) { 19486470930SIngo Molnar if (freq) { 195ea1900e5SPeter Zijlstra attr->sample_type |= PERF_SAMPLE_PERIOD; 19686470930SIngo Molnar attr->freq = 1; 19786470930SIngo Molnar attr->sample_freq = freq; 198f9212819SFrederic Weisbecker } else { 199f9212819SFrederic Weisbecker attr->sample_period = default_interval; 200f9212819SFrederic Weisbecker } 20186470930SIngo Molnar } 2023efa1cc9SIngo Molnar 203649c48a9SPeter Zijlstra if (no_samples) 204649c48a9SPeter Zijlstra attr->sample_freq = 0; 205649c48a9SPeter Zijlstra 206649c48a9SPeter Zijlstra if (inherit_stat) 207649c48a9SPeter Zijlstra attr->inherit_stat = 1; 208649c48a9SPeter Zijlstra 2093af9e859SEric B Munson if (sample_address) { 2104bba828dSAnton Blanchard attr->sample_type |= PERF_SAMPLE_ADDR; 2113af9e859SEric B Munson attr->mmap_data = track; 2123af9e859SEric B Munson } 2134bba828dSAnton Blanchard 2143efa1cc9SIngo Molnar if (call_graph) 2153efa1cc9SIngo Molnar attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 2163efa1cc9SIngo Molnar 217f60f3593SArun Sharma if (system_wide) 218f60f3593SArun Sharma attr->sample_type |= PERF_SAMPLE_CPU; 219f60f3593SArun Sharma 220a43d3f08SArnaldo Carvalho de Melo if (sample_id_all_avail && 221a43d3f08SArnaldo Carvalho de Melo (sample_time || system_wide || !no_inherit || cpu_list)) 2229c90a61cSArnaldo Carvalho de Melo attr->sample_type |= PERF_SAMPLE_TIME; 2239c90a61cSArnaldo Carvalho de Melo 224cd6feeeaSIngo Molnar if (raw_samples) { 2256ddf259dSIngo Molnar attr->sample_type |= PERF_SAMPLE_TIME; 226daac07b2SFrederic Weisbecker attr->sample_type |= PERF_SAMPLE_RAW; 227cd6feeeaSIngo Molnar attr->sample_type |= PERF_SAMPLE_CPU; 228cd6feeeaSIngo Molnar } 229f413cdb8SFrederic Weisbecker 230acac03faSKirill Smelkov if (nodelay) { 231acac03faSKirill Smelkov attr->watermark = 0; 232acac03faSKirill Smelkov attr->wakeup_events = 1; 233acac03faSKirill Smelkov } 234acac03faSKirill Smelkov 23586470930SIngo Molnar attr->mmap = track; 23686470930SIngo Molnar attr->comm = track; 237dd7927f4SArnaldo Carvalho de Melo 2382e6cdf99SStephane Eranian if (target_pid == -1 && target_tid == -1 && !system_wide) { 2394502d77cSPeter Zijlstra attr->disabled = 1; 240bedbfdeaSEric B Munson attr->enable_on_exec = 1; 24146be604bSZhang, Yanmin } 242dd7927f4SArnaldo Carvalho de Melo } 243dd7927f4SArnaldo Carvalho de Melo 244a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 245a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 246a91e5431SArnaldo Carvalho de Melo { 247a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 248a91e5431SArnaldo Carvalho de Melo 249a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 250a91e5431SArnaldo Carvalho de Melo return false; 251a91e5431SArnaldo Carvalho de Melo 252a91e5431SArnaldo Carvalho de Melo pair = list_entry(other->entries.next, struct perf_evsel, node); 253a91e5431SArnaldo Carvalho de Melo 254a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 255a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 256a91e5431SArnaldo Carvalho de Melo return false; 257a91e5431SArnaldo Carvalho de Melo pair = list_entry(pair->node.next, struct perf_evsel, node); 258a91e5431SArnaldo Carvalho de Melo } 259a91e5431SArnaldo Carvalho de Melo 260a91e5431SArnaldo Carvalho de Melo return true; 261a91e5431SArnaldo Carvalho de Melo } 262a91e5431SArnaldo Carvalho de Melo 263dd7927f4SArnaldo Carvalho de Melo static void open_counters(struct perf_evlist *evlist) 264dd7927f4SArnaldo Carvalho de Melo { 265dd7927f4SArnaldo Carvalho de Melo struct perf_evsel *pos; 266dd7927f4SArnaldo Carvalho de Melo 2675d2cd909SArnaldo Carvalho de Melo if (evlist->cpus->map[0] < 0) 2685d2cd909SArnaldo Carvalho de Melo no_inherit = true; 2695d2cd909SArnaldo Carvalho de Melo 270dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 271dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 272dd7927f4SArnaldo Carvalho de Melo /* 273dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 274dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 275dd7927f4SArnaldo Carvalho de Melo * 276dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 277dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 278dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 279dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 280dd7927f4SArnaldo Carvalho de Melo * 281dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 282dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 283dd7927f4SArnaldo Carvalho de Melo */ 284dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 285dd7927f4SArnaldo Carvalho de Melo 286dd7927f4SArnaldo Carvalho de Melo config_attr(pos, evlist); 2879c90a61cSArnaldo Carvalho de Melo retry_sample_id: 2889c90a61cSArnaldo Carvalho de Melo attr->sample_id_all = sample_id_all_avail ? 1 : 0; 2893da297a6SIngo Molnar try_again: 2905d2cd909SArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) { 29186470930SIngo Molnar int err = errno; 29286470930SIngo Molnar 293c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 294c286c419SArnaldo Carvalho de Melo ui__warning_paranoid(); 295c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 296c286c419SArnaldo Carvalho de Melo } else if (err == ENODEV && cpu_list) { 297d6d901c2SZhang, Yanmin die("No such device - did you specify" 298d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 2999c90a61cSArnaldo Carvalho de Melo } else if (err == EINVAL && sample_id_all_avail) { 3009c90a61cSArnaldo Carvalho de Melo /* 3019c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 3029c90a61cSArnaldo Carvalho de Melo */ 3039c90a61cSArnaldo Carvalho de Melo sample_id_all_avail = false; 304a43d3f08SArnaldo Carvalho de Melo if (!sample_time && !raw_samples && !time_needed) 305eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 306eac23d1cSIan Munsie 3079c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 308d6d901c2SZhang, Yanmin } 3093da297a6SIngo Molnar 3103da297a6SIngo Molnar /* 3113da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 3123da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 3133da297a6SIngo Molnar * is always available even if no PMU support: 3143da297a6SIngo Molnar */ 3153da297a6SIngo Molnar if (attr->type == PERF_TYPE_HARDWARE 316f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 3173da297a6SIngo Molnar 3183da297a6SIngo Molnar if (verbose) 319ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 320ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 3213da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 322f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 3233da297a6SIngo Molnar goto try_again; 3243da297a6SIngo Molnar } 325ca6a4258SDavid Ahern 326ca6a4258SDavid Ahern if (err == ENOENT) { 327ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 328ca6a4258SDavid Ahern event_name(pos)); 329ca6a4258SDavid Ahern exit(EXIT_FAILURE); 330ca6a4258SDavid Ahern } 331ca6a4258SDavid Ahern 33230c806a0SIngo Molnar printf("\n"); 333d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 334dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 335bfd45118SSimon Kaempflein 336bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 337bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 338d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 339d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 340d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 341d6d901c2SZhang, Yanmin " force-enable it.\n"); 342bfd45118SSimon Kaempflein #endif 343bfd45118SSimon Kaempflein 344cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 3457c6a1c65SPeter Zijlstra } 3467c6a1c65SPeter Zijlstra } 3477c6a1c65SPeter Zijlstra 3480a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 3490a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 3500a102479SFrederic Weisbecker strerror(errno)); 3510a102479SFrederic Weisbecker exit(-1); 3520a102479SFrederic Weisbecker } 3530a102479SFrederic Weisbecker 3547e2ed097SArnaldo Carvalho de Melo if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) 3550a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 3560a27d7f9SArnaldo Carvalho de Melo 357a91e5431SArnaldo Carvalho de Melo if (file_new) 358a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 359a91e5431SArnaldo Carvalho de Melo else { 360a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 361a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 362a91e5431SArnaldo Carvalho de Melo exit(-1); 363dd7927f4SArnaldo Carvalho de Melo } 36486470930SIngo Molnar } 36586470930SIngo Molnar 366a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 367a91e5431SArnaldo Carvalho de Melo } 368a91e5431SArnaldo Carvalho de Melo 3696122e4e4SArnaldo Carvalho de Melo static int process_buildids(void) 3706122e4e4SArnaldo Carvalho de Melo { 3716122e4e4SArnaldo Carvalho de Melo u64 size = lseek(output, 0, SEEK_CUR); 3726122e4e4SArnaldo Carvalho de Melo 3739f591fd7SArnaldo Carvalho de Melo if (size == 0) 3749f591fd7SArnaldo Carvalho de Melo return 0; 3759f591fd7SArnaldo Carvalho de Melo 3766122e4e4SArnaldo Carvalho de Melo session->fd = output; 3776122e4e4SArnaldo Carvalho de Melo return __perf_session__process_events(session, post_processing_offset, 3786122e4e4SArnaldo Carvalho de Melo size - post_processing_offset, 3796122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3806122e4e4SArnaldo Carvalho de Melo } 3816122e4e4SArnaldo Carvalho de Melo 382f5970550SPeter Zijlstra static void atexit_header(void) 383f5970550SPeter Zijlstra { 384c7929e47STom Zanussi if (!pipe_output) { 38594c744b6SArnaldo Carvalho de Melo session->header.data_size += bytes_written; 386f5970550SPeter Zijlstra 387baa2f6ceSArnaldo Carvalho de Melo if (!no_buildid) 3886122e4e4SArnaldo Carvalho de Melo process_buildids(); 389a91e5431SArnaldo Carvalho de Melo perf_session__write_header(session, evsel_list, output, true); 39039d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 391361c99a6SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 392d65a458bSArnaldo Carvalho de Melo symbol__exit(); 393c7929e47STom Zanussi } 394f5970550SPeter Zijlstra } 395f5970550SPeter Zijlstra 3968115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 397a1645ce1SZhang, Yanmin { 398a1645ce1SZhang, Yanmin int err; 39923346f21SArnaldo Carvalho de Melo struct perf_session *psession = data; 400a1645ce1SZhang, Yanmin 40123346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 402a1645ce1SZhang, Yanmin return; 403a1645ce1SZhang, Yanmin 404a1645ce1SZhang, Yanmin /* 405a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 406a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 407a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 408a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 409a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 410a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 411a1645ce1SZhang, Yanmin */ 4128115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_modules(process_synthesized_event, 41323346f21SArnaldo Carvalho de Melo psession, machine); 414a1645ce1SZhang, Yanmin if (err < 0) 415a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 41623346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 417a1645ce1SZhang, Yanmin 418a1645ce1SZhang, Yanmin /* 419a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 420a1645ce1SZhang, Yanmin * have no _text sometimes. 421a1645ce1SZhang, Yanmin */ 4228115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 42323346f21SArnaldo Carvalho de Melo psession, machine, "_text"); 424a1645ce1SZhang, Yanmin if (err < 0) 4258115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 4268115d60cSArnaldo Carvalho de Melo psession, machine, 4278115d60cSArnaldo Carvalho de Melo "_stext"); 428a1645ce1SZhang, Yanmin if (err < 0) 429a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 43023346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 431a1645ce1SZhang, Yanmin } 432a1645ce1SZhang, Yanmin 43398402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 43498402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 43598402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 43698402807SFrederic Weisbecker }; 43798402807SFrederic Weisbecker 43898402807SFrederic Weisbecker static void mmap_read_all(void) 43998402807SFrederic Weisbecker { 4400e2e63ddSPeter Zijlstra int i; 44198402807SFrederic Weisbecker 442aece948fSArnaldo Carvalho de Melo for (i = 0; i < evsel_list->nr_mmaps; i++) { 4430a27d7f9SArnaldo Carvalho de Melo if (evsel_list->mmap[i].base) 4440a27d7f9SArnaldo Carvalho de Melo mmap_read(&evsel_list->mmap[i]); 44598402807SFrederic Weisbecker } 44698402807SFrederic Weisbecker 44798402807SFrederic Weisbecker if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 44898402807SFrederic Weisbecker write_output(&finished_round_event, sizeof(finished_round_event)); 44998402807SFrederic Weisbecker } 45098402807SFrederic Weisbecker 451d4db3f16SArnaldo Carvalho de Melo static int __cmd_record(int argc, const char **argv) 45286470930SIngo Molnar { 45386470930SIngo Molnar struct stat st; 45486470930SIngo Molnar int flags; 4554dc0a04bSArnaldo Carvalho de Melo int err; 4568b412664SPeter Zijlstra unsigned long waking = 0; 457856e9660SPeter Zijlstra int child_ready_pipe[2], go_pipe[2]; 45846be604bSZhang, Yanmin const bool forks = argc > 0; 459856e9660SPeter Zijlstra char buf; 46023346f21SArnaldo Carvalho de Melo struct machine *machine; 46186470930SIngo Molnar 46233e49ea7SAndi Kleen progname = argv[0]; 46333e49ea7SAndi Kleen 46486470930SIngo Molnar page_size = sysconf(_SC_PAGE_SIZE); 46586470930SIngo Molnar 466f5970550SPeter Zijlstra atexit(sig_atexit); 467f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 468f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 46918483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 470f5970550SPeter Zijlstra 471d4db3f16SArnaldo Carvalho de Melo if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 472856e9660SPeter Zijlstra perror("failed to create pipes"); 473856e9660SPeter Zijlstra exit(-1); 474856e9660SPeter Zijlstra } 475856e9660SPeter Zijlstra 476d7065adbSFranck Bui-Huu if (!output_name) { 477d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 478d7065adbSFranck Bui-Huu pipe_output = 1; 479d7065adbSFranck Bui-Huu else 480d7065adbSFranck Bui-Huu output_name = "perf.data"; 481d7065adbSFranck Bui-Huu } 482d7065adbSFranck Bui-Huu if (output_name) { 483529870e3STom Zanussi if (!strcmp(output_name, "-")) 484529870e3STom Zanussi pipe_output = 1; 485529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 4867865e817SFrederic Weisbecker if (write_mode == WRITE_FORCE) { 487b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 488b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 489b38d3464SArnaldo Carvalho de Melo output_name); 490b38d3464SArnaldo Carvalho de Melo unlink(oldname); 491b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 492b38d3464SArnaldo Carvalho de Melo } 4937865e817SFrederic Weisbecker } else if (write_mode == WRITE_APPEND) { 4947865e817SFrederic Weisbecker write_mode = WRITE_FORCE; 495266e0e21SPierre Habouzit } 496d7065adbSFranck Bui-Huu } 49786470930SIngo Molnar 498f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 4997865e817SFrederic Weisbecker if (write_mode == WRITE_APPEND) 500f5970550SPeter Zijlstra file_new = 0; 50186470930SIngo Molnar else 50286470930SIngo Molnar flags |= O_TRUNC; 50386470930SIngo Molnar 504529870e3STom Zanussi if (pipe_output) 505529870e3STom Zanussi output = STDOUT_FILENO; 506529870e3STom Zanussi else 50786470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 50886470930SIngo Molnar if (output < 0) { 50986470930SIngo Molnar perror("failed to create output file"); 51086470930SIngo Molnar exit(-1); 51186470930SIngo Molnar } 51286470930SIngo Molnar 5137865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 51421ef97f0SIan Munsie write_mode == WRITE_FORCE, false, NULL); 51594c744b6SArnaldo Carvalho de Melo if (session == NULL) { 516a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 517a9a70bbcSArnaldo Carvalho de Melo return -1; 518a9a70bbcSArnaldo Carvalho de Melo } 519a9a70bbcSArnaldo Carvalho de Melo 520baa2f6ceSArnaldo Carvalho de Melo if (!no_buildid) 521baa2f6ceSArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_BUILD_ID); 522baa2f6ceSArnaldo Carvalho de Melo 5234dc0a04bSArnaldo Carvalho de Melo if (!file_new) { 524a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 5254dc0a04bSArnaldo Carvalho de Melo if (err < 0) 52639d17dacSArnaldo Carvalho de Melo goto out_delete_session; 5274dc0a04bSArnaldo Carvalho de Melo } 5284dc0a04bSArnaldo Carvalho de Melo 529361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) 53094c744b6SArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 53103456a15SFrederic Weisbecker 532*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_HOSTNAME); 533*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_OSRELEASE); 534*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_ARCH); 535*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUDESC); 536*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NRCPUS); 537*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_EVENT_DESC); 538*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CMDLINE); 539*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_VERSION); 540*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); 541*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_TOTAL_MEM); 542*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 543*fbe96f29SStephane Eranian perf_header__set_feat(&session->header, HEADER_CPUID); 544*fbe96f29SStephane Eranian 545800cd25cSFrederic Weisbecker /* 512 kiB: default amount of unprivileged mlocked memory */ 546800cd25cSFrederic Weisbecker if (mmap_pages == UINT_MAX) 547800cd25cSFrederic Weisbecker mmap_pages = (512 * 1024) / page_size; 548800cd25cSFrederic Weisbecker 549d4db3f16SArnaldo Carvalho de Melo if (forks) { 55046be604bSZhang, Yanmin child_pid = fork(); 5512fb750e8SBorislav Petkov if (child_pid < 0) { 552856e9660SPeter Zijlstra perror("failed to fork"); 553856e9660SPeter Zijlstra exit(-1); 554856e9660SPeter Zijlstra } 5557c6a1c65SPeter Zijlstra 55646be604bSZhang, Yanmin if (!child_pid) { 557529870e3STom Zanussi if (pipe_output) 558529870e3STom Zanussi dup2(2, 1); 559856e9660SPeter Zijlstra close(child_ready_pipe[0]); 560856e9660SPeter Zijlstra close(go_pipe[1]); 561856e9660SPeter Zijlstra fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 562856e9660SPeter Zijlstra 563856e9660SPeter Zijlstra /* 564856e9660SPeter Zijlstra * Do a dummy execvp to get the PLT entry resolved, 565856e9660SPeter Zijlstra * so we avoid the resolver overhead on the real 566856e9660SPeter Zijlstra * execvp call. 567856e9660SPeter Zijlstra */ 568856e9660SPeter Zijlstra execvp("", (char **)argv); 569856e9660SPeter Zijlstra 570856e9660SPeter Zijlstra /* 571856e9660SPeter Zijlstra * Tell the parent we're ready to go 572856e9660SPeter Zijlstra */ 573856e9660SPeter Zijlstra close(child_ready_pipe[1]); 574856e9660SPeter Zijlstra 575856e9660SPeter Zijlstra /* 576856e9660SPeter Zijlstra * Wait until the parent tells us to go. 577856e9660SPeter Zijlstra */ 578856e9660SPeter Zijlstra if (read(go_pipe[0], &buf, 1) == -1) 579856e9660SPeter Zijlstra perror("unable to read pipe"); 580856e9660SPeter Zijlstra 581856e9660SPeter Zijlstra execvp(argv[0], (char **)argv); 582856e9660SPeter Zijlstra 583856e9660SPeter Zijlstra perror(argv[0]); 58418483b81SArnaldo Carvalho de Melo kill(getppid(), SIGUSR1); 585856e9660SPeter Zijlstra exit(-1); 586856e9660SPeter Zijlstra } 587856e9660SPeter Zijlstra 588d6d901c2SZhang, Yanmin if (!system_wide && target_tid == -1 && target_pid == -1) 5897e2ed097SArnaldo Carvalho de Melo evsel_list->threads->map[0] = child_pid; 590d6d901c2SZhang, Yanmin 591856e9660SPeter Zijlstra close(child_ready_pipe[1]); 592856e9660SPeter Zijlstra close(go_pipe[0]); 593856e9660SPeter Zijlstra /* 594856e9660SPeter Zijlstra * wait for child to settle 595856e9660SPeter Zijlstra */ 596856e9660SPeter Zijlstra if (read(child_ready_pipe[0], &buf, 1) == -1) { 597856e9660SPeter Zijlstra perror("unable to read pipe"); 598856e9660SPeter Zijlstra exit(-1); 599856e9660SPeter Zijlstra } 600856e9660SPeter Zijlstra close(child_ready_pipe[0]); 601856e9660SPeter Zijlstra } 602856e9660SPeter Zijlstra 603dd7927f4SArnaldo Carvalho de Melo open_counters(evsel_list); 60486470930SIngo Molnar 605712a4b60SArnaldo Carvalho de Melo /* 606712a4b60SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at atexit_header() 607712a4b60SArnaldo Carvalho de Melo */ 608712a4b60SArnaldo Carvalho de Melo atexit(atexit_header); 609712a4b60SArnaldo Carvalho de Melo 610529870e3STom Zanussi if (pipe_output) { 611529870e3STom Zanussi err = perf_header__write_pipe(output); 612529870e3STom Zanussi if (err < 0) 613529870e3STom Zanussi return err; 614529870e3STom Zanussi } else if (file_new) { 615a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 616361c99a6SArnaldo Carvalho de Melo output, false); 617d5eed904SArnaldo Carvalho de Melo if (err < 0) 618d5eed904SArnaldo Carvalho de Melo return err; 619d5eed904SArnaldo Carvalho de Melo } 6207c6a1c65SPeter Zijlstra 6216122e4e4SArnaldo Carvalho de Melo post_processing_offset = lseek(output, 0, SEEK_CUR); 6226122e4e4SArnaldo Carvalho de Melo 6232c46dbb5STom Zanussi if (pipe_output) { 624a91e5431SArnaldo Carvalho de Melo err = perf_session__synthesize_attrs(session, 625a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 6262c46dbb5STom Zanussi if (err < 0) { 6272c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 6282c46dbb5STom Zanussi return err; 6292c46dbb5STom Zanussi } 630cd19a035STom Zanussi 6318115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(process_synthesized_event, 632cd19a035STom Zanussi session); 633cd19a035STom Zanussi if (err < 0) { 634cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 635cd19a035STom Zanussi return err; 636cd19a035STom Zanussi } 6379215545eSTom Zanussi 638361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 63963e0c771STom Zanussi /* 64063e0c771STom Zanussi * FIXME err <= 0 here actually means that 64163e0c771STom Zanussi * there were no tracepoints so its not really 64263e0c771STom Zanussi * an error, just that we don't need to 64363e0c771STom Zanussi * synthesize anything. We really have to 64463e0c771STom Zanussi * return this more properly and also 64563e0c771STom Zanussi * propagate errors that now are calling die() 64663e0c771STom Zanussi */ 6478115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(output, evsel_list, 6489215545eSTom Zanussi process_synthesized_event, 6499215545eSTom Zanussi session); 65063e0c771STom Zanussi if (err <= 0) { 65163e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 65263e0c771STom Zanussi return err; 65363e0c771STom Zanussi } 6549215545eSTom Zanussi advance_output(err); 6552c46dbb5STom Zanussi } 65663e0c771STom Zanussi } 6572c46dbb5STom Zanussi 65823346f21SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 65923346f21SArnaldo Carvalho de Melo if (!machine) { 660a1645ce1SZhang, Yanmin pr_err("Couldn't find native kernel information.\n"); 661a1645ce1SZhang, Yanmin return -1; 662a1645ce1SZhang, Yanmin } 663a1645ce1SZhang, Yanmin 6648115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 66523346f21SArnaldo Carvalho de Melo session, machine, "_text"); 66670162138SArnaldo Carvalho de Melo if (err < 0) 6678115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 66823346f21SArnaldo Carvalho de Melo session, machine, "_stext"); 669c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 670c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 671c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 672c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 67356b03f3cSArnaldo Carvalho de Melo 6748115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_modules(process_synthesized_event, 67523346f21SArnaldo Carvalho de Melo session, machine); 676c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 677c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 678c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 679c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 680c1a3a4b9SArnaldo Carvalho de Melo 681a1645ce1SZhang, Yanmin if (perf_guest) 6828115d60cSArnaldo Carvalho de Melo perf_session__process_machines(session, 6838115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 684b7cece76SArnaldo Carvalho de Melo 685cf103a14SStephane Eranian if (!system_wide) 6867c940c18SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(evsel_list->threads, 6878115d60cSArnaldo Carvalho de Melo process_synthesized_event, 688d8f66248SArnaldo Carvalho de Melo session); 689234fbbf5SArnaldo Carvalho de Melo else 6908115d60cSArnaldo Carvalho de Melo perf_event__synthesize_threads(process_synthesized_event, 6918115d60cSArnaldo Carvalho de Melo session); 6927c6a1c65SPeter Zijlstra 69386470930SIngo Molnar if (realtime_prio) { 69486470930SIngo Molnar struct sched_param param; 69586470930SIngo Molnar 69686470930SIngo Molnar param.sched_priority = realtime_prio; 69786470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6986beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 69986470930SIngo Molnar exit(-1); 70086470930SIngo Molnar } 70186470930SIngo Molnar } 70286470930SIngo Molnar 703764e16a3SDavid Ahern perf_evlist__enable(evsel_list); 704764e16a3SDavid Ahern 705856e9660SPeter Zijlstra /* 706856e9660SPeter Zijlstra * Let the child rip 707856e9660SPeter Zijlstra */ 708d4db3f16SArnaldo Carvalho de Melo if (forks) 709856e9660SPeter Zijlstra close(go_pipe[1]); 710856e9660SPeter Zijlstra 711649c48a9SPeter Zijlstra for (;;) { 71286470930SIngo Molnar int hits = samples; 71386470930SIngo Molnar 71498402807SFrederic Weisbecker mmap_read_all(); 71586470930SIngo Molnar 716649c48a9SPeter Zijlstra if (hits == samples) { 717649c48a9SPeter Zijlstra if (done) 718649c48a9SPeter Zijlstra break; 7195c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 7208b412664SPeter Zijlstra waking++; 7218b412664SPeter Zijlstra } 7228b412664SPeter Zijlstra 7234152ab37SArnaldo Carvalho de Melo if (done) 7244152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 7258b412664SPeter Zijlstra } 7268b412664SPeter Zijlstra 72718483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 728b44308f5SArnaldo Carvalho de Melo return 0; 729b44308f5SArnaldo Carvalho de Melo 7308b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 73186470930SIngo Molnar 73286470930SIngo Molnar /* 73386470930SIngo Molnar * Approximate RIP event size: 24 bytes. 73486470930SIngo Molnar */ 73586470930SIngo Molnar fprintf(stderr, 7369486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 73786470930SIngo Molnar (double)bytes_written / 1024.0 / 1024.0, 73886470930SIngo Molnar output_name, 73986470930SIngo Molnar bytes_written / 24); 74086470930SIngo Molnar 74186470930SIngo Molnar return 0; 74239d17dacSArnaldo Carvalho de Melo 74339d17dacSArnaldo Carvalho de Melo out_delete_session: 74439d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 74539d17dacSArnaldo Carvalho de Melo return err; 74686470930SIngo Molnar } 74786470930SIngo Molnar 74886470930SIngo Molnar static const char * const record_usage[] = { 74986470930SIngo Molnar "perf record [<options>] [<command>]", 75086470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 75186470930SIngo Molnar NULL 75286470930SIngo Molnar }; 75386470930SIngo Molnar 7547865e817SFrederic Weisbecker static bool force, append_file; 7557865e817SFrederic Weisbecker 756bca647aaSTom Zanussi const struct option record_options[] = { 757361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 75886470930SIngo Molnar "event selector. use 'perf list' to list available events", 759f120f9d5SJiri Olsa parse_events_option), 760361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &evsel_list, "filter", 761c171b552SLi Zefan "event filter", parse_filter), 76286470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 763d6d901c2SZhang, Yanmin "record events on existing process id"), 764d6d901c2SZhang, Yanmin OPT_INTEGER('t', "tid", &target_tid, 765d6d901c2SZhang, Yanmin "record events on existing thread id"), 76686470930SIngo Molnar OPT_INTEGER('r', "realtime", &realtime_prio, 76786470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 768acac03faSKirill Smelkov OPT_BOOLEAN('D', "no-delay", &nodelay, 769acac03faSKirill Smelkov "collect data without buffering"), 770daac07b2SFrederic Weisbecker OPT_BOOLEAN('R', "raw-samples", &raw_samples, 771daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 77286470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 77386470930SIngo Molnar "system-wide collection from all CPUs"), 77486470930SIngo Molnar OPT_BOOLEAN('A', "append", &append_file, 77586470930SIngo Molnar "append to the output file to do incremental profiling"), 776c45c6ea2SStephane Eranian OPT_STRING('C', "cpu", &cpu_list, "cpu", 777c45c6ea2SStephane Eranian "list of cpus to monitor"), 77886470930SIngo Molnar OPT_BOOLEAN('f', "force", &force, 7797865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 7803de29cabSStephane Eranian OPT_U64('c', "count", &user_interval, "event period to sample"), 78186470930SIngo Molnar OPT_STRING('o', "output", &output_name, "file", 78286470930SIngo Molnar "output file name"), 7832e6cdf99SStephane Eranian OPT_BOOLEAN('i', "no-inherit", &no_inherit, 7842e6cdf99SStephane Eranian "child tasks do not inherit counters"), 7851967936dSArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 7861967936dSArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 78743bece79SLin Ming OPT_BOOLEAN(0, "group", &group, 78843bece79SLin Ming "put the counters into a counter group"), 7893efa1cc9SIngo Molnar OPT_BOOLEAN('g', "call-graph", &call_graph, 7903efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 791c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7923da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 793b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 794649c48a9SPeter Zijlstra OPT_BOOLEAN('s', "stat", &inherit_stat, 795649c48a9SPeter Zijlstra "per thread counts"), 7964bba828dSAnton Blanchard OPT_BOOLEAN('d', "data", &sample_address, 7974bba828dSAnton Blanchard "Sample addresses"), 7989c90a61cSArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"), 799649c48a9SPeter Zijlstra OPT_BOOLEAN('n', "no-samples", &no_samples, 800649c48a9SPeter Zijlstra "don't sample"), 801baa2f6ceSArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 802a1ac1d3cSStephane Eranian "do not update the buildid cache"), 803baa2f6ceSArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &no_buildid, 804baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 805023695d9SStephane Eranian OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 806023695d9SStephane Eranian "monitor event in cgroup name only", 807023695d9SStephane Eranian parse_cgroups), 80886470930SIngo Molnar OPT_END() 80986470930SIngo Molnar }; 81086470930SIngo Molnar 811f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 81286470930SIngo Molnar { 81369aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 81469aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 81586470930SIngo Molnar 816*fbe96f29SStephane Eranian perf_header__set_cmdline(argc, argv); 817*fbe96f29SStephane Eranian 8187e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 819361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 820361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 821361c99a6SArnaldo Carvalho de Melo 822bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 823a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 824d6d901c2SZhang, Yanmin if (!argc && target_pid == -1 && target_tid == -1 && 825c45c6ea2SStephane Eranian !system_wide && !cpu_list) 826bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 82786470930SIngo Molnar 8287865e817SFrederic Weisbecker if (force && append_file) { 8297865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 8307865e817SFrederic Weisbecker " You need to choose between -f and -A"); 831bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 8327865e817SFrederic Weisbecker } else if (append_file) { 8337865e817SFrederic Weisbecker write_mode = WRITE_APPEND; 8347865e817SFrederic Weisbecker } else { 8357865e817SFrederic Weisbecker write_mode = WRITE_FORCE; 8367865e817SFrederic Weisbecker } 8377865e817SFrederic Weisbecker 838023695d9SStephane Eranian if (nr_cgroups && !system_wide) { 839023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 840023695d9SStephane Eranian " system-wide mode\n"); 841023695d9SStephane Eranian usage_with_options(record_usage, record_options); 842023695d9SStephane Eranian } 843023695d9SStephane Eranian 844655000e7SArnaldo Carvalho de Melo symbol__init(); 845baa2f6ceSArnaldo Carvalho de Melo 846ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 847646aaea6SArnaldo Carvalho de Melo pr_warning( 848646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 849ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 850646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 851646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 852646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 853646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 854646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 855ec80fde7SArnaldo Carvalho de Melo 856baa2f6ceSArnaldo Carvalho de Melo if (no_buildid_cache || no_buildid) 857a1ac1d3cSStephane Eranian disable_buildid_cache(); 858655000e7SArnaldo Carvalho de Melo 859361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 860361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 86169aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 86269aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 863bbd36e5eSPeter Zijlstra } 86486470930SIngo Molnar 8655c98d466SArnaldo Carvalho de Melo if (target_pid != -1) 866d6d901c2SZhang, Yanmin target_tid = target_pid; 867d6d901c2SZhang, Yanmin 8687e2ed097SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, target_pid, 8697e2ed097SArnaldo Carvalho de Melo target_tid, cpu_list) < 0) 870dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 87169aad6f1SArnaldo Carvalho de Melo 872361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 8737e2ed097SArnaldo Carvalho de Melo if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, 8747e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr) < 0) 87569aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 876ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 877ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 878d6d901c2SZhang, Yanmin } 8795c581041SArnaldo Carvalho de Melo 8807e2ed097SArnaldo Carvalho de Melo if (perf_evlist__alloc_pollfd(evsel_list) < 0) 88139d17dacSArnaldo Carvalho de Melo goto out_free_fd; 882d6d901c2SZhang, Yanmin 8833de29cabSStephane Eranian if (user_interval != ULLONG_MAX) 884f9212819SFrederic Weisbecker default_interval = user_interval; 885f9212819SFrederic Weisbecker if (user_freq != UINT_MAX) 886f9212819SFrederic Weisbecker freq = user_freq; 887f9212819SFrederic Weisbecker 8887e4ff9e3SMike Galbraith /* 8897e4ff9e3SMike Galbraith * User specified count overrides default frequency. 8907e4ff9e3SMike Galbraith */ 8917e4ff9e3SMike Galbraith if (default_interval) 8927e4ff9e3SMike Galbraith freq = 0; 8937e4ff9e3SMike Galbraith else if (freq) { 8947e4ff9e3SMike Galbraith default_interval = freq; 8957e4ff9e3SMike Galbraith } else { 8967e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 89739d17dacSArnaldo Carvalho de Melo err = -EINVAL; 8985c581041SArnaldo Carvalho de Melo goto out_free_fd; 8997e4ff9e3SMike Galbraith } 9007e4ff9e3SMike Galbraith 90139d17dacSArnaldo Carvalho de Melo err = __cmd_record(argc, argv); 90239d17dacSArnaldo Carvalho de Melo out_free_fd: 9037e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 904d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 905d65a458bSArnaldo Carvalho de Melo symbol__exit(); 90639d17dacSArnaldo Carvalho de Melo return err; 90786470930SIngo Molnar } 908