1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 286470930SIngo Molnar /* 386470930SIngo Molnar * builtin-record.c 486470930SIngo Molnar * 586470930SIngo Molnar * Builtin record command: Record the profile of a workload 686470930SIngo Molnar * (or a CPU, or a PID) into the perf.data output file - for 786470930SIngo Molnar * later analysis via perf report. 886470930SIngo Molnar */ 986470930SIngo Molnar #include "builtin.h" 1086470930SIngo Molnar 1186470930SIngo Molnar #include "perf.h" 1286470930SIngo Molnar 136122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 1486470930SIngo Molnar #include "util/util.h" 154b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1686470930SIngo Molnar #include "util/parse-events.h" 1741840d21STaeung Song #include "util/config.h" 1886470930SIngo Molnar 198f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 20f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 217c6a1c65SPeter Zijlstra #include "util/header.h" 2266e274f3SFrederic Weisbecker #include "util/event.h" 23361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2469aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 258f28827aSFrederic Weisbecker #include "util/debug.h" 265d8bb1ecSMathieu Poirier #include "util/drv_configs.h" 2794c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2845694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 298d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 30a12b51c4SPaul Mackerras #include "util/cpumap.h" 31fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 32f5fc1412SJiri Olsa #include "util/data.h" 33bcc84ec6SStephane Eranian #include "util/perf_regs.h" 34ef149c25SAdrian Hunter #include "util/auxtrace.h" 3546bc29b9SAdrian Hunter #include "util/tsc.h" 36f00898f4SAndi Kleen #include "util/parse-branch-options.h" 37bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3871dc2326SWang Nan #include "util/llvm-utils.h" 398690a2a7SWang Nan #include "util/bpf-loader.h" 405f9cf599SWang Nan #include "util/trigger.h" 41a074865eSWang Nan #include "util/perf-hooks.h" 42c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h" 4358db1d6eSArnaldo Carvalho de Melo #include "util/units.h" 44d8871ea7SWang Nan #include "asm/bug.h" 457c6a1c65SPeter Zijlstra 46a43783aeSArnaldo Carvalho de Melo #include <errno.h> 47fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 484208735dSArnaldo Carvalho de Melo #include <poll.h> 4986470930SIngo Molnar #include <unistd.h> 5086470930SIngo Molnar #include <sched.h> 519607ad3aSArnaldo Carvalho de Melo #include <signal.h> 52a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 534208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 542d11c650SWang Nan #include <asm/bug.h> 550693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 5678da39faSBernhard Rosenkraenzer 571b43b704SJiri Olsa struct switch_output { 58dc0c6127SJiri Olsa bool enabled; 591b43b704SJiri Olsa bool signal; 60dc0c6127SJiri Olsa unsigned long size; 61bfacbe3bSJiri Olsa unsigned long time; 62cb4e1ebbSJiri Olsa const char *str; 63cb4e1ebbSJiri Olsa bool set; 641b43b704SJiri Olsa }; 651b43b704SJiri Olsa 668c6f45a7SArnaldo Carvalho de Melo struct record { 6745694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 68b4006796SArnaldo Carvalho de Melo struct record_opts opts; 69d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 708ceb41d7SJiri Olsa struct perf_data data; 71ef149c25SAdrian Hunter struct auxtrace_record *itr; 72d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist; 73d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 74d20deb64SArnaldo Carvalho de Melo const char *progname; 75d20deb64SArnaldo Carvalho de Melo int realtime_prio; 76d20deb64SArnaldo Carvalho de Melo bool no_buildid; 77d2db9a98SWang Nan bool no_buildid_set; 78d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 79d2db9a98SWang Nan bool no_buildid_cache_set; 806156681bSNamhyung Kim bool buildid_all; 81ecfd7a9cSWang Nan bool timestamp_filename; 821b43b704SJiri Olsa struct switch_output switch_output; 839f065194SYang Shi unsigned long long samples; 840f82ebc4SArnaldo Carvalho de Melo }; 8586470930SIngo Molnar 86dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started; 87dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 88dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger); 89dc0c6127SJiri Olsa 90dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec) 91dc0c6127SJiri Olsa { 92dc0c6127SJiri Olsa return rec->switch_output.signal && 93dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger); 94dc0c6127SJiri Olsa } 95dc0c6127SJiri Olsa 96dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec) 97dc0c6127SJiri Olsa { 98dc0c6127SJiri Olsa return rec->switch_output.size && 99dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) && 100dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size); 101dc0c6127SJiri Olsa } 102dc0c6127SJiri Olsa 103bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec) 104bfacbe3bSJiri Olsa { 105bfacbe3bSJiri Olsa return rec->switch_output.time && 106bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger); 107bfacbe3bSJiri Olsa } 108bfacbe3bSJiri Olsa 1098c6f45a7SArnaldo Carvalho de Melo static int record__write(struct record *rec, void *bf, size_t size) 110f5970550SPeter Zijlstra { 1118ceb41d7SJiri Olsa if (perf_data__write(rec->session->data, bf, size) < 0) { 1124f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 1138d3eca20SDavid Ahern return -1; 1148d3eca20SDavid Ahern } 115f5970550SPeter Zijlstra 116cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 117dc0c6127SJiri Olsa 118dc0c6127SJiri Olsa if (switch_output_size(rec)) 119dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger); 120dc0c6127SJiri Olsa 1218d3eca20SDavid Ahern return 0; 122f5970550SPeter Zijlstra } 123f5970550SPeter Zijlstra 12445694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 125d20deb64SArnaldo Carvalho de Melo union perf_event *event, 1261d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 1271d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 128234fbbf5SArnaldo Carvalho de Melo { 1298c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 1308c6f45a7SArnaldo Carvalho de Melo return record__write(rec, event, event->header.size); 131234fbbf5SArnaldo Carvalho de Melo } 132234fbbf5SArnaldo Carvalho de Melo 133d37f1586SArnaldo Carvalho de Melo static int record__pushfn(void *to, void *bf, size_t size) 134d37f1586SArnaldo Carvalho de Melo { 135d37f1586SArnaldo Carvalho de Melo struct record *rec = to; 136d37f1586SArnaldo Carvalho de Melo 137d37f1586SArnaldo Carvalho de Melo rec->samples++; 138d37f1586SArnaldo Carvalho de Melo return record__write(rec, bf, size); 139d37f1586SArnaldo Carvalho de Melo } 140d37f1586SArnaldo Carvalho de Melo 1412dd6d8a1SAdrian Hunter static volatile int done; 1422dd6d8a1SAdrian Hunter static volatile int signr = -1; 1432dd6d8a1SAdrian Hunter static volatile int child_finished; 144c0bdc1c4SWang Nan 1452dd6d8a1SAdrian Hunter static void sig_handler(int sig) 1462dd6d8a1SAdrian Hunter { 1472dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 1482dd6d8a1SAdrian Hunter child_finished = 1; 1492dd6d8a1SAdrian Hunter else 1502dd6d8a1SAdrian Hunter signr = sig; 1512dd6d8a1SAdrian Hunter 1522dd6d8a1SAdrian Hunter done = 1; 1532dd6d8a1SAdrian Hunter } 1542dd6d8a1SAdrian Hunter 155a074865eSWang Nan static void sigsegv_handler(int sig) 156a074865eSWang Nan { 157a074865eSWang Nan perf_hooks__recover(); 158a074865eSWang Nan sighandler_dump_stack(sig); 159a074865eSWang Nan } 160a074865eSWang Nan 1612dd6d8a1SAdrian Hunter static void record__sig_exit(void) 1622dd6d8a1SAdrian Hunter { 1632dd6d8a1SAdrian Hunter if (signr == -1) 1642dd6d8a1SAdrian Hunter return; 1652dd6d8a1SAdrian Hunter 1662dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 1672dd6d8a1SAdrian Hunter raise(signr); 1682dd6d8a1SAdrian Hunter } 1692dd6d8a1SAdrian Hunter 170e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 171e31f0d01SAdrian Hunter 172ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 173ef149c25SAdrian Hunter union perf_event *event, void *data1, 174ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 175ef149c25SAdrian Hunter { 176ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 1778ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 178ef149c25SAdrian Hunter size_t padding; 179ef149c25SAdrian Hunter u8 pad[8] = {0}; 180ef149c25SAdrian Hunter 1818ceb41d7SJiri Olsa if (!perf_data__is_pipe(data)) { 18299fa2984SAdrian Hunter off_t file_offset; 1838ceb41d7SJiri Olsa int fd = perf_data__fd(data); 18499fa2984SAdrian Hunter int err; 18599fa2984SAdrian Hunter 18699fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 18799fa2984SAdrian Hunter if (file_offset == -1) 18899fa2984SAdrian Hunter return -1; 18999fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 19099fa2984SAdrian Hunter event, file_offset); 19199fa2984SAdrian Hunter if (err) 19299fa2984SAdrian Hunter return err; 19399fa2984SAdrian Hunter } 19499fa2984SAdrian Hunter 195ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 196ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 197ef149c25SAdrian Hunter if (padding) 198ef149c25SAdrian Hunter padding = 8 - padding; 199ef149c25SAdrian Hunter 200ef149c25SAdrian Hunter record__write(rec, event, event->header.size); 201ef149c25SAdrian Hunter record__write(rec, data1, len1); 202ef149c25SAdrian Hunter if (len2) 203ef149c25SAdrian Hunter record__write(rec, data2, len2); 204ef149c25SAdrian Hunter record__write(rec, &pad, padding); 205ef149c25SAdrian Hunter 206ef149c25SAdrian Hunter return 0; 207ef149c25SAdrian Hunter } 208ef149c25SAdrian Hunter 209ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 210ef149c25SAdrian Hunter struct auxtrace_mmap *mm) 211ef149c25SAdrian Hunter { 212ef149c25SAdrian Hunter int ret; 213ef149c25SAdrian Hunter 214ef149c25SAdrian Hunter ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 215ef149c25SAdrian Hunter record__process_auxtrace); 216ef149c25SAdrian Hunter if (ret < 0) 217ef149c25SAdrian Hunter return ret; 218ef149c25SAdrian Hunter 219ef149c25SAdrian Hunter if (ret) 220ef149c25SAdrian Hunter rec->samples++; 221ef149c25SAdrian Hunter 222ef149c25SAdrian Hunter return 0; 223ef149c25SAdrian Hunter } 224ef149c25SAdrian Hunter 2252dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 2262dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm) 2272dd6d8a1SAdrian Hunter { 2282dd6d8a1SAdrian Hunter int ret; 2292dd6d8a1SAdrian Hunter 2302dd6d8a1SAdrian Hunter ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 2312dd6d8a1SAdrian Hunter record__process_auxtrace, 2322dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 2332dd6d8a1SAdrian Hunter if (ret < 0) 2342dd6d8a1SAdrian Hunter return ret; 2352dd6d8a1SAdrian Hunter 2362dd6d8a1SAdrian Hunter if (ret) 2372dd6d8a1SAdrian Hunter rec->samples++; 2382dd6d8a1SAdrian Hunter 2392dd6d8a1SAdrian Hunter return 0; 2402dd6d8a1SAdrian Hunter } 2412dd6d8a1SAdrian Hunter 2422dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 2432dd6d8a1SAdrian Hunter { 2442dd6d8a1SAdrian Hunter int i; 2452dd6d8a1SAdrian Hunter int rc = 0; 2462dd6d8a1SAdrian Hunter 2472dd6d8a1SAdrian Hunter for (i = 0; i < rec->evlist->nr_mmaps; i++) { 2482dd6d8a1SAdrian Hunter struct auxtrace_mmap *mm = 2492dd6d8a1SAdrian Hunter &rec->evlist->mmap[i].auxtrace_mmap; 2502dd6d8a1SAdrian Hunter 2512dd6d8a1SAdrian Hunter if (!mm->base) 2522dd6d8a1SAdrian Hunter continue; 2532dd6d8a1SAdrian Hunter 2542dd6d8a1SAdrian Hunter if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 2552dd6d8a1SAdrian Hunter rc = -1; 2562dd6d8a1SAdrian Hunter goto out; 2572dd6d8a1SAdrian Hunter } 2582dd6d8a1SAdrian Hunter } 2592dd6d8a1SAdrian Hunter out: 2602dd6d8a1SAdrian Hunter return rc; 2612dd6d8a1SAdrian Hunter } 2622dd6d8a1SAdrian Hunter 2632dd6d8a1SAdrian Hunter static void record__read_auxtrace_snapshot(struct record *rec) 2642dd6d8a1SAdrian Hunter { 2652dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 2662dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 2675f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 2682dd6d8a1SAdrian Hunter } else { 2695f9cf599SWang Nan if (auxtrace_record__snapshot_finish(rec->itr)) 2705f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 2715f9cf599SWang Nan else 2725f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 2732dd6d8a1SAdrian Hunter } 2742dd6d8a1SAdrian Hunter } 2752dd6d8a1SAdrian Hunter 276e31f0d01SAdrian Hunter #else 277e31f0d01SAdrian Hunter 278e31f0d01SAdrian Hunter static inline 279e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 280e31f0d01SAdrian Hunter struct auxtrace_mmap *mm __maybe_unused) 281e31f0d01SAdrian Hunter { 282e31f0d01SAdrian Hunter return 0; 283e31f0d01SAdrian Hunter } 284e31f0d01SAdrian Hunter 2852dd6d8a1SAdrian Hunter static inline 2862dd6d8a1SAdrian Hunter void record__read_auxtrace_snapshot(struct record *rec __maybe_unused) 2872dd6d8a1SAdrian Hunter { 2882dd6d8a1SAdrian Hunter } 2892dd6d8a1SAdrian Hunter 2902dd6d8a1SAdrian Hunter static inline 2912dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 2922dd6d8a1SAdrian Hunter { 2932dd6d8a1SAdrian Hunter return 0; 2942dd6d8a1SAdrian Hunter } 2952dd6d8a1SAdrian Hunter 296e31f0d01SAdrian Hunter #endif 297e31f0d01SAdrian Hunter 298cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 299cda57a8cSWang Nan struct perf_evlist *evlist) 300cda57a8cSWang Nan { 301cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 302cda57a8cSWang Nan char msg[512]; 303cda57a8cSWang Nan 304cda57a8cSWang Nan if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 305cda57a8cSWang Nan opts->auxtrace_mmap_pages, 306cda57a8cSWang Nan opts->auxtrace_snapshot_mode) < 0) { 307cda57a8cSWang Nan if (errno == EPERM) { 308cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 309cda57a8cSWang Nan "Consider increasing " 310cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 311cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 312cda57a8cSWang Nan "(current value: %u,%u)\n", 313cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 314cda57a8cSWang Nan return -errno; 315cda57a8cSWang Nan } else { 316cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 317c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 318cda57a8cSWang Nan if (errno) 319cda57a8cSWang Nan return -errno; 320cda57a8cSWang Nan else 321cda57a8cSWang Nan return -EINVAL; 322cda57a8cSWang Nan } 323cda57a8cSWang Nan } 324cda57a8cSWang Nan return 0; 325cda57a8cSWang Nan } 326cda57a8cSWang Nan 327cda57a8cSWang Nan static int record__mmap(struct record *rec) 328cda57a8cSWang Nan { 329cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 330cda57a8cSWang Nan } 331cda57a8cSWang Nan 3328c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 333dd7927f4SArnaldo Carvalho de Melo { 334d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 3356a4bb04cSJiri Olsa struct perf_evsel *pos; 336d20deb64SArnaldo Carvalho de Melo struct perf_evlist *evlist = rec->evlist; 337d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 338b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 3395d8bb1ecSMathieu Poirier struct perf_evsel_config_term *err_term; 3408d3eca20SDavid Ahern int rc = 0; 341dd7927f4SArnaldo Carvalho de Melo 342*d3dbf43cSArnaldo Carvalho de Melo /* 343*d3dbf43cSArnaldo Carvalho de Melo * For initial_delay we need to add a dummy event so that we can track 344*d3dbf43cSArnaldo Carvalho de Melo * PERF_RECORD_MMAP while we wait for the initial delay to enable the 345*d3dbf43cSArnaldo Carvalho de Melo * real events, the ones asked by the user. 346*d3dbf43cSArnaldo Carvalho de Melo */ 347*d3dbf43cSArnaldo Carvalho de Melo if (opts->initial_delay) { 348*d3dbf43cSArnaldo Carvalho de Melo if (perf_evlist__add_dummy(evlist)) 349*d3dbf43cSArnaldo Carvalho de Melo return -ENOMEM; 350*d3dbf43cSArnaldo Carvalho de Melo 351*d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__first(evlist); 352*d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 0; 353*d3dbf43cSArnaldo Carvalho de Melo pos = perf_evlist__last(evlist); 354*d3dbf43cSArnaldo Carvalho de Melo pos->tracking = 1; 355*d3dbf43cSArnaldo Carvalho de Melo pos->attr.enable_on_exec = 1; 356*d3dbf43cSArnaldo Carvalho de Melo } 357*d3dbf43cSArnaldo Carvalho de Melo 358e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 359cac21425SJiri Olsa 360e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 3613da297a6SIngo Molnar try_again: 362d988d5eeSKan Liang if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 36356e52e85SArnaldo Carvalho de Melo if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 364bb963e16SNamhyung Kim if (verbose > 0) 365c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 3663da297a6SIngo Molnar goto try_again; 3673da297a6SIngo Molnar } 368ca6a4258SDavid Ahern 36956e52e85SArnaldo Carvalho de Melo rc = -errno; 37056e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(pos, &opts->target, 37156e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 37256e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 3738d3eca20SDavid Ahern goto out; 3747c6a1c65SPeter Zijlstra } 3757c6a1c65SPeter Zijlstra } 3767c6a1c65SPeter Zijlstra 37723d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 37862d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 37923d4aad4SArnaldo Carvalho de Melo pos->filter, perf_evsel__name(pos), errno, 380c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 3818d3eca20SDavid Ahern rc = -1; 3828d3eca20SDavid Ahern goto out; 3830a102479SFrederic Weisbecker } 3840a102479SFrederic Weisbecker 3855d8bb1ecSMathieu Poirier if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) { 38662d94b00SArnaldo Carvalho de Melo pr_err("failed to set config \"%s\" on event %s with %d (%s)\n", 3875d8bb1ecSMathieu Poirier err_term->val.drv_cfg, perf_evsel__name(pos), errno, 3885d8bb1ecSMathieu Poirier str_error_r(errno, msg, sizeof(msg))); 3895d8bb1ecSMathieu Poirier rc = -1; 3905d8bb1ecSMathieu Poirier goto out; 3915d8bb1ecSMathieu Poirier } 3925d8bb1ecSMathieu Poirier 393cda57a8cSWang Nan rc = record__mmap(rec); 394cda57a8cSWang Nan if (rc) 3958d3eca20SDavid Ahern goto out; 3960a27d7f9SArnaldo Carvalho de Melo 397a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 3987b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 3998d3eca20SDavid Ahern out: 4008d3eca20SDavid Ahern return rc; 401a91e5431SArnaldo Carvalho de Melo } 402a91e5431SArnaldo Carvalho de Melo 403e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 404e3d59112SNamhyung Kim union perf_event *event, 405e3d59112SNamhyung Kim struct perf_sample *sample, 406e3d59112SNamhyung Kim struct perf_evsel *evsel, 407e3d59112SNamhyung Kim struct machine *machine) 408e3d59112SNamhyung Kim { 409e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 410e3d59112SNamhyung Kim 411e3d59112SNamhyung Kim rec->samples++; 412e3d59112SNamhyung Kim 413e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 414e3d59112SNamhyung Kim } 415e3d59112SNamhyung Kim 4168c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 4176122e4e4SArnaldo Carvalho de Melo { 4188ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 419f5fc1412SJiri Olsa struct perf_session *session = rec->session; 4206122e4e4SArnaldo Carvalho de Melo 4218ceb41d7SJiri Olsa if (data->size == 0) 4229f591fd7SArnaldo Carvalho de Melo return 0; 4239f591fd7SArnaldo Carvalho de Melo 42400dc8657SNamhyung Kim /* 42500dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 42600dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 42700dc8657SNamhyung Kim * we prefer the vmlinux path like 42800dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 42900dc8657SNamhyung Kim * 43000dc8657SNamhyung Kim * rather than build-id path (in debug directory). 43100dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 43200dc8657SNamhyung Kim */ 43300dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 43400dc8657SNamhyung Kim 4356156681bSNamhyung Kim /* 4366156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 4376156681bSNamhyung Kim * so no need to process samples. 4386156681bSNamhyung Kim */ 4396156681bSNamhyung Kim if (rec->buildid_all) 4406156681bSNamhyung Kim rec->tool.sample = NULL; 4416156681bSNamhyung Kim 442b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 4436122e4e4SArnaldo Carvalho de Melo } 4446122e4e4SArnaldo Carvalho de Melo 4458115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 446a1645ce1SZhang, Yanmin { 447a1645ce1SZhang, Yanmin int err; 44845694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 449a1645ce1SZhang, Yanmin /* 450a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 451a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 452a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 453a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 454a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 455a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 456a1645ce1SZhang, Yanmin */ 45745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 458743eb868SArnaldo Carvalho de Melo machine); 459a1645ce1SZhang, Yanmin if (err < 0) 460a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 46123346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 462a1645ce1SZhang, Yanmin 463a1645ce1SZhang, Yanmin /* 464a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 465a1645ce1SZhang, Yanmin * have no _text sometimes. 466a1645ce1SZhang, Yanmin */ 46745694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 4680ae617beSAdrian Hunter machine); 469a1645ce1SZhang, Yanmin if (err < 0) 470a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 47123346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 472a1645ce1SZhang, Yanmin } 473a1645ce1SZhang, Yanmin 47498402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 47598402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 47698402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 47798402807SFrederic Weisbecker }; 47898402807SFrederic Weisbecker 479a4ea0ec4SWang Nan static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, 480a4ea0ec4SWang Nan bool backward) 48198402807SFrederic Weisbecker { 482dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 4830e2e63ddSPeter Zijlstra int i; 4848d3eca20SDavid Ahern int rc = 0; 485a4ea0ec4SWang Nan struct perf_mmap *maps; 48698402807SFrederic Weisbecker 487cb21686bSWang Nan if (!evlist) 488cb21686bSWang Nan return 0; 489ef149c25SAdrian Hunter 490b2cb615dSWang Nan maps = backward ? evlist->backward_mmap : evlist->mmap; 491a4ea0ec4SWang Nan if (!maps) 492a4ea0ec4SWang Nan return 0; 493cb21686bSWang Nan 49454cc54deSWang Nan if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 49554cc54deSWang Nan return 0; 49654cc54deSWang Nan 497a4ea0ec4SWang Nan for (i = 0; i < evlist->nr_mmaps; i++) { 498a4ea0ec4SWang Nan struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 499a4ea0ec4SWang Nan 500a4ea0ec4SWang Nan if (maps[i].base) { 501d37f1586SArnaldo Carvalho de Melo if (perf_mmap__push(&maps[i], evlist->overwrite, backward, rec, record__pushfn) != 0) { 5028d3eca20SDavid Ahern rc = -1; 5038d3eca20SDavid Ahern goto out; 5048d3eca20SDavid Ahern } 5058d3eca20SDavid Ahern } 506ef149c25SAdrian Hunter 5072dd6d8a1SAdrian Hunter if (mm->base && !rec->opts.auxtrace_snapshot_mode && 508ef149c25SAdrian Hunter record__auxtrace_mmap_read(rec, mm) != 0) { 509ef149c25SAdrian Hunter rc = -1; 510ef149c25SAdrian Hunter goto out; 511ef149c25SAdrian Hunter } 51298402807SFrederic Weisbecker } 51398402807SFrederic Weisbecker 514dcabb507SJiri Olsa /* 515dcabb507SJiri Olsa * Mark the round finished in case we wrote 516dcabb507SJiri Olsa * at least one event. 517dcabb507SJiri Olsa */ 518dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 5198c6f45a7SArnaldo Carvalho de Melo rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 5208d3eca20SDavid Ahern 52154cc54deSWang Nan if (backward) 52254cc54deSWang Nan perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 5238d3eca20SDavid Ahern out: 5248d3eca20SDavid Ahern return rc; 52598402807SFrederic Weisbecker } 52698402807SFrederic Weisbecker 527cb21686bSWang Nan static int record__mmap_read_all(struct record *rec) 528cb21686bSWang Nan { 529cb21686bSWang Nan int err; 530cb21686bSWang Nan 531a4ea0ec4SWang Nan err = record__mmap_read_evlist(rec, rec->evlist, false); 532cb21686bSWang Nan if (err) 533cb21686bSWang Nan return err; 534cb21686bSWang Nan 53505737464SWang Nan return record__mmap_read_evlist(rec, rec->evlist, true); 536cb21686bSWang Nan } 537cb21686bSWang Nan 5388c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 53957706abcSDavid Ahern { 54057706abcSDavid Ahern struct perf_session *session = rec->session; 54157706abcSDavid Ahern int feat; 54257706abcSDavid Ahern 54357706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 54457706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 54557706abcSDavid Ahern 54657706abcSDavid Ahern if (rec->no_buildid) 54757706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 54857706abcSDavid Ahern 5493e2be2daSArnaldo Carvalho de Melo if (!have_tracepoints(&rec->evlist->entries)) 55057706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 55157706abcSDavid Ahern 55257706abcSDavid Ahern if (!rec->opts.branch_stack) 55357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 554ef149c25SAdrian Hunter 555ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 556ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 557ffa517adSJiri Olsa 558ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 55957706abcSDavid Ahern } 56057706abcSDavid Ahern 561e1ab48baSWang Nan static void 562e1ab48baSWang Nan record__finish_output(struct record *rec) 563e1ab48baSWang Nan { 5648ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 5658ceb41d7SJiri Olsa int fd = perf_data__fd(data); 566e1ab48baSWang Nan 5678ceb41d7SJiri Olsa if (data->is_pipe) 568e1ab48baSWang Nan return; 569e1ab48baSWang Nan 570e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 5718ceb41d7SJiri Olsa data->size = lseek(perf_data__fd(data), 0, SEEK_CUR); 572e1ab48baSWang Nan 573e1ab48baSWang Nan if (!rec->no_buildid) { 574e1ab48baSWang Nan process_buildids(rec); 575e1ab48baSWang Nan 576e1ab48baSWang Nan if (rec->buildid_all) 577e1ab48baSWang Nan dsos__hit_all(rec->session); 578e1ab48baSWang Nan } 579e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 580e1ab48baSWang Nan 581e1ab48baSWang Nan return; 582e1ab48baSWang Nan } 583e1ab48baSWang Nan 5844ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 585be7b0c9eSWang Nan { 5869d6aae72SArnaldo Carvalho de Melo int err; 5879d6aae72SArnaldo Carvalho de Melo struct thread_map *thread_map; 588be7b0c9eSWang Nan 5894ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 5904ea648aeSWang Nan return 0; 5914ea648aeSWang Nan 5929d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 5939d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL) 5949d6aae72SArnaldo Carvalho de Melo return -1; 5959d6aae72SArnaldo Carvalho de Melo 5969d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 597be7b0c9eSWang Nan process_synthesized_event, 598be7b0c9eSWang Nan &rec->session->machines.host, 599be7b0c9eSWang Nan rec->opts.sample_address, 600be7b0c9eSWang Nan rec->opts.proc_map_timeout); 6019d6aae72SArnaldo Carvalho de Melo thread_map__put(thread_map); 6029d6aae72SArnaldo Carvalho de Melo return err; 603be7b0c9eSWang Nan } 604be7b0c9eSWang Nan 6054ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 6063c1cb7e3SWang Nan 607ecfd7a9cSWang Nan static int 608ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 609ecfd7a9cSWang Nan { 6108ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 611ecfd7a9cSWang Nan int fd, err; 612ecfd7a9cSWang Nan 613ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 614ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 615ecfd7a9cSWang Nan 6164ea648aeSWang Nan record__synthesize(rec, true); 6174ea648aeSWang Nan if (target__none(&rec->opts.target)) 6184ea648aeSWang Nan record__synthesize_workload(rec, true); 6194ea648aeSWang Nan 620ecfd7a9cSWang Nan rec->samples = 0; 621ecfd7a9cSWang Nan record__finish_output(rec); 622ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 623ecfd7a9cSWang Nan if (err) { 624ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 625ecfd7a9cSWang Nan return -EINVAL; 626ecfd7a9cSWang Nan } 627ecfd7a9cSWang Nan 6288ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp, 629ecfd7a9cSWang Nan rec->session->header.data_offset, 630ecfd7a9cSWang Nan at_exit); 631ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 632ecfd7a9cSWang Nan rec->bytes_written = 0; 633ecfd7a9cSWang Nan rec->session->header.data_size = 0; 634ecfd7a9cSWang Nan } 635ecfd7a9cSWang Nan 636ecfd7a9cSWang Nan if (!quiet) 637ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 638eae8ad80SJiri Olsa data->file.path, timestamp); 6393c1cb7e3SWang Nan 6403c1cb7e3SWang Nan /* Output tracking events */ 641be7b0c9eSWang Nan if (!at_exit) { 6424ea648aeSWang Nan record__synthesize(rec, false); 6433c1cb7e3SWang Nan 644be7b0c9eSWang Nan /* 645be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 646be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 647be7b0c9eSWang Nan * generate tracking events because there's no thread_map 648be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 649be7b0c9eSWang Nan * contain map and comm information. 650be7b0c9eSWang Nan * Create a fake thread_map and directly call 651be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 652be7b0c9eSWang Nan */ 653be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 6544ea648aeSWang Nan record__synthesize_workload(rec, false); 655be7b0c9eSWang Nan } 656ecfd7a9cSWang Nan return fd; 657ecfd7a9cSWang Nan } 658ecfd7a9cSWang Nan 659f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 660f33cbe72SArnaldo Carvalho de Melo 661f33cbe72SArnaldo Carvalho de Melo /* 662f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 663f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 664f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 665f33cbe72SArnaldo Carvalho de Melo */ 66645604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 66745604710SNamhyung Kim siginfo_t *info, 668f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 669f33cbe72SArnaldo Carvalho de Melo { 670f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 671f33cbe72SArnaldo Carvalho de Melo done = 1; 672f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 673f33cbe72SArnaldo Carvalho de Melo } 674f33cbe72SArnaldo Carvalho de Melo 6752dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 676bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig); 6772dd6d8a1SAdrian Hunter 67846bc29b9SAdrian Hunter int __weak 67946bc29b9SAdrian Hunter perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused, 68046bc29b9SAdrian Hunter struct perf_tool *tool __maybe_unused, 68146bc29b9SAdrian Hunter perf_event__handler_t process __maybe_unused, 68246bc29b9SAdrian Hunter struct machine *machine __maybe_unused) 68346bc29b9SAdrian Hunter { 68446bc29b9SAdrian Hunter return 0; 68546bc29b9SAdrian Hunter } 68646bc29b9SAdrian Hunter 687ee667f94SWang Nan static const struct perf_event_mmap_page * 688ee667f94SWang Nan perf_evlist__pick_pc(struct perf_evlist *evlist) 689ee667f94SWang Nan { 690b2cb615dSWang Nan if (evlist) { 691b2cb615dSWang Nan if (evlist->mmap && evlist->mmap[0].base) 692ee667f94SWang Nan return evlist->mmap[0].base; 693b2cb615dSWang Nan if (evlist->backward_mmap && evlist->backward_mmap[0].base) 694b2cb615dSWang Nan return evlist->backward_mmap[0].base; 695b2cb615dSWang Nan } 696ee667f94SWang Nan return NULL; 697ee667f94SWang Nan } 698ee667f94SWang Nan 699c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 700c45628b0SWang Nan { 701ee667f94SWang Nan const struct perf_event_mmap_page *pc; 702ee667f94SWang Nan 703ee667f94SWang Nan pc = perf_evlist__pick_pc(rec->evlist); 704ee667f94SWang Nan if (pc) 705ee667f94SWang Nan return pc; 706c45628b0SWang Nan return NULL; 707c45628b0SWang Nan } 708c45628b0SWang Nan 7094ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 710c45c86ebSWang Nan { 711c45c86ebSWang Nan struct perf_session *session = rec->session; 712c45c86ebSWang Nan struct machine *machine = &session->machines.host; 7138ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 714c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 715c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 7168ceb41d7SJiri Olsa int fd = perf_data__fd(data); 717c45c86ebSWang Nan int err = 0; 718c45c86ebSWang Nan 7194ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 7204ea648aeSWang Nan return 0; 7214ea648aeSWang Nan 7228ceb41d7SJiri Olsa if (data->is_pipe) { 723e9def1b2SDavid Carrillo-Cisneros err = perf_event__synthesize_features( 724e9def1b2SDavid Carrillo-Cisneros tool, session, rec->evlist, process_synthesized_event); 725e9def1b2SDavid Carrillo-Cisneros if (err < 0) { 726e9def1b2SDavid Carrillo-Cisneros pr_err("Couldn't synthesize features.\n"); 727e9def1b2SDavid Carrillo-Cisneros return err; 728e9def1b2SDavid Carrillo-Cisneros } 729e9def1b2SDavid Carrillo-Cisneros 730c45c86ebSWang Nan err = perf_event__synthesize_attrs(tool, session, 731c45c86ebSWang Nan process_synthesized_event); 732c45c86ebSWang Nan if (err < 0) { 733c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 734c45c86ebSWang Nan goto out; 735c45c86ebSWang Nan } 736c45c86ebSWang Nan 737c45c86ebSWang Nan if (have_tracepoints(&rec->evlist->entries)) { 738c45c86ebSWang Nan /* 739c45c86ebSWang Nan * FIXME err <= 0 here actually means that 740c45c86ebSWang Nan * there were no tracepoints so its not really 741c45c86ebSWang Nan * an error, just that we don't need to 742c45c86ebSWang Nan * synthesize anything. We really have to 743c45c86ebSWang Nan * return this more properly and also 744c45c86ebSWang Nan * propagate errors that now are calling die() 745c45c86ebSWang Nan */ 746c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 747c45c86ebSWang Nan process_synthesized_event); 748c45c86ebSWang Nan if (err <= 0) { 749c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 750c45c86ebSWang Nan goto out; 751c45c86ebSWang Nan } 752c45c86ebSWang Nan rec->bytes_written += err; 753c45c86ebSWang Nan } 754c45c86ebSWang Nan } 755c45c86ebSWang Nan 756c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 75746bc29b9SAdrian Hunter process_synthesized_event, machine); 75846bc29b9SAdrian Hunter if (err) 75946bc29b9SAdrian Hunter goto out; 76046bc29b9SAdrian Hunter 761c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 762c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 763c45c86ebSWang Nan session, process_synthesized_event); 764c45c86ebSWang Nan if (err) 765c45c86ebSWang Nan goto out; 766c45c86ebSWang Nan } 767c45c86ebSWang Nan 768c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 769c45c86ebSWang Nan machine); 770c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 771c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 772c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 773c45c86ebSWang Nan 774c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 775c45c86ebSWang Nan machine); 776c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 777c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 778c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 779c45c86ebSWang Nan 780c45c86ebSWang Nan if (perf_guest) { 781c45c86ebSWang Nan machines__process_guests(&session->machines, 782c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 783c45c86ebSWang Nan } 784c45c86ebSWang Nan 785c45c86ebSWang Nan err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, 786c45c86ebSWang Nan process_synthesized_event, opts->sample_address, 787340b47f5SKan Liang opts->proc_map_timeout, 1); 788c45c86ebSWang Nan out: 789c45c86ebSWang Nan return err; 790c45c86ebSWang Nan } 791c45c86ebSWang Nan 7928c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 79386470930SIngo Molnar { 79457706abcSDavid Ahern int err; 79545604710SNamhyung Kim int status = 0; 7968b412664SPeter Zijlstra unsigned long waking = 0; 79746be604bSZhang, Yanmin const bool forks = argc > 0; 79823346f21SArnaldo Carvalho de Melo struct machine *machine; 79945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 800b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 8018ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 802d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 8036dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 80442aa276fSNamhyung Kim int fd; 80586470930SIngo Molnar 806d20deb64SArnaldo Carvalho de Melo rec->progname = argv[0]; 80733e49ea7SAndi Kleen 80845604710SNamhyung Kim atexit(record__sig_exit); 809f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 810f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 811804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 812a074865eSWang Nan signal(SIGSEGV, sigsegv_handler); 813c0bdc1c4SWang Nan 814f3b3614aSHari Bathini if (rec->opts.record_namespaces) 815f3b3614aSHari Bathini tool->namespace_events = true; 816f3b3614aSHari Bathini 817dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 8182dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 8193c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 8205f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 821dc0c6127SJiri Olsa if (rec->switch_output.enabled) 8223c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 823c0bdc1c4SWang Nan } else { 8242dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 825c0bdc1c4SWang Nan } 826f5970550SPeter Zijlstra 8278ceb41d7SJiri Olsa session = perf_session__new(data, false, tool); 82894c744b6SArnaldo Carvalho de Melo if (session == NULL) { 829ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 830a9a70bbcSArnaldo Carvalho de Melo return -1; 831a9a70bbcSArnaldo Carvalho de Melo } 832a9a70bbcSArnaldo Carvalho de Melo 8338ceb41d7SJiri Olsa fd = perf_data__fd(data); 834d20deb64SArnaldo Carvalho de Melo rec->session = session; 835d20deb64SArnaldo Carvalho de Melo 8368c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 837330aa675SStephane Eranian 838d4db3f16SArnaldo Carvalho de Melo if (forks) { 8393e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 8408ceb41d7SJiri Olsa argv, data->is_pipe, 841735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 84235b9d88eSArnaldo Carvalho de Melo if (err < 0) { 84335b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 84445604710SNamhyung Kim status = err; 84535b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 846856e9660SPeter Zijlstra } 847856e9660SPeter Zijlstra } 848856e9660SPeter Zijlstra 8498c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 8508d3eca20SDavid Ahern err = -1; 85145604710SNamhyung Kim goto out_child; 8528d3eca20SDavid Ahern } 85386470930SIngo Molnar 8548690a2a7SWang Nan err = bpf__apply_obj_config(); 8558690a2a7SWang Nan if (err) { 8568690a2a7SWang Nan char errbuf[BUFSIZ]; 8578690a2a7SWang Nan 8588690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 8598690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 8608690a2a7SWang Nan errbuf); 8618690a2a7SWang Nan goto out_child; 8628690a2a7SWang Nan } 8638690a2a7SWang Nan 864cca8482cSAdrian Hunter /* 865cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 866cca8482cSAdrian Hunter * evlist. 867cca8482cSAdrian Hunter */ 868cca8482cSAdrian Hunter if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { 869cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 870cca8482cSAdrian Hunter rec->tool.ordered_events = false; 871cca8482cSAdrian Hunter } 872cca8482cSAdrian Hunter 8733e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 874a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 875a8bb559bSNamhyung Kim 8768ceb41d7SJiri Olsa if (data->is_pipe) { 87742aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 878529870e3STom Zanussi if (err < 0) 87945604710SNamhyung Kim goto out_child; 880563aecb2SJiri Olsa } else { 88142aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 882d5eed904SArnaldo Carvalho de Melo if (err < 0) 88345604710SNamhyung Kim goto out_child; 884d5eed904SArnaldo Carvalho de Melo } 8857c6a1c65SPeter Zijlstra 886d3665498SDavid Ahern if (!rec->no_buildid 887e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 888d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 889e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 8908d3eca20SDavid Ahern err = -1; 89145604710SNamhyung Kim goto out_child; 892e20960c0SRobert Richter } 893e20960c0SRobert Richter 89434ba5122SArnaldo Carvalho de Melo machine = &session->machines.host; 895743eb868SArnaldo Carvalho de Melo 8964ea648aeSWang Nan err = record__synthesize(rec, false); 897c45c86ebSWang Nan if (err < 0) 89845604710SNamhyung Kim goto out_child; 8998d3eca20SDavid Ahern 900d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 90186470930SIngo Molnar struct sched_param param; 90286470930SIngo Molnar 903d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 90486470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 9056beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 9068d3eca20SDavid Ahern err = -1; 90745604710SNamhyung Kim goto out_child; 90886470930SIngo Molnar } 90986470930SIngo Molnar } 91086470930SIngo Molnar 911774cb499SJiri Olsa /* 912774cb499SJiri Olsa * When perf is starting the traced process, all the events 913774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 914774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 915774cb499SJiri Olsa */ 9166619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 9173e2be2daSArnaldo Carvalho de Melo perf_evlist__enable(rec->evlist); 918764e16a3SDavid Ahern 919856e9660SPeter Zijlstra /* 920856e9660SPeter Zijlstra * Let the child rip 921856e9660SPeter Zijlstra */ 922e803cf97SNamhyung Kim if (forks) { 923e5bed564SNamhyung Kim union perf_event *event; 924e907caf3SHari Bathini pid_t tgid; 925e5bed564SNamhyung Kim 926e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 927e5bed564SNamhyung Kim if (event == NULL) { 928e5bed564SNamhyung Kim err = -ENOMEM; 929e5bed564SNamhyung Kim goto out_child; 930e5bed564SNamhyung Kim } 931e5bed564SNamhyung Kim 932e803cf97SNamhyung Kim /* 933e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 934e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 935e803cf97SNamhyung Kim * cannot see a correct process name for those events. 936e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 937e803cf97SNamhyung Kim */ 938e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event, 939e803cf97SNamhyung Kim rec->evlist->workload.pid, 940e803cf97SNamhyung Kim process_synthesized_event, 941e803cf97SNamhyung Kim machine); 942e5bed564SNamhyung Kim free(event); 943e803cf97SNamhyung Kim 944e907caf3SHari Bathini if (tgid == -1) 945e907caf3SHari Bathini goto out_child; 946e907caf3SHari Bathini 947e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) + 948e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 949e907caf3SHari Bathini machine->id_hdr_size); 950e907caf3SHari Bathini if (event == NULL) { 951e907caf3SHari Bathini err = -ENOMEM; 952e907caf3SHari Bathini goto out_child; 953e907caf3SHari Bathini } 954e907caf3SHari Bathini 955e907caf3SHari Bathini /* 956e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified. 957e907caf3SHari Bathini */ 958e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event, 959e907caf3SHari Bathini rec->evlist->workload.pid, 960e907caf3SHari Bathini tgid, process_synthesized_event, 961e907caf3SHari Bathini machine); 962e907caf3SHari Bathini free(event); 963e907caf3SHari Bathini 9643e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 965e803cf97SNamhyung Kim } 966856e9660SPeter Zijlstra 9676619a53eSAndi Kleen if (opts->initial_delay) { 9680693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 9696619a53eSAndi Kleen perf_evlist__enable(rec->evlist); 9706619a53eSAndi Kleen } 9716619a53eSAndi Kleen 9725f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 9733c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 974a074865eSWang Nan perf_hooks__invoke_record_start(); 975649c48a9SPeter Zijlstra for (;;) { 9769f065194SYang Shi unsigned long long hits = rec->samples; 97786470930SIngo Molnar 97805737464SWang Nan /* 97905737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 98005737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 98105737464SWang Nan * hits != rec->samples in previous round. 98205737464SWang Nan * 98305737464SWang Nan * perf_evlist__toggle_bkw_mmap ensure we never 98405737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 98505737464SWang Nan */ 98605737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 98705737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 98805737464SWang Nan 9898c6f45a7SArnaldo Carvalho de Melo if (record__mmap_read_all(rec) < 0) { 9905f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 9913c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 9928d3eca20SDavid Ahern err = -1; 99345604710SNamhyung Kim goto out_child; 9948d3eca20SDavid Ahern } 99586470930SIngo Molnar 9962dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 9972dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 9985f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 9992dd6d8a1SAdrian Hunter record__read_auxtrace_snapshot(rec); 10005f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 10012dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 10022dd6d8a1SAdrian Hunter err = -1; 10032dd6d8a1SAdrian Hunter goto out_child; 10042dd6d8a1SAdrian Hunter } 10052dd6d8a1SAdrian Hunter } 10062dd6d8a1SAdrian Hunter 10073c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 100805737464SWang Nan /* 100905737464SWang Nan * If switch_output_trigger is hit, the data in 101005737464SWang Nan * overwritable ring buffer should have been collected, 101105737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 101205737464SWang Nan * 101305737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 101405737464SWang Nan * record__mmap_read_all() didn't collect data from 101505737464SWang Nan * overwritable ring buffer. Read again. 101605737464SWang Nan */ 101705737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 101805737464SWang Nan continue; 10193c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 10203c1cb7e3SWang Nan 102105737464SWang Nan /* 102205737464SWang Nan * Reenable events in overwrite ring buffer after 102305737464SWang Nan * record__mmap_read_all(): we should have collected 102405737464SWang Nan * data from it. 102505737464SWang Nan */ 102605737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 102705737464SWang Nan 10283c1cb7e3SWang Nan if (!quiet) 10293c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 10303c1cb7e3SWang Nan waking); 10313c1cb7e3SWang Nan waking = 0; 10323c1cb7e3SWang Nan fd = record__switch_output(rec, false); 10333c1cb7e3SWang Nan if (fd < 0) { 10343c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 10353c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 10363c1cb7e3SWang Nan err = fd; 10373c1cb7e3SWang Nan goto out_child; 10383c1cb7e3SWang Nan } 1039bfacbe3bSJiri Olsa 1040bfacbe3bSJiri Olsa /* re-arm the alarm */ 1041bfacbe3bSJiri Olsa if (rec->switch_output.time) 1042bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 10433c1cb7e3SWang Nan } 10443c1cb7e3SWang Nan 1045d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 10466dcf45efSArnaldo Carvalho de Melo if (done || draining) 1047649c48a9SPeter Zijlstra break; 1048f66a889dSArnaldo Carvalho de Melo err = perf_evlist__poll(rec->evlist, -1); 1049a515114fSJiri Olsa /* 1050a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1051a515114fSJiri Olsa * number of returned events and interrupt error. 1052a515114fSJiri Olsa */ 1053a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 105445604710SNamhyung Kim err = 0; 10558b412664SPeter Zijlstra waking++; 10566dcf45efSArnaldo Carvalho de Melo 10576dcf45efSArnaldo Carvalho de Melo if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 10586dcf45efSArnaldo Carvalho de Melo draining = true; 10598b412664SPeter Zijlstra } 10608b412664SPeter Zijlstra 1061774cb499SJiri Olsa /* 1062774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1063774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1064774cb499SJiri Olsa * disable events in this case. 1065774cb499SJiri Olsa */ 1066602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 10675f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 10683e2be2daSArnaldo Carvalho de Melo perf_evlist__disable(rec->evlist); 10692711926aSJiri Olsa disabled = true; 10702711926aSJiri Olsa } 10718b412664SPeter Zijlstra } 10725f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 10733c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 10748b412664SPeter Zijlstra 1075f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 107635550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 1077c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 1078f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 1079f33cbe72SArnaldo Carvalho de Melo err = -1; 108045604710SNamhyung Kim goto out_child; 1081f33cbe72SArnaldo Carvalho de Melo } 1082f33cbe72SArnaldo Carvalho de Melo 1083e3d59112SNamhyung Kim if (!quiet) 10848b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 108586470930SIngo Molnar 10864ea648aeSWang Nan if (target__none(&rec->opts.target)) 10874ea648aeSWang Nan record__synthesize_workload(rec, true); 10884ea648aeSWang Nan 108945604710SNamhyung Kim out_child: 109045604710SNamhyung Kim if (forks) { 109145604710SNamhyung Kim int exit_status; 109245604710SNamhyung Kim 109345604710SNamhyung Kim if (!child_finished) 109445604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 109545604710SNamhyung Kim 109645604710SNamhyung Kim wait(&exit_status); 109745604710SNamhyung Kim 109845604710SNamhyung Kim if (err < 0) 109945604710SNamhyung Kim status = err; 110045604710SNamhyung Kim else if (WIFEXITED(exit_status)) 110145604710SNamhyung Kim status = WEXITSTATUS(exit_status); 110245604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 110345604710SNamhyung Kim signr = WTERMSIG(exit_status); 110445604710SNamhyung Kim } else 110545604710SNamhyung Kim status = err; 110645604710SNamhyung Kim 11074ea648aeSWang Nan record__synthesize(rec, true); 1108e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 1109e3d59112SNamhyung Kim rec->samples = 0; 1110e3d59112SNamhyung Kim 1111ecfd7a9cSWang Nan if (!err) { 1112ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 1113e1ab48baSWang Nan record__finish_output(rec); 1114ecfd7a9cSWang Nan } else { 1115ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1116ecfd7a9cSWang Nan if (fd < 0) { 1117ecfd7a9cSWang Nan status = fd; 1118ecfd7a9cSWang Nan goto out_delete_session; 1119ecfd7a9cSWang Nan } 1120ecfd7a9cSWang Nan } 1121ecfd7a9cSWang Nan } 112239d17dacSArnaldo Carvalho de Melo 1123a074865eSWang Nan perf_hooks__invoke_record_end(); 1124a074865eSWang Nan 1125e3d59112SNamhyung Kim if (!err && !quiet) { 1126e3d59112SNamhyung Kim char samples[128]; 1127ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1128ecfd7a9cSWang Nan ".<timestamp>" : ""; 1129e3d59112SNamhyung Kim 1130ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1131e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1132e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1133e3d59112SNamhyung Kim else 1134e3d59112SNamhyung Kim samples[0] = '\0'; 1135e3d59112SNamhyung Kim 1136ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 11378ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0, 1138eae8ad80SJiri Olsa data->file.path, postfix, samples); 1139e3d59112SNamhyung Kim } 1140e3d59112SNamhyung Kim 114139d17dacSArnaldo Carvalho de Melo out_delete_session: 114239d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 114345604710SNamhyung Kim return status; 114486470930SIngo Molnar } 114586470930SIngo Molnar 11460883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 114709b0fd45SJiri Olsa { 1148aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1149a601fdffSJiri Olsa 11500883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 115126d33022SJiri Olsa 11520883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 115309b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 11540883e820SArnaldo Carvalho de Melo callchain->dump_size); 11550883e820SArnaldo Carvalho de Melo } 11560883e820SArnaldo Carvalho de Melo 11570883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 11580883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 11590883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 11600883e820SArnaldo Carvalho de Melo { 11610883e820SArnaldo Carvalho de Melo int ret; 11620883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 11630883e820SArnaldo Carvalho de Melo 11640883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 11650883e820SArnaldo Carvalho de Melo if (unset) { 11660883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 11670883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 11680883e820SArnaldo Carvalho de Melo return 0; 11690883e820SArnaldo Carvalho de Melo } 11700883e820SArnaldo Carvalho de Melo 11710883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 11720883e820SArnaldo Carvalho de Melo if (!ret) { 11730883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 11740883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 11750883e820SArnaldo Carvalho de Melo record->sample_address = true; 11760883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 11770883e820SArnaldo Carvalho de Melo } 11780883e820SArnaldo Carvalho de Melo 11790883e820SArnaldo Carvalho de Melo return ret; 118009b0fd45SJiri Olsa } 118109b0fd45SJiri Olsa 1182c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 118309b0fd45SJiri Olsa const char *arg, 118409b0fd45SJiri Olsa int unset) 118509b0fd45SJiri Olsa { 11860883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 118726d33022SJiri Olsa } 118826d33022SJiri Olsa 1189c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 119009b0fd45SJiri Olsa const char *arg __maybe_unused, 119109b0fd45SJiri Olsa int unset __maybe_unused) 119209b0fd45SJiri Olsa { 11932ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 1194c421e80bSKan Liang 11952ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 119609b0fd45SJiri Olsa 11972ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 11982ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 1199eb853e80SJiri Olsa 12002ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 120109b0fd45SJiri Olsa return 0; 120209b0fd45SJiri Olsa } 120309b0fd45SJiri Olsa 1204eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 1205eb853e80SJiri Olsa { 12067a29c087SNamhyung Kim struct record *rec = cb; 12077a29c087SNamhyung Kim 12087a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 12097a29c087SNamhyung Kim if (!strcmp(value, "cache")) 12107a29c087SNamhyung Kim rec->no_buildid_cache = false; 12117a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 12127a29c087SNamhyung Kim rec->no_buildid_cache = true; 12137a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 12147a29c087SNamhyung Kim rec->no_buildid = true; 12157a29c087SNamhyung Kim else 12167a29c087SNamhyung Kim return -1; 12177a29c087SNamhyung Kim return 0; 12187a29c087SNamhyung Kim } 1219eb853e80SJiri Olsa if (!strcmp(var, "record.call-graph")) 12205a2e5e85SNamhyung Kim var = "call-graph.record-mode"; /* fall-through */ 1221eb853e80SJiri Olsa 1222eb853e80SJiri Olsa return perf_default_config(var, value, cb); 1223eb853e80SJiri Olsa } 1224eb853e80SJiri Olsa 1225814c8c38SPeter Zijlstra struct clockid_map { 1226814c8c38SPeter Zijlstra const char *name; 1227814c8c38SPeter Zijlstra int clockid; 1228814c8c38SPeter Zijlstra }; 1229814c8c38SPeter Zijlstra 1230814c8c38SPeter Zijlstra #define CLOCKID_MAP(n, c) \ 1231814c8c38SPeter Zijlstra { .name = n, .clockid = (c), } 1232814c8c38SPeter Zijlstra 1233814c8c38SPeter Zijlstra #define CLOCKID_END { .name = NULL, } 1234814c8c38SPeter Zijlstra 1235814c8c38SPeter Zijlstra 1236814c8c38SPeter Zijlstra /* 1237814c8c38SPeter Zijlstra * Add the missing ones, we need to build on many distros... 1238814c8c38SPeter Zijlstra */ 1239814c8c38SPeter Zijlstra #ifndef CLOCK_MONOTONIC_RAW 1240814c8c38SPeter Zijlstra #define CLOCK_MONOTONIC_RAW 4 1241814c8c38SPeter Zijlstra #endif 1242814c8c38SPeter Zijlstra #ifndef CLOCK_BOOTTIME 1243814c8c38SPeter Zijlstra #define CLOCK_BOOTTIME 7 1244814c8c38SPeter Zijlstra #endif 1245814c8c38SPeter Zijlstra #ifndef CLOCK_TAI 1246814c8c38SPeter Zijlstra #define CLOCK_TAI 11 1247814c8c38SPeter Zijlstra #endif 1248814c8c38SPeter Zijlstra 1249814c8c38SPeter Zijlstra static const struct clockid_map clockids[] = { 1250814c8c38SPeter Zijlstra /* available for all events, NMI safe */ 1251814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic", CLOCK_MONOTONIC), 1252814c8c38SPeter Zijlstra CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW), 1253814c8c38SPeter Zijlstra 1254814c8c38SPeter Zijlstra /* available for some events */ 1255814c8c38SPeter Zijlstra CLOCKID_MAP("realtime", CLOCK_REALTIME), 1256814c8c38SPeter Zijlstra CLOCKID_MAP("boottime", CLOCK_BOOTTIME), 1257814c8c38SPeter Zijlstra CLOCKID_MAP("tai", CLOCK_TAI), 1258814c8c38SPeter Zijlstra 1259814c8c38SPeter Zijlstra /* available for the lazy */ 1260814c8c38SPeter Zijlstra CLOCKID_MAP("mono", CLOCK_MONOTONIC), 1261814c8c38SPeter Zijlstra CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW), 1262814c8c38SPeter Zijlstra CLOCKID_MAP("real", CLOCK_REALTIME), 1263814c8c38SPeter Zijlstra CLOCKID_MAP("boot", CLOCK_BOOTTIME), 1264814c8c38SPeter Zijlstra 1265814c8c38SPeter Zijlstra CLOCKID_END, 1266814c8c38SPeter Zijlstra }; 1267814c8c38SPeter Zijlstra 1268814c8c38SPeter Zijlstra static int parse_clockid(const struct option *opt, const char *str, int unset) 1269814c8c38SPeter Zijlstra { 1270814c8c38SPeter Zijlstra struct record_opts *opts = (struct record_opts *)opt->value; 1271814c8c38SPeter Zijlstra const struct clockid_map *cm; 1272814c8c38SPeter Zijlstra const char *ostr = str; 1273814c8c38SPeter Zijlstra 1274814c8c38SPeter Zijlstra if (unset) { 1275814c8c38SPeter Zijlstra opts->use_clockid = 0; 1276814c8c38SPeter Zijlstra return 0; 1277814c8c38SPeter Zijlstra } 1278814c8c38SPeter Zijlstra 1279814c8c38SPeter Zijlstra /* no arg passed */ 1280814c8c38SPeter Zijlstra if (!str) 1281814c8c38SPeter Zijlstra return 0; 1282814c8c38SPeter Zijlstra 1283814c8c38SPeter Zijlstra /* no setting it twice */ 1284814c8c38SPeter Zijlstra if (opts->use_clockid) 1285814c8c38SPeter Zijlstra return -1; 1286814c8c38SPeter Zijlstra 1287814c8c38SPeter Zijlstra opts->use_clockid = true; 1288814c8c38SPeter Zijlstra 1289814c8c38SPeter Zijlstra /* if its a number, we're done */ 1290814c8c38SPeter Zijlstra if (sscanf(str, "%d", &opts->clockid) == 1) 1291814c8c38SPeter Zijlstra return 0; 1292814c8c38SPeter Zijlstra 1293814c8c38SPeter Zijlstra /* allow a "CLOCK_" prefix to the name */ 1294814c8c38SPeter Zijlstra if (!strncasecmp(str, "CLOCK_", 6)) 1295814c8c38SPeter Zijlstra str += 6; 1296814c8c38SPeter Zijlstra 1297814c8c38SPeter Zijlstra for (cm = clockids; cm->name; cm++) { 1298814c8c38SPeter Zijlstra if (!strcasecmp(str, cm->name)) { 1299814c8c38SPeter Zijlstra opts->clockid = cm->clockid; 1300814c8c38SPeter Zijlstra return 0; 1301814c8c38SPeter Zijlstra } 1302814c8c38SPeter Zijlstra } 1303814c8c38SPeter Zijlstra 1304814c8c38SPeter Zijlstra opts->use_clockid = false; 1305814c8c38SPeter Zijlstra ui__warning("unknown clockid %s, check man page\n", ostr); 1306814c8c38SPeter Zijlstra return -1; 1307814c8c38SPeter Zijlstra } 1308814c8c38SPeter Zijlstra 1309e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 1310e9db1310SAdrian Hunter const char *str, 1311e9db1310SAdrian Hunter int unset __maybe_unused) 1312e9db1310SAdrian Hunter { 1313e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 1314e9db1310SAdrian Hunter char *s, *p; 1315e9db1310SAdrian Hunter unsigned int mmap_pages; 1316e9db1310SAdrian Hunter int ret; 1317e9db1310SAdrian Hunter 1318e9db1310SAdrian Hunter if (!str) 1319e9db1310SAdrian Hunter return -EINVAL; 1320e9db1310SAdrian Hunter 1321e9db1310SAdrian Hunter s = strdup(str); 1322e9db1310SAdrian Hunter if (!s) 1323e9db1310SAdrian Hunter return -ENOMEM; 1324e9db1310SAdrian Hunter 1325e9db1310SAdrian Hunter p = strchr(s, ','); 1326e9db1310SAdrian Hunter if (p) 1327e9db1310SAdrian Hunter *p = '\0'; 1328e9db1310SAdrian Hunter 1329e9db1310SAdrian Hunter if (*s) { 1330e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 1331e9db1310SAdrian Hunter if (ret) 1332e9db1310SAdrian Hunter goto out_free; 1333e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 1334e9db1310SAdrian Hunter } 1335e9db1310SAdrian Hunter 1336e9db1310SAdrian Hunter if (!p) { 1337e9db1310SAdrian Hunter ret = 0; 1338e9db1310SAdrian Hunter goto out_free; 1339e9db1310SAdrian Hunter } 1340e9db1310SAdrian Hunter 1341e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 1342e9db1310SAdrian Hunter if (ret) 1343e9db1310SAdrian Hunter goto out_free; 1344e9db1310SAdrian Hunter 1345e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 1346e9db1310SAdrian Hunter 1347e9db1310SAdrian Hunter out_free: 1348e9db1310SAdrian Hunter free(s); 1349e9db1310SAdrian Hunter return ret; 1350e9db1310SAdrian Hunter } 1351e9db1310SAdrian Hunter 13520c582449SJiri Olsa static void switch_output_size_warn(struct record *rec) 13530c582449SJiri Olsa { 13540c582449SJiri Olsa u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages); 13550c582449SJiri Olsa struct switch_output *s = &rec->switch_output; 13560c582449SJiri Olsa 13570c582449SJiri Olsa wakeup_size /= 2; 13580c582449SJiri Olsa 13590c582449SJiri Olsa if (s->size < wakeup_size) { 13600c582449SJiri Olsa char buf[100]; 13610c582449SJiri Olsa 13620c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 13630c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than " 13640c582449SJiri Olsa "wakeup kernel buffer size (%s) " 13650c582449SJiri Olsa "expect bigger perf.data sizes\n", buf); 13660c582449SJiri Olsa } 13670c582449SJiri Olsa } 13680c582449SJiri Olsa 1369cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec) 1370cb4e1ebbSJiri Olsa { 1371cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output; 1372dc0c6127SJiri Olsa static struct parse_tag tags_size[] = { 1373dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 }, 1374dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 1375dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 1376dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 1377dc0c6127SJiri Olsa { .tag = 0 }, 1378dc0c6127SJiri Olsa }; 1379bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = { 1380bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 }, 1381bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 }, 1382bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 }, 1383bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 }, 1384bfacbe3bSJiri Olsa { .tag = 0 }, 1385bfacbe3bSJiri Olsa }; 1386dc0c6127SJiri Olsa unsigned long val; 1387cb4e1ebbSJiri Olsa 1388cb4e1ebbSJiri Olsa if (!s->set) 1389cb4e1ebbSJiri Olsa return 0; 1390cb4e1ebbSJiri Olsa 1391cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) { 1392cb4e1ebbSJiri Olsa s->signal = true; 1393cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n"); 1394dc0c6127SJiri Olsa goto enabled; 1395dc0c6127SJiri Olsa } 1396dc0c6127SJiri Olsa 1397dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size); 1398dc0c6127SJiri Olsa if (val != (unsigned long) -1) { 1399dc0c6127SJiri Olsa s->size = val; 1400dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str); 1401dc0c6127SJiri Olsa goto enabled; 1402cb4e1ebbSJiri Olsa } 1403cb4e1ebbSJiri Olsa 1404bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time); 1405bfacbe3bSJiri Olsa if (val != (unsigned long) -1) { 1406bfacbe3bSJiri Olsa s->time = val; 1407bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n", 1408bfacbe3bSJiri Olsa s->str, s->time); 1409bfacbe3bSJiri Olsa goto enabled; 1410bfacbe3bSJiri Olsa } 1411bfacbe3bSJiri Olsa 1412cb4e1ebbSJiri Olsa return -1; 1413dc0c6127SJiri Olsa 1414dc0c6127SJiri Olsa enabled: 1415dc0c6127SJiri Olsa rec->timestamp_filename = true; 1416dc0c6127SJiri Olsa s->enabled = true; 14170c582449SJiri Olsa 14180c582449SJiri Olsa if (s->size && !rec->opts.no_buffering) 14190c582449SJiri Olsa switch_output_size_warn(rec); 14200c582449SJiri Olsa 1421dc0c6127SJiri Olsa return 0; 1422cb4e1ebbSJiri Olsa } 1423cb4e1ebbSJiri Olsa 1424e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 142586470930SIngo Molnar "perf record [<options>] [<command>]", 142686470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 142786470930SIngo Molnar NULL 142886470930SIngo Molnar }; 1429e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 143086470930SIngo Molnar 1431d20deb64SArnaldo Carvalho de Melo /* 14328c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 14338c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 1434d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 1435d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 1436d20deb64SArnaldo Carvalho de Melo * 1437d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 1438d20deb64SArnaldo Carvalho de Melo * 1439d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 1440d20deb64SArnaldo Carvalho de Melo */ 14418c6f45a7SArnaldo Carvalho de Melo static struct record record = { 1442d20deb64SArnaldo Carvalho de Melo .opts = { 14438affc2b8SAndi Kleen .sample_time = true, 1444d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 1445d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 1446d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 1447447a6013SArnaldo Carvalho de Melo .freq = 4000, 1448d1cb9fceSNamhyung Kim .target = { 1449d1cb9fceSNamhyung Kim .uses_mmap = true, 14503aa5939dSAdrian Hunter .default_per_cpu = true, 1451d1cb9fceSNamhyung Kim }, 14529d9cad76SKan Liang .proc_map_timeout = 500, 1453d20deb64SArnaldo Carvalho de Melo }, 1454e3d59112SNamhyung Kim .tool = { 1455e3d59112SNamhyung Kim .sample = process_sample_event, 1456e3d59112SNamhyung Kim .fork = perf_event__process_fork, 1457cca8482cSAdrian Hunter .exit = perf_event__process_exit, 1458e3d59112SNamhyung Kim .comm = perf_event__process_comm, 1459f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces, 1460e3d59112SNamhyung Kim .mmap = perf_event__process_mmap, 1461e3d59112SNamhyung Kim .mmap2 = perf_event__process_mmap2, 1462cca8482cSAdrian Hunter .ordered_events = true, 1463e3d59112SNamhyung Kim }, 1464d20deb64SArnaldo Carvalho de Melo }; 14657865e817SFrederic Weisbecker 146676a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 146776a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 146861eaa3beSArnaldo Carvalho de Melo 14690aab2136SWang Nan static bool dry_run; 14700aab2136SWang Nan 1471d20deb64SArnaldo Carvalho de Melo /* 1472d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1473d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 1474b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 1475d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 1476d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 1477d20deb64SArnaldo Carvalho de Melo */ 1478efd21307SJiri Olsa static struct option __record_options[] = { 1479d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 148086470930SIngo Molnar "event selector. use 'perf list' to list available events", 1481f120f9d5SJiri Olsa parse_events_option), 1482d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 1483c171b552SLi Zefan "event filter", parse_filter), 14844ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 14854ba1faa1SWang Nan NULL, "don't record events from perf itself", 14864ba1faa1SWang Nan exclude_perf), 1487bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 1488d6d901c2SZhang, Yanmin "record events on existing process id"), 1489bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 1490d6d901c2SZhang, Yanmin "record events on existing thread id"), 1491d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 149286470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 1493509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 1494acac03faSKirill Smelkov "collect data without buffering"), 1495d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 1496daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 1497bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 149886470930SIngo Molnar "system-wide collection from all CPUs"), 1499bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 1500c45c6ea2SStephane Eranian "list of cpus to monitor"), 1501d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 1502eae8ad80SJiri Olsa OPT_STRING('o', "output", &record.data.file.path, "file", 150386470930SIngo Molnar "output file name"), 150469e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 150569e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 15062e6cdf99SStephane Eranian "child tasks do not inherit counters"), 15074ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 15084ea648aeSWang Nan "synthesize non-sample events at the end of output"), 1509626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1510d20deb64SArnaldo Carvalho de Melo OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1511e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1512e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 1513e9db1310SAdrian Hunter record__parse_mmap_pages), 1514d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 151543bece79SLin Ming "put the counters into a counter group"), 15162ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 151709b0fd45SJiri Olsa NULL, "enables call-graph recording" , 151809b0fd45SJiri Olsa &record_callchain_opt), 151909b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 152076a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 152109b0fd45SJiri Olsa &record_parse_callchain_opt), 1522c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 15233da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 1524b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 1525d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1526649c48a9SPeter Zijlstra "per thread counts"), 152756100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 15283b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 15293b0a5daaSKan Liang "Record the sample physical addresses"), 1530b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 15313abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 15323abebc55SAdrian Hunter &record.opts.sample_time_set, 15333abebc55SAdrian Hunter "Record the sample timestamps"), 153456100321SPeter Zijlstra OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), 1535d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 1536649c48a9SPeter Zijlstra "don't sample"), 1537d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 1538d2db9a98SWang Nan &record.no_buildid_cache_set, 1539a1ac1d3cSStephane Eranian "do not update the buildid cache"), 1540d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 1541d2db9a98SWang Nan &record.no_buildid_set, 1542baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 1543d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 1544023695d9SStephane Eranian "monitor event in cgroup name only", 1545023695d9SStephane Eranian parse_cgroups), 1546a6205a35SArnaldo Carvalho de Melo OPT_UINTEGER('D', "delay", &record.opts.initial_delay, 15476619a53eSAndi Kleen "ms to wait before starting measurement after program start"), 1548bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 1549bea03405SNamhyung Kim "user to profile"), 1550a5aabdacSStephane Eranian 1551a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 1552a5aabdacSStephane Eranian "branch any", "sample any taken branches", 1553a5aabdacSStephane Eranian parse_branch_stack), 1554a5aabdacSStephane Eranian 1555a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 1556a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 1557bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 155805484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 155905484298SAndi Kleen "sample by weight (on special events only)"), 1560475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 1561475eeab9SAndi Kleen "sample transaction flags (special events only)"), 15623aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 15633aa5939dSAdrian Hunter "use per-thread mmaps"), 1564bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 1565bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 1566bcc84ec6SStephane Eranian " use -I ? to list register names", parse_regs), 156784c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 156884c41742SAndi Kleen "sample selected machine registers on interrupt," 156984c41742SAndi Kleen " use -I ? to list register names", parse_regs), 157085c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 157185c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 1572814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 1573814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 1574814c8c38SPeter Zijlstra parse_clockid), 15752dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 15762dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 15779d9cad76SKan Liang OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout, 15789d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 1579f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 1580f3b3614aSHari Bathini "Record namespaces events"), 1581b757bb09SAdrian Hunter OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, 1582b757bb09SAdrian Hunter "Record context switch events"), 158385723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 158485723885SJiri Olsa "Configure all used events to run in kernel space.", 158585723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 158685723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 158785723885SJiri Olsa "Configure all used events to run in user space.", 158885723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 158971dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 159071dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 159171dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 159271dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 15937efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 15947efe0e03SHe Kuang "file", "vmlinux pathname"), 15956156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 15966156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 1597ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 1598ecfd7a9cSWang Nan "append timestamp to output filename"), 1599cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 1600bfacbe3bSJiri Olsa &record.switch_output.set, "signal,size,time", 1601bfacbe3bSJiri Olsa "Switch output when receive SIGUSR2 or cross size,time threshold", 1602dc0c6127SJiri Olsa "signal"), 16030aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 16040aab2136SWang Nan "Parse options then exit"), 160586470930SIngo Molnar OPT_END() 160686470930SIngo Molnar }; 160786470930SIngo Molnar 1608e5b2c207SNamhyung Kim struct option *record_options = __record_options; 1609e5b2c207SNamhyung Kim 1610b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv) 161186470930SIngo Molnar { 1612ef149c25SAdrian Hunter int err; 16138c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 161416ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 161586470930SIngo Molnar 161648e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 161748e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 161848e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 161948e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 162048e1cab1SWang Nan # undef set_nobuild 162148e1cab1SWang Nan #endif 162248e1cab1SWang Nan 16237efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 16247efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 16257efe0e03SHe Kuang # define REASON "NO_DWARF=1" 16267efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 16277efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 16287efe0e03SHe Kuang # else 16297efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 16307efe0e03SHe Kuang # endif 16317efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 16327efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 16337efe0e03SHe Kuang # undef set_nobuild 16347efe0e03SHe Kuang # undef REASON 16357efe0e03SHe Kuang #endif 16367efe0e03SHe Kuang 16373e2be2daSArnaldo Carvalho de Melo rec->evlist = perf_evlist__new(); 16383e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 1639361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 1640361c99a6SArnaldo Carvalho de Melo 1641ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec); 1642ecc4c561SArnaldo Carvalho de Melo if (err) 1643ecc4c561SArnaldo Carvalho de Melo return err; 1644eb853e80SJiri Olsa 1645bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 1646a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 164768ba3235SNamhyung Kim if (quiet) 164868ba3235SNamhyung Kim perf_quiet_option(); 1649483635a9SJiri Olsa 1650483635a9SJiri Olsa /* Make system wide (-a) the default target. */ 1651602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 1652483635a9SJiri Olsa rec->opts.target.system_wide = true; 165386470930SIngo Molnar 1654bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 1655c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 1656c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 1657c7118369SNamhyung Kim 1658023695d9SStephane Eranian } 1659b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 1660b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 1661c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 1662c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 1663c7118369SNamhyung Kim return -EINVAL; 1664b757bb09SAdrian Hunter } 1665023695d9SStephane Eranian 1666cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) { 1667cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0); 1668cb4e1ebbSJiri Olsa return -EINVAL; 1669cb4e1ebbSJiri Olsa } 1670cb4e1ebbSJiri Olsa 1671bfacbe3bSJiri Olsa if (rec->switch_output.time) { 1672bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler); 1673bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 1674bfacbe3bSJiri Olsa } 1675bfacbe3bSJiri Olsa 1676ef149c25SAdrian Hunter if (!rec->itr) { 1677ef149c25SAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 1678ef149c25SAdrian Hunter if (err) 16795c01ad60SAdrian Hunter goto out; 1680ef149c25SAdrian Hunter } 1681ef149c25SAdrian Hunter 16822dd6d8a1SAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 16832dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_opts); 16842dd6d8a1SAdrian Hunter if (err) 16855c01ad60SAdrian Hunter goto out; 16862dd6d8a1SAdrian Hunter 16871b36c03eSAdrian Hunter /* 16881b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address 16891b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters(). 16901b36c03eSAdrian Hunter */ 16911b36c03eSAdrian Hunter symbol_conf.allow_aliases = true; 16921b36c03eSAdrian Hunter 16931b36c03eSAdrian Hunter symbol__init(NULL); 16941b36c03eSAdrian Hunter 16951b36c03eSAdrian Hunter err = auxtrace_parse_filters(rec->evlist); 16961b36c03eSAdrian Hunter if (err) 16971b36c03eSAdrian Hunter goto out; 16981b36c03eSAdrian Hunter 16990aab2136SWang Nan if (dry_run) 17005c01ad60SAdrian Hunter goto out; 17010aab2136SWang Nan 1702d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 1703d7888573SWang Nan if (err) { 1704d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1705d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 1706d7888573SWang Nan errbuf); 17075c01ad60SAdrian Hunter goto out; 1708d7888573SWang Nan } 1709d7888573SWang Nan 1710ef149c25SAdrian Hunter err = -ENOMEM; 1711ef149c25SAdrian Hunter 1712ec80fde7SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict) 1713646aaea6SArnaldo Carvalho de Melo pr_warning( 1714646aaea6SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1715ec80fde7SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict.\n\n" 1716646aaea6SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 1717646aaea6SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 1718646aaea6SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 1719646aaea6SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1720646aaea6SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 1721ec80fde7SArnaldo Carvalho de Melo 17220c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 1723a1ac1d3cSStephane Eranian disable_buildid_cache(); 1724dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) { 17250c1d46a8SWang Nan /* 17260c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 17270c1d46a8SWang Nan * generation by default to reduce data file switching 17280c1d46a8SWang Nan * overhead. Still generate buildid if they are required 17290c1d46a8SWang Nan * explicitly using 17300c1d46a8SWang Nan * 173160437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \ 17320c1d46a8SWang Nan * --no-no-buildid-cache 17330c1d46a8SWang Nan * 17340c1d46a8SWang Nan * Following code equals to: 17350c1d46a8SWang Nan * 17360c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 17370c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 17380c1d46a8SWang Nan * disable_buildid_cache(); 17390c1d46a8SWang Nan */ 17400c1d46a8SWang Nan bool disable = true; 17410c1d46a8SWang Nan 17420c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 17430c1d46a8SWang Nan disable = false; 17440c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 17450c1d46a8SWang Nan disable = false; 17460c1d46a8SWang Nan if (disable) { 17470c1d46a8SWang Nan rec->no_buildid = true; 17480c1d46a8SWang Nan rec->no_buildid_cache = true; 17490c1d46a8SWang Nan disable_buildid_cache(); 17500c1d46a8SWang Nan } 17510c1d46a8SWang Nan } 1752655000e7SArnaldo Carvalho de Melo 17534ea648aeSWang Nan if (record.opts.overwrite) 17544ea648aeSWang Nan record.opts.tail_synthesize = true; 17554ea648aeSWang Nan 17563e2be2daSArnaldo Carvalho de Melo if (rec->evlist->nr_entries == 0 && 17574b4cd503SArnaldo Carvalho de Melo __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { 175869aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 1759394c01edSAdrian Hunter goto out; 1760bbd36e5eSPeter Zijlstra } 176186470930SIngo Molnar 176269e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 176369e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 176469e7e5b0SAdrian Hunter 1765602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 176616ad2ffbSNamhyung Kim if (err) { 1767602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 176816ad2ffbSNamhyung Kim ui__warning("%s", errbuf); 176916ad2ffbSNamhyung Kim } 17704bd0f2d2SNamhyung Kim 1771602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 177216ad2ffbSNamhyung Kim if (err) { 177316ad2ffbSNamhyung Kim int saved_errno = errno; 177416ad2ffbSNamhyung Kim 1775602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 17763780f488SNamhyung Kim ui__error("%s", errbuf); 177716ad2ffbSNamhyung Kim 177816ad2ffbSNamhyung Kim err = -saved_errno; 1779394c01edSAdrian Hunter goto out; 178016ad2ffbSNamhyung Kim } 17810d37aa34SArnaldo Carvalho de Melo 178223dc4f15SJiri Olsa /* Enable ignoring missing threads when -u option is defined. */ 178323dc4f15SJiri Olsa rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX; 178423dc4f15SJiri Olsa 178516ad2ffbSNamhyung Kim err = -ENOMEM; 17863e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 1787dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 178869aad6f1SArnaldo Carvalho de Melo 1789ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1790ef149c25SAdrian Hunter if (err) 1791394c01edSAdrian Hunter goto out; 1792ef149c25SAdrian Hunter 17936156681bSNamhyung Kim /* 17946156681bSNamhyung Kim * We take all buildids when the file contains 17956156681bSNamhyung Kim * AUX area tracing data because we do not decode the 17966156681bSNamhyung Kim * trace because it would take too long. 17976156681bSNamhyung Kim */ 17986156681bSNamhyung Kim if (rec->opts.full_auxtrace) 17996156681bSNamhyung Kim rec->buildid_all = true; 18006156681bSNamhyung Kim 1801b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 180239d17dacSArnaldo Carvalho de Melo err = -EINVAL; 1803394c01edSAdrian Hunter goto out; 18047e4ff9e3SMike Galbraith } 18057e4ff9e3SMike Galbraith 1806d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 1807394c01edSAdrian Hunter out: 180845604710SNamhyung Kim perf_evlist__delete(rec->evlist); 1809d65a458bSArnaldo Carvalho de Melo symbol__exit(); 1810ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 181139d17dacSArnaldo Carvalho de Melo return err; 181286470930SIngo Molnar } 18132dd6d8a1SAdrian Hunter 18142dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 18152dd6d8a1SAdrian Hunter { 1816dc0c6127SJiri Olsa struct record *rec = &record; 1817dc0c6127SJiri Olsa 18185f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 18195f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 18202dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 18215f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 18225f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 18235f9cf599SWang Nan } 18243c1cb7e3SWang Nan 1825dc0c6127SJiri Olsa if (switch_output_signal(rec)) 18263c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 18272dd6d8a1SAdrian Hunter } 1828bfacbe3bSJiri Olsa 1829bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused) 1830bfacbe3bSJiri Olsa { 1831bfacbe3bSJiri Olsa struct record *rec = &record; 1832bfacbe3bSJiri Olsa 1833bfacbe3bSJiri Olsa if (switch_output_time(rec)) 1834bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger); 1835bfacbe3bSJiri Olsa } 1836