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; 4886470930SIngo Molnar static int group = 0; 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; 76f5970550SPeter Zijlstra 779215545eSTom Zanussi static void advance_output(size_t size) 789215545eSTom Zanussi { 799215545eSTom Zanussi bytes_written += size; 809215545eSTom Zanussi } 819215545eSTom Zanussi 82f5970550SPeter Zijlstra static void write_output(void *buf, size_t size) 83f5970550SPeter Zijlstra { 84f5970550SPeter Zijlstra while (size) { 85f5970550SPeter Zijlstra int ret = write(output, buf, size); 86f5970550SPeter Zijlstra 87f5970550SPeter Zijlstra if (ret < 0) 88f5970550SPeter Zijlstra die("failed to write"); 89f5970550SPeter Zijlstra 90f5970550SPeter Zijlstra size -= ret; 91f5970550SPeter Zijlstra buf += ret; 92f5970550SPeter Zijlstra 93f5970550SPeter Zijlstra bytes_written += ret; 94f5970550SPeter Zijlstra } 95f5970550SPeter Zijlstra } 96f5970550SPeter Zijlstra 978115d60cSArnaldo Carvalho de Melo static int process_synthesized_event(union perf_event *event, 988d50e5b4SArnaldo Carvalho de Melo struct perf_sample *sample __used, 99d8f66248SArnaldo Carvalho de Melo struct perf_session *self __used) 100234fbbf5SArnaldo Carvalho de Melo { 1016122e4e4SArnaldo Carvalho de Melo write_output(event, event->header.size); 102234fbbf5SArnaldo Carvalho de Melo return 0; 103234fbbf5SArnaldo Carvalho de Melo } 104234fbbf5SArnaldo Carvalho de Melo 105744bd8aaSArnaldo Carvalho de Melo static void mmap_read(struct perf_mmap *md) 10686470930SIngo Molnar { 107744bd8aaSArnaldo Carvalho de Melo unsigned int head = perf_mmap__read_head(md); 10886470930SIngo Molnar unsigned int old = md->prev; 10986470930SIngo Molnar unsigned char *data = md->base + page_size; 11086470930SIngo Molnar unsigned long size; 11186470930SIngo Molnar void *buf; 11286470930SIngo Molnar 113dc82009aSArnaldo Carvalho de Melo if (old == head) 114dc82009aSArnaldo Carvalho de Melo return; 11586470930SIngo Molnar 11686470930SIngo Molnar samples++; 11786470930SIngo Molnar 11886470930SIngo Molnar size = head - old; 11986470930SIngo Molnar 12086470930SIngo Molnar if ((old & md->mask) + size != (head & md->mask)) { 12186470930SIngo Molnar buf = &data[old & md->mask]; 12286470930SIngo Molnar size = md->mask + 1 - (old & md->mask); 12386470930SIngo Molnar old += size; 12486470930SIngo Molnar 1256122e4e4SArnaldo Carvalho de Melo write_output(buf, size); 12686470930SIngo Molnar } 12786470930SIngo Molnar 12886470930SIngo Molnar buf = &data[old & md->mask]; 12986470930SIngo Molnar size = head - old; 13086470930SIngo Molnar old += size; 13186470930SIngo Molnar 1326122e4e4SArnaldo Carvalho de Melo write_output(buf, size); 13386470930SIngo Molnar 13486470930SIngo Molnar md->prev = old; 135115d2d89SArnaldo Carvalho de Melo perf_mmap__write_tail(md, old); 13686470930SIngo Molnar } 13786470930SIngo Molnar 13886470930SIngo Molnar static volatile int done = 0; 139f7b7c26eSPeter Zijlstra static volatile int signr = -1; 14086470930SIngo Molnar 14186470930SIngo Molnar static void sig_handler(int sig) 14286470930SIngo Molnar { 14386470930SIngo Molnar done = 1; 144f7b7c26eSPeter Zijlstra signr = sig; 145f7b7c26eSPeter Zijlstra } 146f7b7c26eSPeter Zijlstra 147f7b7c26eSPeter Zijlstra static void sig_atexit(void) 148f7b7c26eSPeter Zijlstra { 1495ffc8881SIan Munsie if (child_pid > 0) 150933da83aSChris Wilson kill(child_pid, SIGTERM); 151933da83aSChris Wilson 15218483b81SArnaldo Carvalho de Melo if (signr == -1 || signr == SIGUSR1) 153f7b7c26eSPeter Zijlstra return; 154f7b7c26eSPeter Zijlstra 155f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 156f7b7c26eSPeter Zijlstra kill(getpid(), signr); 15786470930SIngo Molnar } 15886470930SIngo Molnar 159dd7927f4SArnaldo Carvalho de Melo static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) 160dd7927f4SArnaldo Carvalho de Melo { 161dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &evsel->attr; 162dd7927f4SArnaldo Carvalho de Melo int track = !evsel->idx; /* only the first counter needs these */ 1637c6a1c65SPeter Zijlstra 1645d2cd909SArnaldo Carvalho de Melo attr->inherit = !no_inherit; 1657c6a1c65SPeter Zijlstra attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 1667c6a1c65SPeter Zijlstra PERF_FORMAT_TOTAL_TIME_RUNNING | 1677c6a1c65SPeter Zijlstra PERF_FORMAT_ID; 16886470930SIngo Molnar 1693a9f131fSFrederic Weisbecker attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1703efa1cc9SIngo Molnar 171361c99a6SArnaldo Carvalho de Melo if (evlist->nr_entries > 1) 1728907fd60SEric B Munson attr->sample_type |= PERF_SAMPLE_ID; 1738907fd60SEric B Munson 174f9212819SFrederic Weisbecker /* 175f9212819SFrederic Weisbecker * We default some events to a 1 default interval. But keep 176f9212819SFrederic Weisbecker * it a weak assumption overridable by the user. 177f9212819SFrederic Weisbecker */ 178f9212819SFrederic Weisbecker if (!attr->sample_period || (user_freq != UINT_MAX && 1793de29cabSStephane Eranian user_interval != ULLONG_MAX)) { 18086470930SIngo Molnar if (freq) { 181ea1900e5SPeter Zijlstra attr->sample_type |= PERF_SAMPLE_PERIOD; 18286470930SIngo Molnar attr->freq = 1; 18386470930SIngo Molnar attr->sample_freq = freq; 184f9212819SFrederic Weisbecker } else { 185f9212819SFrederic Weisbecker attr->sample_period = default_interval; 186f9212819SFrederic Weisbecker } 18786470930SIngo Molnar } 1883efa1cc9SIngo Molnar 189649c48a9SPeter Zijlstra if (no_samples) 190649c48a9SPeter Zijlstra attr->sample_freq = 0; 191649c48a9SPeter Zijlstra 192649c48a9SPeter Zijlstra if (inherit_stat) 193649c48a9SPeter Zijlstra attr->inherit_stat = 1; 194649c48a9SPeter Zijlstra 1953af9e859SEric B Munson if (sample_address) { 1964bba828dSAnton Blanchard attr->sample_type |= PERF_SAMPLE_ADDR; 1973af9e859SEric B Munson attr->mmap_data = track; 1983af9e859SEric B Munson } 1994bba828dSAnton Blanchard 2003efa1cc9SIngo Molnar if (call_graph) 2013efa1cc9SIngo Molnar attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 2023efa1cc9SIngo Molnar 203f60f3593SArun Sharma if (system_wide) 204f60f3593SArun Sharma attr->sample_type |= PERF_SAMPLE_CPU; 205f60f3593SArun Sharma 206a43d3f08SArnaldo Carvalho de Melo if (sample_id_all_avail && 207a43d3f08SArnaldo Carvalho de Melo (sample_time || system_wide || !no_inherit || cpu_list)) 2089c90a61cSArnaldo Carvalho de Melo attr->sample_type |= PERF_SAMPLE_TIME; 2099c90a61cSArnaldo Carvalho de Melo 210cd6feeeaSIngo Molnar if (raw_samples) { 2116ddf259dSIngo Molnar attr->sample_type |= PERF_SAMPLE_TIME; 212daac07b2SFrederic Weisbecker attr->sample_type |= PERF_SAMPLE_RAW; 213cd6feeeaSIngo Molnar attr->sample_type |= PERF_SAMPLE_CPU; 214cd6feeeaSIngo Molnar } 215f413cdb8SFrederic Weisbecker 216acac03faSKirill Smelkov if (nodelay) { 217acac03faSKirill Smelkov attr->watermark = 0; 218acac03faSKirill Smelkov attr->wakeup_events = 1; 219acac03faSKirill Smelkov } 220acac03faSKirill Smelkov 22186470930SIngo Molnar attr->mmap = track; 22286470930SIngo Molnar attr->comm = track; 223dd7927f4SArnaldo Carvalho de Melo 2242e6cdf99SStephane Eranian if (target_pid == -1 && target_tid == -1 && !system_wide) { 2254502d77cSPeter Zijlstra attr->disabled = 1; 226bedbfdeaSEric B Munson attr->enable_on_exec = 1; 22746be604bSZhang, Yanmin } 228dd7927f4SArnaldo Carvalho de Melo } 229dd7927f4SArnaldo Carvalho de Melo 230a91e5431SArnaldo Carvalho de Melo static bool perf_evlist__equal(struct perf_evlist *evlist, 231a91e5431SArnaldo Carvalho de Melo struct perf_evlist *other) 232a91e5431SArnaldo Carvalho de Melo { 233a91e5431SArnaldo Carvalho de Melo struct perf_evsel *pos, *pair; 234a91e5431SArnaldo Carvalho de Melo 235a91e5431SArnaldo Carvalho de Melo if (evlist->nr_entries != other->nr_entries) 236a91e5431SArnaldo Carvalho de Melo return false; 237a91e5431SArnaldo Carvalho de Melo 238a91e5431SArnaldo Carvalho de Melo pair = list_entry(other->entries.next, struct perf_evsel, node); 239a91e5431SArnaldo Carvalho de Melo 240a91e5431SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 241a91e5431SArnaldo Carvalho de Melo if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) 242a91e5431SArnaldo Carvalho de Melo return false; 243a91e5431SArnaldo Carvalho de Melo pair = list_entry(pair->node.next, struct perf_evsel, node); 244a91e5431SArnaldo Carvalho de Melo } 245a91e5431SArnaldo Carvalho de Melo 246a91e5431SArnaldo Carvalho de Melo return true; 247a91e5431SArnaldo Carvalho de Melo } 248a91e5431SArnaldo Carvalho de Melo 249dd7927f4SArnaldo Carvalho de Melo static void open_counters(struct perf_evlist *evlist) 250dd7927f4SArnaldo Carvalho de Melo { 251dd7927f4SArnaldo Carvalho de Melo struct perf_evsel *pos; 252dd7927f4SArnaldo Carvalho de Melo 2535d2cd909SArnaldo Carvalho de Melo if (evlist->cpus->map[0] < 0) 2545d2cd909SArnaldo Carvalho de Melo no_inherit = true; 2555d2cd909SArnaldo Carvalho de Melo 256dd7927f4SArnaldo Carvalho de Melo list_for_each_entry(pos, &evlist->entries, node) { 257dd7927f4SArnaldo Carvalho de Melo struct perf_event_attr *attr = &pos->attr; 258dd7927f4SArnaldo Carvalho de Melo /* 259dd7927f4SArnaldo Carvalho de Melo * Check if parse_single_tracepoint_event has already asked for 260dd7927f4SArnaldo Carvalho de Melo * PERF_SAMPLE_TIME. 261dd7927f4SArnaldo Carvalho de Melo * 262dd7927f4SArnaldo Carvalho de Melo * XXX this is kludgy but short term fix for problems introduced by 263dd7927f4SArnaldo Carvalho de Melo * eac23d1c that broke 'perf script' by having different sample_types 264dd7927f4SArnaldo Carvalho de Melo * when using multiple tracepoint events when we use a perf binary 265dd7927f4SArnaldo Carvalho de Melo * that tries to use sample_id_all on an older kernel. 266dd7927f4SArnaldo Carvalho de Melo * 267dd7927f4SArnaldo Carvalho de Melo * We need to move counter creation to perf_session, support 268dd7927f4SArnaldo Carvalho de Melo * different sample_types, etc. 269dd7927f4SArnaldo Carvalho de Melo */ 270dd7927f4SArnaldo Carvalho de Melo bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 271dd7927f4SArnaldo Carvalho de Melo 272dd7927f4SArnaldo Carvalho de Melo config_attr(pos, evlist); 2739c90a61cSArnaldo Carvalho de Melo retry_sample_id: 2749c90a61cSArnaldo Carvalho de Melo attr->sample_id_all = sample_id_all_avail ? 1 : 0; 2753da297a6SIngo Molnar try_again: 2765d2cd909SArnaldo Carvalho de Melo if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) { 27786470930SIngo Molnar int err = errno; 27886470930SIngo Molnar 279c286c419SArnaldo Carvalho de Melo if (err == EPERM || err == EACCES) { 280c286c419SArnaldo Carvalho de Melo ui__warning_paranoid(); 281c286c419SArnaldo Carvalho de Melo exit(EXIT_FAILURE); 282c286c419SArnaldo Carvalho de Melo } else if (err == ENODEV && cpu_list) { 283d6d901c2SZhang, Yanmin die("No such device - did you specify" 284d6d901c2SZhang, Yanmin " an out-of-range profile CPU?\n"); 2859c90a61cSArnaldo Carvalho de Melo } else if (err == EINVAL && sample_id_all_avail) { 2869c90a61cSArnaldo Carvalho de Melo /* 2879c90a61cSArnaldo Carvalho de Melo * Old kernel, no attr->sample_id_type_all field 2889c90a61cSArnaldo Carvalho de Melo */ 2899c90a61cSArnaldo Carvalho de Melo sample_id_all_avail = false; 290a43d3f08SArnaldo Carvalho de Melo if (!sample_time && !raw_samples && !time_needed) 291eac23d1cSIan Munsie attr->sample_type &= ~PERF_SAMPLE_TIME; 292eac23d1cSIan Munsie 2939c90a61cSArnaldo Carvalho de Melo goto retry_sample_id; 294d6d901c2SZhang, Yanmin } 2953da297a6SIngo Molnar 2963da297a6SIngo Molnar /* 2973da297a6SIngo Molnar * If it's cycles then fall back to hrtimer 2983da297a6SIngo Molnar * based cpu-clock-tick sw counter, which 2993da297a6SIngo Molnar * is always available even if no PMU support: 3003da297a6SIngo Molnar */ 3013da297a6SIngo Molnar if (attr->type == PERF_TYPE_HARDWARE 302f4dbfa8fSPeter Zijlstra && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 3033da297a6SIngo Molnar 3043da297a6SIngo Molnar if (verbose) 305ca6a4258SDavid Ahern ui__warning("The cycles event is not supported, " 306ca6a4258SDavid Ahern "trying to fall back to cpu-clock-ticks\n"); 3073da297a6SIngo Molnar attr->type = PERF_TYPE_SOFTWARE; 308f4dbfa8fSPeter Zijlstra attr->config = PERF_COUNT_SW_CPU_CLOCK; 3093da297a6SIngo Molnar goto try_again; 3103da297a6SIngo Molnar } 311ca6a4258SDavid Ahern 312ca6a4258SDavid Ahern if (err == ENOENT) { 313ca6a4258SDavid Ahern ui__warning("The %s event is not supported.\n", 314ca6a4258SDavid Ahern event_name(pos)); 315ca6a4258SDavid Ahern exit(EXIT_FAILURE); 316ca6a4258SDavid Ahern } 317ca6a4258SDavid Ahern 31830c806a0SIngo Molnar printf("\n"); 319d9cf837eSCorey Ashford error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", 320dd7927f4SArnaldo Carvalho de Melo err, strerror(err)); 321bfd45118SSimon Kaempflein 322bfd45118SSimon Kaempflein #if defined(__i386__) || defined(__x86_64__) 323bfd45118SSimon Kaempflein if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 324d6d901c2SZhang, Yanmin die("No hardware sampling interrupt available." 325d6d901c2SZhang, Yanmin " No APIC? If so then you can boot the kernel" 326d6d901c2SZhang, Yanmin " with the \"lapic\" boot parameter to" 327d6d901c2SZhang, Yanmin " force-enable it.\n"); 328bfd45118SSimon Kaempflein #endif 329bfd45118SSimon Kaempflein 330cdd6c482SIngo Molnar die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 3317c6a1c65SPeter Zijlstra } 3327c6a1c65SPeter Zijlstra } 3337c6a1c65SPeter Zijlstra 3340a102479SFrederic Weisbecker if (perf_evlist__set_filters(evlist)) { 3350a102479SFrederic Weisbecker error("failed to set filter with %d (%s)\n", errno, 3360a102479SFrederic Weisbecker strerror(errno)); 3370a102479SFrederic Weisbecker exit(-1); 3380a102479SFrederic Weisbecker } 3390a102479SFrederic Weisbecker 3407e2ed097SArnaldo Carvalho de Melo if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) 3410a27d7f9SArnaldo Carvalho de Melo die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 3420a27d7f9SArnaldo Carvalho de Melo 343a91e5431SArnaldo Carvalho de Melo if (file_new) 344a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 345a91e5431SArnaldo Carvalho de Melo else { 346a91e5431SArnaldo Carvalho de Melo if (!perf_evlist__equal(session->evlist, evlist)) { 347a91e5431SArnaldo Carvalho de Melo fprintf(stderr, "incompatible append\n"); 348a91e5431SArnaldo Carvalho de Melo exit(-1); 349dd7927f4SArnaldo Carvalho de Melo } 35086470930SIngo Molnar } 35186470930SIngo Molnar 352a91e5431SArnaldo Carvalho de Melo perf_session__update_sample_type(session); 353a91e5431SArnaldo Carvalho de Melo } 354a91e5431SArnaldo Carvalho de Melo 3556122e4e4SArnaldo Carvalho de Melo static int process_buildids(void) 3566122e4e4SArnaldo Carvalho de Melo { 3576122e4e4SArnaldo Carvalho de Melo u64 size = lseek(output, 0, SEEK_CUR); 3586122e4e4SArnaldo Carvalho de Melo 3599f591fd7SArnaldo Carvalho de Melo if (size == 0) 3609f591fd7SArnaldo Carvalho de Melo return 0; 3619f591fd7SArnaldo Carvalho de Melo 3626122e4e4SArnaldo Carvalho de Melo session->fd = output; 3636122e4e4SArnaldo Carvalho de Melo return __perf_session__process_events(session, post_processing_offset, 3646122e4e4SArnaldo Carvalho de Melo size - post_processing_offset, 3656122e4e4SArnaldo Carvalho de Melo size, &build_id__mark_dso_hit_ops); 3666122e4e4SArnaldo Carvalho de Melo } 3676122e4e4SArnaldo Carvalho de Melo 368f5970550SPeter Zijlstra static void atexit_header(void) 369f5970550SPeter Zijlstra { 370c7929e47STom Zanussi if (!pipe_output) { 37194c744b6SArnaldo Carvalho de Melo session->header.data_size += bytes_written; 372f5970550SPeter Zijlstra 373baa2f6ceSArnaldo Carvalho de Melo if (!no_buildid) 3746122e4e4SArnaldo Carvalho de Melo process_buildids(); 375a91e5431SArnaldo Carvalho de Melo perf_session__write_header(session, evsel_list, output, true); 37639d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 377361c99a6SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 378d65a458bSArnaldo Carvalho de Melo symbol__exit(); 379c7929e47STom Zanussi } 380f5970550SPeter Zijlstra } 381f5970550SPeter Zijlstra 3828115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 383a1645ce1SZhang, Yanmin { 384a1645ce1SZhang, Yanmin int err; 38523346f21SArnaldo Carvalho de Melo struct perf_session *psession = data; 386a1645ce1SZhang, Yanmin 38723346f21SArnaldo Carvalho de Melo if (machine__is_host(machine)) 388a1645ce1SZhang, Yanmin return; 389a1645ce1SZhang, Yanmin 390a1645ce1SZhang, Yanmin /* 391a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 392a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 393a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 394a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 395a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 396a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 397a1645ce1SZhang, Yanmin */ 3988115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_modules(process_synthesized_event, 39923346f21SArnaldo Carvalho de Melo psession, machine); 400a1645ce1SZhang, Yanmin if (err < 0) 401a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 40223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 403a1645ce1SZhang, Yanmin 404a1645ce1SZhang, Yanmin /* 405a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 406a1645ce1SZhang, Yanmin * have no _text sometimes. 407a1645ce1SZhang, Yanmin */ 4088115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 40923346f21SArnaldo Carvalho de Melo psession, machine, "_text"); 410a1645ce1SZhang, Yanmin if (err < 0) 4118115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 4128115d60cSArnaldo Carvalho de Melo psession, machine, 4138115d60cSArnaldo Carvalho de Melo "_stext"); 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 41998402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 42098402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 42198402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 42298402807SFrederic Weisbecker }; 42398402807SFrederic Weisbecker 42498402807SFrederic Weisbecker static void mmap_read_all(void) 42598402807SFrederic Weisbecker { 4260e2e63ddSPeter Zijlstra int i; 42798402807SFrederic Weisbecker 428aece948fSArnaldo Carvalho de Melo for (i = 0; i < evsel_list->nr_mmaps; i++) { 4290a27d7f9SArnaldo Carvalho de Melo if (evsel_list->mmap[i].base) 4300a27d7f9SArnaldo Carvalho de Melo mmap_read(&evsel_list->mmap[i]); 43198402807SFrederic Weisbecker } 43298402807SFrederic Weisbecker 43398402807SFrederic Weisbecker if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 43498402807SFrederic Weisbecker write_output(&finished_round_event, sizeof(finished_round_event)); 43598402807SFrederic Weisbecker } 43698402807SFrederic Weisbecker 437d4db3f16SArnaldo Carvalho de Melo static int __cmd_record(int argc, const char **argv) 43886470930SIngo Molnar { 43986470930SIngo Molnar struct stat st; 44086470930SIngo Molnar int flags; 4414dc0a04bSArnaldo Carvalho de Melo int err; 4428b412664SPeter Zijlstra unsigned long waking = 0; 443856e9660SPeter Zijlstra int child_ready_pipe[2], go_pipe[2]; 44446be604bSZhang, Yanmin const bool forks = argc > 0; 445856e9660SPeter Zijlstra char buf; 44623346f21SArnaldo Carvalho de Melo struct machine *machine; 44786470930SIngo Molnar 44886470930SIngo Molnar page_size = sysconf(_SC_PAGE_SIZE); 44986470930SIngo Molnar 450f5970550SPeter Zijlstra atexit(sig_atexit); 451f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 452f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 45318483b81SArnaldo Carvalho de Melo signal(SIGUSR1, sig_handler); 454f5970550SPeter Zijlstra 455d4db3f16SArnaldo Carvalho de Melo if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 456856e9660SPeter Zijlstra perror("failed to create pipes"); 457856e9660SPeter Zijlstra exit(-1); 458856e9660SPeter Zijlstra } 459856e9660SPeter Zijlstra 460d7065adbSFranck Bui-Huu if (!output_name) { 461d7065adbSFranck Bui-Huu if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 462d7065adbSFranck Bui-Huu pipe_output = 1; 463d7065adbSFranck Bui-Huu else 464d7065adbSFranck Bui-Huu output_name = "perf.data"; 465d7065adbSFranck Bui-Huu } 466d7065adbSFranck Bui-Huu if (output_name) { 467529870e3STom Zanussi if (!strcmp(output_name, "-")) 468529870e3STom Zanussi pipe_output = 1; 469529870e3STom Zanussi else if (!stat(output_name, &st) && st.st_size) { 4707865e817SFrederic Weisbecker if (write_mode == WRITE_FORCE) { 471b38d3464SArnaldo Carvalho de Melo char oldname[PATH_MAX]; 472b38d3464SArnaldo Carvalho de Melo snprintf(oldname, sizeof(oldname), "%s.old", 473b38d3464SArnaldo Carvalho de Melo output_name); 474b38d3464SArnaldo Carvalho de Melo unlink(oldname); 475b38d3464SArnaldo Carvalho de Melo rename(output_name, oldname); 476b38d3464SArnaldo Carvalho de Melo } 4777865e817SFrederic Weisbecker } else if (write_mode == WRITE_APPEND) { 4787865e817SFrederic Weisbecker write_mode = WRITE_FORCE; 479266e0e21SPierre Habouzit } 480d7065adbSFranck Bui-Huu } 48186470930SIngo Molnar 482f887f301SXiao Guangrong flags = O_CREAT|O_RDWR; 4837865e817SFrederic Weisbecker if (write_mode == WRITE_APPEND) 484f5970550SPeter Zijlstra file_new = 0; 48586470930SIngo Molnar else 48686470930SIngo Molnar flags |= O_TRUNC; 48786470930SIngo Molnar 488529870e3STom Zanussi if (pipe_output) 489529870e3STom Zanussi output = STDOUT_FILENO; 490529870e3STom Zanussi else 49186470930SIngo Molnar output = open(output_name, flags, S_IRUSR | S_IWUSR); 49286470930SIngo Molnar if (output < 0) { 49386470930SIngo Molnar perror("failed to create output file"); 49486470930SIngo Molnar exit(-1); 49586470930SIngo Molnar } 49686470930SIngo Molnar 4977865e817SFrederic Weisbecker session = perf_session__new(output_name, O_WRONLY, 49821ef97f0SIan Munsie write_mode == WRITE_FORCE, false, NULL); 49994c744b6SArnaldo Carvalho de Melo if (session == NULL) { 500a9a70bbcSArnaldo Carvalho de Melo pr_err("Not enough memory for reading perf file header\n"); 501a9a70bbcSArnaldo Carvalho de Melo return -1; 502a9a70bbcSArnaldo Carvalho de Melo } 503a9a70bbcSArnaldo Carvalho de Melo 504baa2f6ceSArnaldo Carvalho de Melo if (!no_buildid) 505baa2f6ceSArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_BUILD_ID); 506baa2f6ceSArnaldo Carvalho de Melo 5074dc0a04bSArnaldo Carvalho de Melo if (!file_new) { 508a91e5431SArnaldo Carvalho de Melo err = perf_session__read_header(session, output); 5094dc0a04bSArnaldo Carvalho de Melo if (err < 0) 51039d17dacSArnaldo Carvalho de Melo goto out_delete_session; 5114dc0a04bSArnaldo Carvalho de Melo } 5124dc0a04bSArnaldo Carvalho de Melo 513361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) 51494c744b6SArnaldo Carvalho de Melo perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 51503456a15SFrederic Weisbecker 516800cd25cSFrederic Weisbecker /* 512 kiB: default amount of unprivileged mlocked memory */ 517800cd25cSFrederic Weisbecker if (mmap_pages == UINT_MAX) 518800cd25cSFrederic Weisbecker mmap_pages = (512 * 1024) / page_size; 519800cd25cSFrederic Weisbecker 520d4db3f16SArnaldo Carvalho de Melo if (forks) { 52146be604bSZhang, Yanmin child_pid = fork(); 5222fb750e8SBorislav Petkov if (child_pid < 0) { 523856e9660SPeter Zijlstra perror("failed to fork"); 524856e9660SPeter Zijlstra exit(-1); 525856e9660SPeter Zijlstra } 5267c6a1c65SPeter Zijlstra 52746be604bSZhang, Yanmin if (!child_pid) { 528529870e3STom Zanussi if (pipe_output) 529529870e3STom Zanussi dup2(2, 1); 530856e9660SPeter Zijlstra close(child_ready_pipe[0]); 531856e9660SPeter Zijlstra close(go_pipe[1]); 532856e9660SPeter Zijlstra fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 533856e9660SPeter Zijlstra 534856e9660SPeter Zijlstra /* 535856e9660SPeter Zijlstra * Do a dummy execvp to get the PLT entry resolved, 536856e9660SPeter Zijlstra * so we avoid the resolver overhead on the real 537856e9660SPeter Zijlstra * execvp call. 538856e9660SPeter Zijlstra */ 539856e9660SPeter Zijlstra execvp("", (char **)argv); 540856e9660SPeter Zijlstra 541856e9660SPeter Zijlstra /* 542856e9660SPeter Zijlstra * Tell the parent we're ready to go 543856e9660SPeter Zijlstra */ 544856e9660SPeter Zijlstra close(child_ready_pipe[1]); 545856e9660SPeter Zijlstra 546856e9660SPeter Zijlstra /* 547856e9660SPeter Zijlstra * Wait until the parent tells us to go. 548856e9660SPeter Zijlstra */ 549856e9660SPeter Zijlstra if (read(go_pipe[0], &buf, 1) == -1) 550856e9660SPeter Zijlstra perror("unable to read pipe"); 551856e9660SPeter Zijlstra 552856e9660SPeter Zijlstra execvp(argv[0], (char **)argv); 553856e9660SPeter Zijlstra 554856e9660SPeter Zijlstra perror(argv[0]); 55518483b81SArnaldo Carvalho de Melo kill(getppid(), SIGUSR1); 556856e9660SPeter Zijlstra exit(-1); 557856e9660SPeter Zijlstra } 558856e9660SPeter Zijlstra 559d6d901c2SZhang, Yanmin if (!system_wide && target_tid == -1 && target_pid == -1) 5607e2ed097SArnaldo Carvalho de Melo evsel_list->threads->map[0] = child_pid; 561d6d901c2SZhang, Yanmin 562856e9660SPeter Zijlstra close(child_ready_pipe[1]); 563856e9660SPeter Zijlstra close(go_pipe[0]); 564856e9660SPeter Zijlstra /* 565856e9660SPeter Zijlstra * wait for child to settle 566856e9660SPeter Zijlstra */ 567856e9660SPeter Zijlstra if (read(child_ready_pipe[0], &buf, 1) == -1) { 568856e9660SPeter Zijlstra perror("unable to read pipe"); 569856e9660SPeter Zijlstra exit(-1); 570856e9660SPeter Zijlstra } 571856e9660SPeter Zijlstra close(child_ready_pipe[0]); 572856e9660SPeter Zijlstra } 573856e9660SPeter Zijlstra 574dd7927f4SArnaldo Carvalho de Melo open_counters(evsel_list); 57586470930SIngo Molnar 576712a4b60SArnaldo Carvalho de Melo /* 577712a4b60SArnaldo Carvalho de Melo * perf_session__delete(session) will be called at atexit_header() 578712a4b60SArnaldo Carvalho de Melo */ 579712a4b60SArnaldo Carvalho de Melo atexit(atexit_header); 580712a4b60SArnaldo Carvalho de Melo 581529870e3STom Zanussi if (pipe_output) { 582529870e3STom Zanussi err = perf_header__write_pipe(output); 583529870e3STom Zanussi if (err < 0) 584529870e3STom Zanussi return err; 585529870e3STom Zanussi } else if (file_new) { 586a91e5431SArnaldo Carvalho de Melo err = perf_session__write_header(session, evsel_list, 587361c99a6SArnaldo Carvalho de Melo output, false); 588d5eed904SArnaldo Carvalho de Melo if (err < 0) 589d5eed904SArnaldo Carvalho de Melo return err; 590d5eed904SArnaldo Carvalho de Melo } 5917c6a1c65SPeter Zijlstra 5926122e4e4SArnaldo Carvalho de Melo post_processing_offset = lseek(output, 0, SEEK_CUR); 5936122e4e4SArnaldo Carvalho de Melo 5942c46dbb5STom Zanussi if (pipe_output) { 595a91e5431SArnaldo Carvalho de Melo err = perf_session__synthesize_attrs(session, 596a91e5431SArnaldo Carvalho de Melo process_synthesized_event); 5972c46dbb5STom Zanussi if (err < 0) { 5982c46dbb5STom Zanussi pr_err("Couldn't synthesize attrs.\n"); 5992c46dbb5STom Zanussi return err; 6002c46dbb5STom Zanussi } 601cd19a035STom Zanussi 6028115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_event_types(process_synthesized_event, 603cd19a035STom Zanussi session); 604cd19a035STom Zanussi if (err < 0) { 605cd19a035STom Zanussi pr_err("Couldn't synthesize event_types.\n"); 606cd19a035STom Zanussi return err; 607cd19a035STom Zanussi } 6089215545eSTom Zanussi 609361c99a6SArnaldo Carvalho de Melo if (have_tracepoints(&evsel_list->entries)) { 61063e0c771STom Zanussi /* 61163e0c771STom Zanussi * FIXME err <= 0 here actually means that 61263e0c771STom Zanussi * there were no tracepoints so its not really 61363e0c771STom Zanussi * an error, just that we don't need to 61463e0c771STom Zanussi * synthesize anything. We really have to 61563e0c771STom Zanussi * return this more properly and also 61663e0c771STom Zanussi * propagate errors that now are calling die() 61763e0c771STom Zanussi */ 6188115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_tracing_data(output, evsel_list, 6199215545eSTom Zanussi process_synthesized_event, 6209215545eSTom Zanussi session); 62163e0c771STom Zanussi if (err <= 0) { 62263e0c771STom Zanussi pr_err("Couldn't record tracing data.\n"); 62363e0c771STom Zanussi return err; 62463e0c771STom Zanussi } 6259215545eSTom Zanussi advance_output(err); 6262c46dbb5STom Zanussi } 62763e0c771STom Zanussi } 6282c46dbb5STom Zanussi 62923346f21SArnaldo Carvalho de Melo machine = perf_session__find_host_machine(session); 63023346f21SArnaldo Carvalho de Melo if (!machine) { 631a1645ce1SZhang, Yanmin pr_err("Couldn't find native kernel information.\n"); 632a1645ce1SZhang, Yanmin return -1; 633a1645ce1SZhang, Yanmin } 634a1645ce1SZhang, Yanmin 6358115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 63623346f21SArnaldo Carvalho de Melo session, machine, "_text"); 63770162138SArnaldo Carvalho de Melo if (err < 0) 6388115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 63923346f21SArnaldo Carvalho de Melo session, machine, "_stext"); 640c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 641c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel reference relocation symbol\n" 642c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 643c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/kallsyms permission or run as root.\n"); 64456b03f3cSArnaldo Carvalho de Melo 6458115d60cSArnaldo Carvalho de Melo err = perf_event__synthesize_modules(process_synthesized_event, 64623346f21SArnaldo Carvalho de Melo session, machine); 647c1a3a4b9SArnaldo Carvalho de Melo if (err < 0) 648c1a3a4b9SArnaldo Carvalho de Melo pr_err("Couldn't record kernel module information.\n" 649c1a3a4b9SArnaldo Carvalho de Melo "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 650c1a3a4b9SArnaldo Carvalho de Melo "Check /proc/modules permission or run as root.\n"); 651c1a3a4b9SArnaldo Carvalho de Melo 652a1645ce1SZhang, Yanmin if (perf_guest) 6538115d60cSArnaldo Carvalho de Melo perf_session__process_machines(session, 6548115d60cSArnaldo Carvalho de Melo perf_event__synthesize_guest_os); 655b7cece76SArnaldo Carvalho de Melo 656cf103a14SStephane Eranian if (!system_wide) 6577c940c18SArnaldo Carvalho de Melo perf_event__synthesize_thread_map(evsel_list->threads, 6588115d60cSArnaldo Carvalho de Melo process_synthesized_event, 659d8f66248SArnaldo Carvalho de Melo session); 660234fbbf5SArnaldo Carvalho de Melo else 6618115d60cSArnaldo Carvalho de Melo perf_event__synthesize_threads(process_synthesized_event, 6628115d60cSArnaldo Carvalho de Melo session); 6637c6a1c65SPeter Zijlstra 66486470930SIngo Molnar if (realtime_prio) { 66586470930SIngo Molnar struct sched_param param; 66686470930SIngo Molnar 66786470930SIngo Molnar param.sched_priority = realtime_prio; 66886470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 6696beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 67086470930SIngo Molnar exit(-1); 67186470930SIngo Molnar } 67286470930SIngo Molnar } 67386470930SIngo Molnar 674856e9660SPeter Zijlstra /* 675856e9660SPeter Zijlstra * Let the child rip 676856e9660SPeter Zijlstra */ 677d4db3f16SArnaldo Carvalho de Melo if (forks) 678856e9660SPeter Zijlstra close(go_pipe[1]); 679856e9660SPeter Zijlstra 680649c48a9SPeter Zijlstra for (;;) { 68186470930SIngo Molnar int hits = samples; 68286470930SIngo Molnar 68398402807SFrederic Weisbecker mmap_read_all(); 68486470930SIngo Molnar 685649c48a9SPeter Zijlstra if (hits == samples) { 686649c48a9SPeter Zijlstra if (done) 687649c48a9SPeter Zijlstra break; 6885c581041SArnaldo Carvalho de Melo err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 6898b412664SPeter Zijlstra waking++; 6908b412664SPeter Zijlstra } 6918b412664SPeter Zijlstra 692*4152ab37SArnaldo Carvalho de Melo if (done) 693*4152ab37SArnaldo Carvalho de Melo perf_evlist__disable(evsel_list); 6948b412664SPeter Zijlstra } 6958b412664SPeter Zijlstra 69618483b81SArnaldo Carvalho de Melo if (quiet || signr == SIGUSR1) 697b44308f5SArnaldo Carvalho de Melo return 0; 698b44308f5SArnaldo Carvalho de Melo 6998b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 70086470930SIngo Molnar 70186470930SIngo Molnar /* 70286470930SIngo Molnar * Approximate RIP event size: 24 bytes. 70386470930SIngo Molnar */ 70486470930SIngo Molnar fprintf(stderr, 7059486aa38SArnaldo Carvalho de Melo "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 70686470930SIngo Molnar (double)bytes_written / 1024.0 / 1024.0, 70786470930SIngo Molnar output_name, 70886470930SIngo Molnar bytes_written / 24); 70986470930SIngo Molnar 71086470930SIngo Molnar return 0; 71139d17dacSArnaldo Carvalho de Melo 71239d17dacSArnaldo Carvalho de Melo out_delete_session: 71339d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 71439d17dacSArnaldo Carvalho de Melo return err; 71586470930SIngo Molnar } 71686470930SIngo Molnar 71786470930SIngo Molnar static const char * const record_usage[] = { 71886470930SIngo Molnar "perf record [<options>] [<command>]", 71986470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 72086470930SIngo Molnar NULL 72186470930SIngo Molnar }; 72286470930SIngo Molnar 7237865e817SFrederic Weisbecker static bool force, append_file; 7247865e817SFrederic Weisbecker 725bca647aaSTom Zanussi const struct option record_options[] = { 726361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &evsel_list, "event", 72786470930SIngo Molnar "event selector. use 'perf list' to list available events", 728f120f9d5SJiri Olsa parse_events_option), 729361c99a6SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &evsel_list, "filter", 730c171b552SLi Zefan "event filter", parse_filter), 73186470930SIngo Molnar OPT_INTEGER('p', "pid", &target_pid, 732d6d901c2SZhang, Yanmin "record events on existing process id"), 733d6d901c2SZhang, Yanmin OPT_INTEGER('t', "tid", &target_tid, 734d6d901c2SZhang, Yanmin "record events on existing thread id"), 73586470930SIngo Molnar OPT_INTEGER('r', "realtime", &realtime_prio, 73686470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 737acac03faSKirill Smelkov OPT_BOOLEAN('D', "no-delay", &nodelay, 738acac03faSKirill Smelkov "collect data without buffering"), 739daac07b2SFrederic Weisbecker OPT_BOOLEAN('R', "raw-samples", &raw_samples, 740daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 74186470930SIngo Molnar OPT_BOOLEAN('a', "all-cpus", &system_wide, 74286470930SIngo Molnar "system-wide collection from all CPUs"), 74386470930SIngo Molnar OPT_BOOLEAN('A', "append", &append_file, 74486470930SIngo Molnar "append to the output file to do incremental profiling"), 745c45c6ea2SStephane Eranian OPT_STRING('C', "cpu", &cpu_list, "cpu", 746c45c6ea2SStephane Eranian "list of cpus to monitor"), 74786470930SIngo Molnar OPT_BOOLEAN('f', "force", &force, 7487865e817SFrederic Weisbecker "overwrite existing data file (deprecated)"), 7493de29cabSStephane Eranian OPT_U64('c', "count", &user_interval, "event period to sample"), 75086470930SIngo Molnar OPT_STRING('o', "output", &output_name, "file", 75186470930SIngo Molnar "output file name"), 7522e6cdf99SStephane Eranian OPT_BOOLEAN('i', "no-inherit", &no_inherit, 7532e6cdf99SStephane Eranian "child tasks do not inherit counters"), 7541967936dSArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 7551967936dSArnaldo Carvalho de Melo OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 7563efa1cc9SIngo Molnar OPT_BOOLEAN('g', "call-graph", &call_graph, 7573efa1cc9SIngo Molnar "do call-graph (stack chain/backtrace) recording"), 758c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 7593da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 760b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 761649c48a9SPeter Zijlstra OPT_BOOLEAN('s', "stat", &inherit_stat, 762649c48a9SPeter Zijlstra "per thread counts"), 7634bba828dSAnton Blanchard OPT_BOOLEAN('d', "data", &sample_address, 7644bba828dSAnton Blanchard "Sample addresses"), 7659c90a61cSArnaldo Carvalho de Melo OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"), 766649c48a9SPeter Zijlstra OPT_BOOLEAN('n', "no-samples", &no_samples, 767649c48a9SPeter Zijlstra "don't sample"), 768baa2f6ceSArnaldo Carvalho de Melo OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 769a1ac1d3cSStephane Eranian "do not update the buildid cache"), 770baa2f6ceSArnaldo Carvalho de Melo OPT_BOOLEAN('B', "no-buildid", &no_buildid, 771baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 772023695d9SStephane Eranian OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 773023695d9SStephane Eranian "monitor event in cgroup name only", 774023695d9SStephane Eranian parse_cgroups), 77586470930SIngo Molnar OPT_END() 77686470930SIngo Molnar }; 77786470930SIngo Molnar 778f37a291cSIngo Molnar int cmd_record(int argc, const char **argv, const char *prefix __used) 77986470930SIngo Molnar { 78069aad6f1SArnaldo Carvalho de Melo int err = -ENOMEM; 78169aad6f1SArnaldo Carvalho de Melo struct perf_evsel *pos; 78286470930SIngo Molnar 7837e2ed097SArnaldo Carvalho de Melo evsel_list = perf_evlist__new(NULL, NULL); 784361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 785361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 786361c99a6SArnaldo Carvalho de Melo 787bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 788a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 789d6d901c2SZhang, Yanmin if (!argc && target_pid == -1 && target_tid == -1 && 790c45c6ea2SStephane Eranian !system_wide && !cpu_list) 791bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 79286470930SIngo Molnar 7937865e817SFrederic Weisbecker if (force && append_file) { 7947865e817SFrederic Weisbecker fprintf(stderr, "Can't overwrite and append at the same time." 7957865e817SFrederic Weisbecker " You need to choose between -f and -A"); 796bca647aaSTom Zanussi usage_with_options(record_usage, record_options); 7977865e817SFrederic Weisbecker } else if (append_file) { 7987865e817SFrederic Weisbecker write_mode = WRITE_APPEND; 7997865e817SFrederic Weisbecker } else { 8007865e817SFrederic Weisbecker write_mode = WRITE_FORCE; 8017865e817SFrederic Weisbecker } 8027865e817SFrederic Weisbecker 803023695d9SStephane Eranian if (nr_cgroups && !system_wide) { 804023695d9SStephane Eranian fprintf(stderr, "cgroup monitoring only available in" 805023695d9SStephane Eranian " system-wide mode\n"); 806023695d9SStephane Eranian usage_with_options(record_usage, record_options); 807023695d9SStephane Eranian } 808023695d9SStephane Eranian 809655000e7SArnaldo Carvalho de Melo symbol__init(); 810baa2f6ceSArnaldo Carvalho de Melo 811ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 812646aaea6SArnaldo Carvalho de Melo pr_warning( 813646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 814ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 815646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 816646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 817646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 818646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 819646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 820ec80fde7SArnaldo Carvalho de Melo 821baa2f6ceSArnaldo Carvalho de Melo if (no_buildid_cache || no_buildid) 822a1ac1d3cSStephane Eranian disable_buildid_cache(); 823655000e7SArnaldo Carvalho de Melo 824361c99a6SArnaldo Carvalho de Melo if (evsel_list->nr_entries == 0 && 825361c99a6SArnaldo Carvalho de Melo perf_evlist__add_default(evsel_list) < 0) { 82669aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 82769aad6f1SArnaldo Carvalho de Melo goto out_symbol_exit; 828bbd36e5eSPeter Zijlstra } 82986470930SIngo Molnar 8305c98d466SArnaldo Carvalho de Melo if (target_pid != -1) 831d6d901c2SZhang, Yanmin target_tid = target_pid; 832d6d901c2SZhang, Yanmin 8337e2ed097SArnaldo Carvalho de Melo if (perf_evlist__create_maps(evsel_list, target_pid, 8347e2ed097SArnaldo Carvalho de Melo target_tid, cpu_list) < 0) 835dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 83669aad6f1SArnaldo Carvalho de Melo 837361c99a6SArnaldo Carvalho de Melo list_for_each_entry(pos, &evsel_list->entries, node) { 8387e2ed097SArnaldo Carvalho de Melo if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, 8397e2ed097SArnaldo Carvalho de Melo evsel_list->threads->nr) < 0) 84069aad6f1SArnaldo Carvalho de Melo goto out_free_fd; 841ad7f4e3fSArnaldo Carvalho de Melo if (perf_header__push_event(pos->attr.config, event_name(pos))) 842ad7f4e3fSArnaldo Carvalho de Melo goto out_free_fd; 843d6d901c2SZhang, Yanmin } 8445c581041SArnaldo Carvalho de Melo 8457e2ed097SArnaldo Carvalho de Melo if (perf_evlist__alloc_pollfd(evsel_list) < 0) 84639d17dacSArnaldo Carvalho de Melo goto out_free_fd; 847d6d901c2SZhang, Yanmin 8483de29cabSStephane Eranian if (user_interval != ULLONG_MAX) 849f9212819SFrederic Weisbecker default_interval = user_interval; 850f9212819SFrederic Weisbecker if (user_freq != UINT_MAX) 851f9212819SFrederic Weisbecker freq = user_freq; 852f9212819SFrederic Weisbecker 8537e4ff9e3SMike Galbraith /* 8547e4ff9e3SMike Galbraith * User specified count overrides default frequency. 8557e4ff9e3SMike Galbraith */ 8567e4ff9e3SMike Galbraith if (default_interval) 8577e4ff9e3SMike Galbraith freq = 0; 8587e4ff9e3SMike Galbraith else if (freq) { 8597e4ff9e3SMike Galbraith default_interval = freq; 8607e4ff9e3SMike Galbraith } else { 8617e4ff9e3SMike Galbraith fprintf(stderr, "frequency and count are zero, aborting\n"); 86239d17dacSArnaldo Carvalho de Melo err = -EINVAL; 8635c581041SArnaldo Carvalho de Melo goto out_free_fd; 8647e4ff9e3SMike Galbraith } 8657e4ff9e3SMike Galbraith 86639d17dacSArnaldo Carvalho de Melo err = __cmd_record(argc, argv); 86739d17dacSArnaldo Carvalho de Melo out_free_fd: 8687e2ed097SArnaldo Carvalho de Melo perf_evlist__delete_maps(evsel_list); 869d65a458bSArnaldo Carvalho de Melo out_symbol_exit: 870d65a458bSArnaldo Carvalho de Melo symbol__exit(); 87139d17dacSArnaldo Carvalho de Melo return err; 87286470930SIngo Molnar } 873