18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * builtin-record.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Builtin record command: Record the profile of a workload 68c2ecf20Sopenharmony_ci * (or a CPU, or a PID) into the perf.data output file - for 78c2ecf20Sopenharmony_ci * later analysis via perf report. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include "builtin.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "util/build-id.h" 128c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h> 138c2ecf20Sopenharmony_ci#include "util/parse-events.h" 148c2ecf20Sopenharmony_ci#include "util/config.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "util/callchain.h" 178c2ecf20Sopenharmony_ci#include "util/cgroup.h" 188c2ecf20Sopenharmony_ci#include "util/header.h" 198c2ecf20Sopenharmony_ci#include "util/event.h" 208c2ecf20Sopenharmony_ci#include "util/evlist.h" 218c2ecf20Sopenharmony_ci#include "util/evsel.h" 228c2ecf20Sopenharmony_ci#include "util/debug.h" 238c2ecf20Sopenharmony_ci#include "util/mmap.h" 248c2ecf20Sopenharmony_ci#include "util/target.h" 258c2ecf20Sopenharmony_ci#include "util/session.h" 268c2ecf20Sopenharmony_ci#include "util/tool.h" 278c2ecf20Sopenharmony_ci#include "util/symbol.h" 288c2ecf20Sopenharmony_ci#include "util/record.h" 298c2ecf20Sopenharmony_ci#include "util/cpumap.h" 308c2ecf20Sopenharmony_ci#include "util/thread_map.h" 318c2ecf20Sopenharmony_ci#include "util/data.h" 328c2ecf20Sopenharmony_ci#include "util/perf_regs.h" 338c2ecf20Sopenharmony_ci#include "util/auxtrace.h" 348c2ecf20Sopenharmony_ci#include "util/tsc.h" 358c2ecf20Sopenharmony_ci#include "util/parse-branch-options.h" 368c2ecf20Sopenharmony_ci#include "util/parse-regs-options.h" 378c2ecf20Sopenharmony_ci#include "util/perf_api_probe.h" 388c2ecf20Sopenharmony_ci#include "util/llvm-utils.h" 398c2ecf20Sopenharmony_ci#include "util/bpf-loader.h" 408c2ecf20Sopenharmony_ci#include "util/trigger.h" 418c2ecf20Sopenharmony_ci#include "util/perf-hooks.h" 428c2ecf20Sopenharmony_ci#include "util/cpu-set-sched.h" 438c2ecf20Sopenharmony_ci#include "util/synthetic-events.h" 448c2ecf20Sopenharmony_ci#include "util/time-utils.h" 458c2ecf20Sopenharmony_ci#include "util/units.h" 468c2ecf20Sopenharmony_ci#include "util/bpf-event.h" 478c2ecf20Sopenharmony_ci#include "util/util.h" 488c2ecf20Sopenharmony_ci#include "util/pfm.h" 498c2ecf20Sopenharmony_ci#include "util/clockid.h" 508c2ecf20Sopenharmony_ci#include "asm/bug.h" 518c2ecf20Sopenharmony_ci#include "perf.h" 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#include <errno.h> 548c2ecf20Sopenharmony_ci#include <inttypes.h> 558c2ecf20Sopenharmony_ci#include <locale.h> 568c2ecf20Sopenharmony_ci#include <poll.h> 578c2ecf20Sopenharmony_ci#include <pthread.h> 588c2ecf20Sopenharmony_ci#include <unistd.h> 598c2ecf20Sopenharmony_ci#include <sched.h> 608c2ecf20Sopenharmony_ci#include <signal.h> 618c2ecf20Sopenharmony_ci#ifdef HAVE_EVENTFD_SUPPORT 628c2ecf20Sopenharmony_ci#include <sys/eventfd.h> 638c2ecf20Sopenharmony_ci#endif 648c2ecf20Sopenharmony_ci#include <sys/mman.h> 658c2ecf20Sopenharmony_ci#include <sys/wait.h> 668c2ecf20Sopenharmony_ci#include <sys/types.h> 678c2ecf20Sopenharmony_ci#include <sys/stat.h> 688c2ecf20Sopenharmony_ci#include <fcntl.h> 698c2ecf20Sopenharmony_ci#include <linux/err.h> 708c2ecf20Sopenharmony_ci#include <linux/string.h> 718c2ecf20Sopenharmony_ci#include <linux/time64.h> 728c2ecf20Sopenharmony_ci#include <linux/zalloc.h> 738c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 748c2ecf20Sopenharmony_ci#include <sys/time.h> 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct switch_output { 778c2ecf20Sopenharmony_ci bool enabled; 788c2ecf20Sopenharmony_ci bool signal; 798c2ecf20Sopenharmony_ci unsigned long size; 808c2ecf20Sopenharmony_ci unsigned long time; 818c2ecf20Sopenharmony_ci const char *str; 828c2ecf20Sopenharmony_ci bool set; 838c2ecf20Sopenharmony_ci char **filenames; 848c2ecf20Sopenharmony_ci int num_files; 858c2ecf20Sopenharmony_ci int cur_file; 868c2ecf20Sopenharmony_ci}; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistruct record { 898c2ecf20Sopenharmony_ci struct perf_tool tool; 908c2ecf20Sopenharmony_ci struct record_opts opts; 918c2ecf20Sopenharmony_ci u64 bytes_written; 928c2ecf20Sopenharmony_ci struct perf_data data; 938c2ecf20Sopenharmony_ci struct auxtrace_record *itr; 948c2ecf20Sopenharmony_ci struct evlist *evlist; 958c2ecf20Sopenharmony_ci struct perf_session *session; 968c2ecf20Sopenharmony_ci struct evlist *sb_evlist; 978c2ecf20Sopenharmony_ci pthread_t thread_id; 988c2ecf20Sopenharmony_ci int realtime_prio; 998c2ecf20Sopenharmony_ci bool switch_output_event_set; 1008c2ecf20Sopenharmony_ci bool no_buildid; 1018c2ecf20Sopenharmony_ci bool no_buildid_set; 1028c2ecf20Sopenharmony_ci bool no_buildid_cache; 1038c2ecf20Sopenharmony_ci bool no_buildid_cache_set; 1048c2ecf20Sopenharmony_ci bool buildid_all; 1058c2ecf20Sopenharmony_ci bool timestamp_filename; 1068c2ecf20Sopenharmony_ci bool timestamp_boundary; 1078c2ecf20Sopenharmony_ci struct switch_output switch_output; 1088c2ecf20Sopenharmony_ci unsigned long long samples; 1098c2ecf20Sopenharmony_ci struct mmap_cpu_mask affinity_mask; 1108c2ecf20Sopenharmony_ci unsigned long output_max_size; /* = 0: unlimited */ 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic volatile int done; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic volatile int auxtrace_record__snapshot_started; 1168c2ecf20Sopenharmony_cistatic DEFINE_TRIGGER(auxtrace_snapshot_trigger); 1178c2ecf20Sopenharmony_cistatic DEFINE_TRIGGER(switch_output_trigger); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic const char *affinity_tags[PERF_AFFINITY_MAX] = { 1208c2ecf20Sopenharmony_ci "SYS", "NODE", "CPU" 1218c2ecf20Sopenharmony_ci}; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic bool switch_output_signal(struct record *rec) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return rec->switch_output.signal && 1268c2ecf20Sopenharmony_ci trigger_is_ready(&switch_output_trigger); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic bool switch_output_size(struct record *rec) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci return rec->switch_output.size && 1328c2ecf20Sopenharmony_ci trigger_is_ready(&switch_output_trigger) && 1338c2ecf20Sopenharmony_ci (rec->bytes_written >= rec->switch_output.size); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic bool switch_output_time(struct record *rec) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci return rec->switch_output.time && 1398c2ecf20Sopenharmony_ci trigger_is_ready(&switch_output_trigger); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic bool record__output_max_size_exceeded(struct record *rec) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci return rec->output_max_size && 1458c2ecf20Sopenharmony_ci (rec->bytes_written >= rec->output_max_size); 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic int record__write(struct record *rec, struct mmap *map __maybe_unused, 1498c2ecf20Sopenharmony_ci void *bf, size_t size) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci struct perf_data_file *file = &rec->session->data->file; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (perf_data_file__write(file, bf, size) < 0) { 1548c2ecf20Sopenharmony_ci pr_err("failed to write perf data, error: %m\n"); 1558c2ecf20Sopenharmony_ci return -1; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci rec->bytes_written += size; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (record__output_max_size_exceeded(rec) && !done) { 1618c2ecf20Sopenharmony_ci fprintf(stderr, "[ perf record: perf size limit reached (%" PRIu64 " KB)," 1628c2ecf20Sopenharmony_ci " stopping session ]\n", 1638c2ecf20Sopenharmony_ci rec->bytes_written >> 10); 1648c2ecf20Sopenharmony_ci done = 1; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci if (switch_output_size(rec)) 1688c2ecf20Sopenharmony_ci trigger_hit(&switch_output_trigger); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci return 0; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic int record__aio_enabled(struct record *rec); 1748c2ecf20Sopenharmony_cistatic int record__comp_enabled(struct record *rec); 1758c2ecf20Sopenharmony_cistatic size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 1768c2ecf20Sopenharmony_ci void *src, size_t src_size); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci#ifdef HAVE_AIO_SUPPORT 1798c2ecf20Sopenharmony_cistatic int record__aio_write(struct aiocb *cblock, int trace_fd, 1808c2ecf20Sopenharmony_ci void *buf, size_t size, off_t off) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci int rc; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci cblock->aio_fildes = trace_fd; 1858c2ecf20Sopenharmony_ci cblock->aio_buf = buf; 1868c2ecf20Sopenharmony_ci cblock->aio_nbytes = size; 1878c2ecf20Sopenharmony_ci cblock->aio_offset = off; 1888c2ecf20Sopenharmony_ci cblock->aio_sigevent.sigev_notify = SIGEV_NONE; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci do { 1918c2ecf20Sopenharmony_ci rc = aio_write(cblock); 1928c2ecf20Sopenharmony_ci if (rc == 0) { 1938c2ecf20Sopenharmony_ci break; 1948c2ecf20Sopenharmony_ci } else if (errno != EAGAIN) { 1958c2ecf20Sopenharmony_ci cblock->aio_fildes = -1; 1968c2ecf20Sopenharmony_ci pr_err("failed to queue perf data, error: %m\n"); 1978c2ecf20Sopenharmony_ci break; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci } while (1); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci return rc; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic int record__aio_complete(struct mmap *md, struct aiocb *cblock) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci void *rem_buf; 2078c2ecf20Sopenharmony_ci off_t rem_off; 2088c2ecf20Sopenharmony_ci size_t rem_size; 2098c2ecf20Sopenharmony_ci int rc, aio_errno; 2108c2ecf20Sopenharmony_ci ssize_t aio_ret, written; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci aio_errno = aio_error(cblock); 2138c2ecf20Sopenharmony_ci if (aio_errno == EINPROGRESS) 2148c2ecf20Sopenharmony_ci return 0; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci written = aio_ret = aio_return(cblock); 2178c2ecf20Sopenharmony_ci if (aio_ret < 0) { 2188c2ecf20Sopenharmony_ci if (aio_errno != EINTR) 2198c2ecf20Sopenharmony_ci pr_err("failed to write perf data, error: %m\n"); 2208c2ecf20Sopenharmony_ci written = 0; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci rem_size = cblock->aio_nbytes - written; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (rem_size == 0) { 2268c2ecf20Sopenharmony_ci cblock->aio_fildes = -1; 2278c2ecf20Sopenharmony_ci /* 2288c2ecf20Sopenharmony_ci * md->refcount is incremented in record__aio_pushfn() for 2298c2ecf20Sopenharmony_ci * every aio write request started in record__aio_push() so 2308c2ecf20Sopenharmony_ci * decrement it because the request is now complete. 2318c2ecf20Sopenharmony_ci */ 2328c2ecf20Sopenharmony_ci perf_mmap__put(&md->core); 2338c2ecf20Sopenharmony_ci rc = 1; 2348c2ecf20Sopenharmony_ci } else { 2358c2ecf20Sopenharmony_ci /* 2368c2ecf20Sopenharmony_ci * aio write request may require restart with the 2378c2ecf20Sopenharmony_ci * reminder if the kernel didn't write whole 2388c2ecf20Sopenharmony_ci * chunk at once. 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ci rem_off = cblock->aio_offset + written; 2418c2ecf20Sopenharmony_ci rem_buf = (void *)(cblock->aio_buf + written); 2428c2ecf20Sopenharmony_ci record__aio_write(cblock, cblock->aio_fildes, 2438c2ecf20Sopenharmony_ci rem_buf, rem_size, rem_off); 2448c2ecf20Sopenharmony_ci rc = 0; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return rc; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic int record__aio_sync(struct mmap *md, bool sync_all) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci struct aiocb **aiocb = md->aio.aiocb; 2538c2ecf20Sopenharmony_ci struct aiocb *cblocks = md->aio.cblocks; 2548c2ecf20Sopenharmony_ci struct timespec timeout = { 0, 1000 * 1000 * 1 }; /* 1ms */ 2558c2ecf20Sopenharmony_ci int i, do_suspend; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci do { 2588c2ecf20Sopenharmony_ci do_suspend = 0; 2598c2ecf20Sopenharmony_ci for (i = 0; i < md->aio.nr_cblocks; ++i) { 2608c2ecf20Sopenharmony_ci if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) { 2618c2ecf20Sopenharmony_ci if (sync_all) 2628c2ecf20Sopenharmony_ci aiocb[i] = NULL; 2638c2ecf20Sopenharmony_ci else 2648c2ecf20Sopenharmony_ci return i; 2658c2ecf20Sopenharmony_ci } else { 2668c2ecf20Sopenharmony_ci /* 2678c2ecf20Sopenharmony_ci * Started aio write is not complete yet 2688c2ecf20Sopenharmony_ci * so it has to be waited before the 2698c2ecf20Sopenharmony_ci * next allocation. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci aiocb[i] = &cblocks[i]; 2728c2ecf20Sopenharmony_ci do_suspend = 1; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci if (!do_suspend) 2768c2ecf20Sopenharmony_ci return -1; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) { 2798c2ecf20Sopenharmony_ci if (!(errno == EAGAIN || errno == EINTR)) 2808c2ecf20Sopenharmony_ci pr_err("failed to sync perf data, error: %m\n"); 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci } while (1); 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistruct record_aio { 2868c2ecf20Sopenharmony_ci struct record *rec; 2878c2ecf20Sopenharmony_ci void *data; 2888c2ecf20Sopenharmony_ci size_t size; 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic int record__aio_pushfn(struct mmap *map, void *to, void *buf, size_t size) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct record_aio *aio = to; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* 2968c2ecf20Sopenharmony_ci * map->core.base data pointed by buf is copied into free map->aio.data[] buffer 2978c2ecf20Sopenharmony_ci * to release space in the kernel buffer as fast as possible, calling 2988c2ecf20Sopenharmony_ci * perf_mmap__consume() from perf_mmap__push() function. 2998c2ecf20Sopenharmony_ci * 3008c2ecf20Sopenharmony_ci * That lets the kernel to proceed with storing more profiling data into 3018c2ecf20Sopenharmony_ci * the kernel buffer earlier than other per-cpu kernel buffers are handled. 3028c2ecf20Sopenharmony_ci * 3038c2ecf20Sopenharmony_ci * Coping can be done in two steps in case the chunk of profiling data 3048c2ecf20Sopenharmony_ci * crosses the upper bound of the kernel buffer. In this case we first move 3058c2ecf20Sopenharmony_ci * part of data from map->start till the upper bound and then the reminder 3068c2ecf20Sopenharmony_ci * from the beginning of the kernel buffer till the end of the data chunk. 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (record__comp_enabled(aio->rec)) { 3108c2ecf20Sopenharmony_ci size = zstd_compress(aio->rec->session, aio->data + aio->size, 3118c2ecf20Sopenharmony_ci mmap__mmap_len(map) - aio->size, 3128c2ecf20Sopenharmony_ci buf, size); 3138c2ecf20Sopenharmony_ci } else { 3148c2ecf20Sopenharmony_ci memcpy(aio->data + aio->size, buf, size); 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (!aio->size) { 3188c2ecf20Sopenharmony_ci /* 3198c2ecf20Sopenharmony_ci * Increment map->refcount to guard map->aio.data[] buffer 3208c2ecf20Sopenharmony_ci * from premature deallocation because map object can be 3218c2ecf20Sopenharmony_ci * released earlier than aio write request started on 3228c2ecf20Sopenharmony_ci * map->aio.data[] buffer is complete. 3238c2ecf20Sopenharmony_ci * 3248c2ecf20Sopenharmony_ci * perf_mmap__put() is done at record__aio_complete() 3258c2ecf20Sopenharmony_ci * after started aio request completion or at record__aio_push() 3268c2ecf20Sopenharmony_ci * if the request failed to start. 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ci perf_mmap__get(&map->core); 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci aio->size += size; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci return size; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic int record__aio_push(struct record *rec, struct mmap *map, off_t *off) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci int ret, idx; 3398c2ecf20Sopenharmony_ci int trace_fd = rec->session->data->file.fd; 3408c2ecf20Sopenharmony_ci struct record_aio aio = { .rec = rec, .size = 0 }; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* 3438c2ecf20Sopenharmony_ci * Call record__aio_sync() to wait till map->aio.data[] buffer 3448c2ecf20Sopenharmony_ci * becomes available after previous aio write operation. 3458c2ecf20Sopenharmony_ci */ 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci idx = record__aio_sync(map, false); 3488c2ecf20Sopenharmony_ci aio.data = map->aio.data[idx]; 3498c2ecf20Sopenharmony_ci ret = perf_mmap__push(map, &aio, record__aio_pushfn); 3508c2ecf20Sopenharmony_ci if (ret != 0) /* ret > 0 - no data, ret < 0 - error */ 3518c2ecf20Sopenharmony_ci return ret; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci rec->samples++; 3548c2ecf20Sopenharmony_ci ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off); 3558c2ecf20Sopenharmony_ci if (!ret) { 3568c2ecf20Sopenharmony_ci *off += aio.size; 3578c2ecf20Sopenharmony_ci rec->bytes_written += aio.size; 3588c2ecf20Sopenharmony_ci if (switch_output_size(rec)) 3598c2ecf20Sopenharmony_ci trigger_hit(&switch_output_trigger); 3608c2ecf20Sopenharmony_ci } else { 3618c2ecf20Sopenharmony_ci /* 3628c2ecf20Sopenharmony_ci * Decrement map->refcount incremented in record__aio_pushfn() 3638c2ecf20Sopenharmony_ci * back if record__aio_write() operation failed to start, otherwise 3648c2ecf20Sopenharmony_ci * map->refcount is decremented in record__aio_complete() after 3658c2ecf20Sopenharmony_ci * aio write operation finishes successfully. 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_ci perf_mmap__put(&map->core); 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci return ret; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic off_t record__aio_get_pos(int trace_fd) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci return lseek(trace_fd, 0, SEEK_CUR); 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic void record__aio_set_pos(int trace_fd, off_t pos) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci lseek(trace_fd, pos, SEEK_SET); 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic void record__aio_mmap_read_sync(struct record *rec) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci int i; 3868c2ecf20Sopenharmony_ci struct evlist *evlist = rec->evlist; 3878c2ecf20Sopenharmony_ci struct mmap *maps = evlist->mmap; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (!record__aio_enabled(rec)) 3908c2ecf20Sopenharmony_ci return; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci for (i = 0; i < evlist->core.nr_mmaps; i++) { 3938c2ecf20Sopenharmony_ci struct mmap *map = &maps[i]; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci if (map->core.base) 3968c2ecf20Sopenharmony_ci record__aio_sync(map, true); 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistatic int nr_cblocks_default = 1; 4018c2ecf20Sopenharmony_cistatic int nr_cblocks_max = 4; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic int record__aio_parse(const struct option *opt, 4048c2ecf20Sopenharmony_ci const char *str, 4058c2ecf20Sopenharmony_ci int unset) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct record_opts *opts = (struct record_opts *)opt->value; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci if (unset) { 4108c2ecf20Sopenharmony_ci opts->nr_cblocks = 0; 4118c2ecf20Sopenharmony_ci } else { 4128c2ecf20Sopenharmony_ci if (str) 4138c2ecf20Sopenharmony_ci opts->nr_cblocks = strtol(str, NULL, 0); 4148c2ecf20Sopenharmony_ci if (!opts->nr_cblocks) 4158c2ecf20Sopenharmony_ci opts->nr_cblocks = nr_cblocks_default; 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci return 0; 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci#else /* HAVE_AIO_SUPPORT */ 4218c2ecf20Sopenharmony_cistatic int nr_cblocks_max = 0; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cistatic int record__aio_push(struct record *rec __maybe_unused, struct mmap *map __maybe_unused, 4248c2ecf20Sopenharmony_ci off_t *off __maybe_unused) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci return -1; 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic off_t record__aio_get_pos(int trace_fd __maybe_unused) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci return -1; 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic void record__aio_mmap_read_sync(struct record *rec __maybe_unused) 4398c2ecf20Sopenharmony_ci{ 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci#endif 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic int record__aio_enabled(struct record *rec) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci return rec->opts.nr_cblocks > 0; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci#define MMAP_FLUSH_DEFAULT 1 4498c2ecf20Sopenharmony_cistatic int record__mmap_flush_parse(const struct option *opt, 4508c2ecf20Sopenharmony_ci const char *str, 4518c2ecf20Sopenharmony_ci int unset) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci int flush_max; 4548c2ecf20Sopenharmony_ci struct record_opts *opts = (struct record_opts *)opt->value; 4558c2ecf20Sopenharmony_ci static struct parse_tag tags[] = { 4568c2ecf20Sopenharmony_ci { .tag = 'B', .mult = 1 }, 4578c2ecf20Sopenharmony_ci { .tag = 'K', .mult = 1 << 10 }, 4588c2ecf20Sopenharmony_ci { .tag = 'M', .mult = 1 << 20 }, 4598c2ecf20Sopenharmony_ci { .tag = 'G', .mult = 1 << 30 }, 4608c2ecf20Sopenharmony_ci { .tag = 0 }, 4618c2ecf20Sopenharmony_ci }; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (unset) 4648c2ecf20Sopenharmony_ci return 0; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci if (str) { 4678c2ecf20Sopenharmony_ci opts->mmap_flush = parse_tag_value(str, tags); 4688c2ecf20Sopenharmony_ci if (opts->mmap_flush == (int)-1) 4698c2ecf20Sopenharmony_ci opts->mmap_flush = strtol(str, NULL, 0); 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (!opts->mmap_flush) 4738c2ecf20Sopenharmony_ci opts->mmap_flush = MMAP_FLUSH_DEFAULT; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci flush_max = evlist__mmap_size(opts->mmap_pages); 4768c2ecf20Sopenharmony_ci flush_max /= 4; 4778c2ecf20Sopenharmony_ci if (opts->mmap_flush > flush_max) 4788c2ecf20Sopenharmony_ci opts->mmap_flush = flush_max; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci return 0; 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci#ifdef HAVE_ZSTD_SUPPORT 4848c2ecf20Sopenharmony_cistatic unsigned int comp_level_default = 1; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic int record__parse_comp_level(const struct option *opt, const char *str, int unset) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct record_opts *opts = opt->value; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (unset) { 4918c2ecf20Sopenharmony_ci opts->comp_level = 0; 4928c2ecf20Sopenharmony_ci } else { 4938c2ecf20Sopenharmony_ci if (str) 4948c2ecf20Sopenharmony_ci opts->comp_level = strtol(str, NULL, 0); 4958c2ecf20Sopenharmony_ci if (!opts->comp_level) 4968c2ecf20Sopenharmony_ci opts->comp_level = comp_level_default; 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci return 0; 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci#endif 5028c2ecf20Sopenharmony_cistatic unsigned int comp_level_max = 22; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic int record__comp_enabled(struct record *rec) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci return rec->opts.comp_level > 0; 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic int process_synthesized_event(struct perf_tool *tool, 5108c2ecf20Sopenharmony_ci union perf_event *event, 5118c2ecf20Sopenharmony_ci struct perf_sample *sample __maybe_unused, 5128c2ecf20Sopenharmony_ci struct machine *machine __maybe_unused) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci struct record *rec = container_of(tool, struct record, tool); 5158c2ecf20Sopenharmony_ci return record__write(rec, NULL, event, event->header.size); 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic int process_locked_synthesized_event(struct perf_tool *tool, 5198c2ecf20Sopenharmony_ci union perf_event *event, 5208c2ecf20Sopenharmony_ci struct perf_sample *sample __maybe_unused, 5218c2ecf20Sopenharmony_ci struct machine *machine __maybe_unused) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci static pthread_mutex_t synth_lock = PTHREAD_MUTEX_INITIALIZER; 5248c2ecf20Sopenharmony_ci int ret; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci pthread_mutex_lock(&synth_lock); 5278c2ecf20Sopenharmony_ci ret = process_synthesized_event(tool, event, sample, machine); 5288c2ecf20Sopenharmony_ci pthread_mutex_unlock(&synth_lock); 5298c2ecf20Sopenharmony_ci return ret; 5308c2ecf20Sopenharmony_ci} 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_cistatic int record__pushfn(struct mmap *map, void *to, void *bf, size_t size) 5338c2ecf20Sopenharmony_ci{ 5348c2ecf20Sopenharmony_ci struct record *rec = to; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (record__comp_enabled(rec)) { 5378c2ecf20Sopenharmony_ci size = zstd_compress(rec->session, map->data, mmap__mmap_len(map), bf, size); 5388c2ecf20Sopenharmony_ci bf = map->data; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci rec->samples++; 5428c2ecf20Sopenharmony_ci return record__write(rec, map, bf, size); 5438c2ecf20Sopenharmony_ci} 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_cistatic volatile int signr = -1; 5468c2ecf20Sopenharmony_cistatic volatile int child_finished; 5478c2ecf20Sopenharmony_ci#ifdef HAVE_EVENTFD_SUPPORT 5488c2ecf20Sopenharmony_cistatic int done_fd = -1; 5498c2ecf20Sopenharmony_ci#endif 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic void sig_handler(int sig) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci if (sig == SIGCHLD) 5548c2ecf20Sopenharmony_ci child_finished = 1; 5558c2ecf20Sopenharmony_ci else 5568c2ecf20Sopenharmony_ci signr = sig; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci done = 1; 5598c2ecf20Sopenharmony_ci#ifdef HAVE_EVENTFD_SUPPORT 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci u64 tmp = 1; 5628c2ecf20Sopenharmony_ci /* 5638c2ecf20Sopenharmony_ci * It is possible for this signal handler to run after done is checked 5648c2ecf20Sopenharmony_ci * in the main loop, but before the perf counter fds are polled. If this 5658c2ecf20Sopenharmony_ci * happens, the poll() will continue to wait even though done is set, 5668c2ecf20Sopenharmony_ci * and will only break out if either another signal is received, or the 5678c2ecf20Sopenharmony_ci * counters are ready for read. To ensure the poll() doesn't sleep when 5688c2ecf20Sopenharmony_ci * done is set, use an eventfd (done_fd) to wake up the poll(). 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_ci if (write(done_fd, &tmp, sizeof(tmp)) < 0) 5718c2ecf20Sopenharmony_ci pr_err("failed to signal wakeup fd, error: %m\n"); 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci#endif // HAVE_EVENTFD_SUPPORT 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic void sigsegv_handler(int sig) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci perf_hooks__recover(); 5798c2ecf20Sopenharmony_ci sighandler_dump_stack(sig); 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic void record__sig_exit(void) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci if (signr == -1) 5858c2ecf20Sopenharmony_ci return; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci signal(signr, SIG_DFL); 5888c2ecf20Sopenharmony_ci raise(signr); 5898c2ecf20Sopenharmony_ci} 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci#ifdef HAVE_AUXTRACE_SUPPORT 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic int record__process_auxtrace(struct perf_tool *tool, 5948c2ecf20Sopenharmony_ci struct mmap *map, 5958c2ecf20Sopenharmony_ci union perf_event *event, void *data1, 5968c2ecf20Sopenharmony_ci size_t len1, void *data2, size_t len2) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci struct record *rec = container_of(tool, struct record, tool); 5998c2ecf20Sopenharmony_ci struct perf_data *data = &rec->data; 6008c2ecf20Sopenharmony_ci size_t padding; 6018c2ecf20Sopenharmony_ci u8 pad[8] = {0}; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci if (!perf_data__is_pipe(data) && perf_data__is_single_file(data)) { 6048c2ecf20Sopenharmony_ci off_t file_offset; 6058c2ecf20Sopenharmony_ci int fd = perf_data__fd(data); 6068c2ecf20Sopenharmony_ci int err; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci file_offset = lseek(fd, 0, SEEK_CUR); 6098c2ecf20Sopenharmony_ci if (file_offset == -1) 6108c2ecf20Sopenharmony_ci return -1; 6118c2ecf20Sopenharmony_ci err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 6128c2ecf20Sopenharmony_ci event, file_offset); 6138c2ecf20Sopenharmony_ci if (err) 6148c2ecf20Sopenharmony_ci return err; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 6188c2ecf20Sopenharmony_ci padding = (len1 + len2) & 7; 6198c2ecf20Sopenharmony_ci if (padding) 6208c2ecf20Sopenharmony_ci padding = 8 - padding; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci record__write(rec, map, event, event->header.size); 6238c2ecf20Sopenharmony_ci record__write(rec, map, data1, len1); 6248c2ecf20Sopenharmony_ci if (len2) 6258c2ecf20Sopenharmony_ci record__write(rec, map, data2, len2); 6268c2ecf20Sopenharmony_ci record__write(rec, map, &pad, padding); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci return 0; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic int record__auxtrace_mmap_read(struct record *rec, 6328c2ecf20Sopenharmony_ci struct mmap *map) 6338c2ecf20Sopenharmony_ci{ 6348c2ecf20Sopenharmony_ci int ret; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci ret = auxtrace_mmap__read(map, rec->itr, &rec->tool, 6378c2ecf20Sopenharmony_ci record__process_auxtrace); 6388c2ecf20Sopenharmony_ci if (ret < 0) 6398c2ecf20Sopenharmony_ci return ret; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (ret) 6428c2ecf20Sopenharmony_ci rec->samples++; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci return 0; 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic int record__auxtrace_mmap_read_snapshot(struct record *rec, 6488c2ecf20Sopenharmony_ci struct mmap *map) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci int ret; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool, 6538c2ecf20Sopenharmony_ci record__process_auxtrace, 6548c2ecf20Sopenharmony_ci rec->opts.auxtrace_snapshot_size); 6558c2ecf20Sopenharmony_ci if (ret < 0) 6568c2ecf20Sopenharmony_ci return ret; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci if (ret) 6598c2ecf20Sopenharmony_ci rec->samples++; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci return 0; 6628c2ecf20Sopenharmony_ci} 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_cistatic int record__auxtrace_read_snapshot_all(struct record *rec) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci int i; 6678c2ecf20Sopenharmony_ci int rc = 0; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci for (i = 0; i < rec->evlist->core.nr_mmaps; i++) { 6708c2ecf20Sopenharmony_ci struct mmap *map = &rec->evlist->mmap[i]; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci if (!map->auxtrace_mmap.base) 6738c2ecf20Sopenharmony_ci continue; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) { 6768c2ecf20Sopenharmony_ci rc = -1; 6778c2ecf20Sopenharmony_ci goto out; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ciout: 6818c2ecf20Sopenharmony_ci return rc; 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_cistatic void record__read_auxtrace_snapshot(struct record *rec, bool on_exit) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci pr_debug("Recording AUX area tracing snapshot\n"); 6878c2ecf20Sopenharmony_ci if (record__auxtrace_read_snapshot_all(rec) < 0) { 6888c2ecf20Sopenharmony_ci trigger_error(&auxtrace_snapshot_trigger); 6898c2ecf20Sopenharmony_ci } else { 6908c2ecf20Sopenharmony_ci if (auxtrace_record__snapshot_finish(rec->itr, on_exit)) 6918c2ecf20Sopenharmony_ci trigger_error(&auxtrace_snapshot_trigger); 6928c2ecf20Sopenharmony_ci else 6938c2ecf20Sopenharmony_ci trigger_ready(&auxtrace_snapshot_trigger); 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_cistatic int record__auxtrace_snapshot_exit(struct record *rec) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci if (trigger_is_error(&auxtrace_snapshot_trigger)) 7008c2ecf20Sopenharmony_ci return 0; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci if (!auxtrace_record__snapshot_started && 7038c2ecf20Sopenharmony_ci auxtrace_record__snapshot_start(rec->itr)) 7048c2ecf20Sopenharmony_ci return -1; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci record__read_auxtrace_snapshot(rec, true); 7078c2ecf20Sopenharmony_ci if (trigger_is_error(&auxtrace_snapshot_trigger)) 7088c2ecf20Sopenharmony_ci return -1; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci return 0; 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic int record__auxtrace_init(struct record *rec) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci int err; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci if (!rec->itr) { 7188c2ecf20Sopenharmony_ci rec->itr = auxtrace_record__init(rec->evlist, &err); 7198c2ecf20Sopenharmony_ci if (err) 7208c2ecf20Sopenharmony_ci return err; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 7248c2ecf20Sopenharmony_ci rec->opts.auxtrace_snapshot_opts); 7258c2ecf20Sopenharmony_ci if (err) 7268c2ecf20Sopenharmony_ci return err; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci err = auxtrace_parse_sample_options(rec->itr, rec->evlist, &rec->opts, 7298c2ecf20Sopenharmony_ci rec->opts.auxtrace_sample_opts); 7308c2ecf20Sopenharmony_ci if (err) 7318c2ecf20Sopenharmony_ci return err; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci return auxtrace_parse_filters(rec->evlist); 7348c2ecf20Sopenharmony_ci} 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci#else 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_cistatic inline 7398c2ecf20Sopenharmony_ciint record__auxtrace_mmap_read(struct record *rec __maybe_unused, 7408c2ecf20Sopenharmony_ci struct mmap *map __maybe_unused) 7418c2ecf20Sopenharmony_ci{ 7428c2ecf20Sopenharmony_ci return 0; 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_cistatic inline 7468c2ecf20Sopenharmony_civoid record__read_auxtrace_snapshot(struct record *rec __maybe_unused, 7478c2ecf20Sopenharmony_ci bool on_exit __maybe_unused) 7488c2ecf20Sopenharmony_ci{ 7498c2ecf20Sopenharmony_ci} 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistatic inline 7528c2ecf20Sopenharmony_ciint auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 7538c2ecf20Sopenharmony_ci{ 7548c2ecf20Sopenharmony_ci return 0; 7558c2ecf20Sopenharmony_ci} 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_cistatic inline 7588c2ecf20Sopenharmony_ciint record__auxtrace_snapshot_exit(struct record *rec __maybe_unused) 7598c2ecf20Sopenharmony_ci{ 7608c2ecf20Sopenharmony_ci return 0; 7618c2ecf20Sopenharmony_ci} 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_cistatic int record__auxtrace_init(struct record *rec __maybe_unused) 7648c2ecf20Sopenharmony_ci{ 7658c2ecf20Sopenharmony_ci return 0; 7668c2ecf20Sopenharmony_ci} 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci#endif 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_cistatic int record__config_text_poke(struct evlist *evlist) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci struct evsel *evsel; 7738c2ecf20Sopenharmony_ci int err; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci /* Nothing to do if text poke is already configured */ 7768c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 7778c2ecf20Sopenharmony_ci if (evsel->core.attr.text_poke) 7788c2ecf20Sopenharmony_ci return 0; 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci err = parse_events(evlist, "dummy:u", NULL); 7828c2ecf20Sopenharmony_ci if (err) 7838c2ecf20Sopenharmony_ci return err; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci evsel = evlist__last(evlist); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci evsel->core.attr.freq = 0; 7888c2ecf20Sopenharmony_ci evsel->core.attr.sample_period = 1; 7898c2ecf20Sopenharmony_ci evsel->core.attr.text_poke = 1; 7908c2ecf20Sopenharmony_ci evsel->core.attr.ksymbol = 1; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci evsel->core.system_wide = true; 7938c2ecf20Sopenharmony_ci evsel->no_aux_samples = true; 7948c2ecf20Sopenharmony_ci evsel->immediate = true; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci /* Text poke must be collected on all CPUs */ 7978c2ecf20Sopenharmony_ci perf_cpu_map__put(evsel->core.own_cpus); 7988c2ecf20Sopenharmony_ci evsel->core.own_cpus = perf_cpu_map__new(NULL); 7998c2ecf20Sopenharmony_ci perf_cpu_map__put(evsel->core.cpus); 8008c2ecf20Sopenharmony_ci evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci evsel__set_sample_bit(evsel, TIME); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci return 0; 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic bool record__kcore_readable(struct machine *machine) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci char kcore[PATH_MAX]; 8108c2ecf20Sopenharmony_ci int fd; 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci scnprintf(kcore, sizeof(kcore), "%s/proc/kcore", machine->root_dir); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci fd = open(kcore, O_RDONLY); 8158c2ecf20Sopenharmony_ci if (fd < 0) 8168c2ecf20Sopenharmony_ci return false; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci close(fd); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci return true; 8218c2ecf20Sopenharmony_ci} 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_cistatic int record__kcore_copy(struct machine *machine, struct perf_data *data) 8248c2ecf20Sopenharmony_ci{ 8258c2ecf20Sopenharmony_ci char from_dir[PATH_MAX]; 8268c2ecf20Sopenharmony_ci char kcore_dir[PATH_MAX]; 8278c2ecf20Sopenharmony_ci int ret; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci snprintf(from_dir, sizeof(from_dir), "%s/proc", machine->root_dir); 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci ret = perf_data__make_kcore_dir(data, kcore_dir, sizeof(kcore_dir)); 8328c2ecf20Sopenharmony_ci if (ret) 8338c2ecf20Sopenharmony_ci return ret; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci return kcore_copy(from_dir, kcore_dir); 8368c2ecf20Sopenharmony_ci} 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_cistatic int record__mmap_evlist(struct record *rec, 8398c2ecf20Sopenharmony_ci struct evlist *evlist) 8408c2ecf20Sopenharmony_ci{ 8418c2ecf20Sopenharmony_ci struct record_opts *opts = &rec->opts; 8428c2ecf20Sopenharmony_ci bool auxtrace_overwrite = opts->auxtrace_snapshot_mode || 8438c2ecf20Sopenharmony_ci opts->auxtrace_sample_mode; 8448c2ecf20Sopenharmony_ci char msg[512]; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci if (opts->affinity != PERF_AFFINITY_SYS) 8478c2ecf20Sopenharmony_ci cpu__setup_cpunode_map(); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci if (evlist__mmap_ex(evlist, opts->mmap_pages, 8508c2ecf20Sopenharmony_ci opts->auxtrace_mmap_pages, 8518c2ecf20Sopenharmony_ci auxtrace_overwrite, 8528c2ecf20Sopenharmony_ci opts->nr_cblocks, opts->affinity, 8538c2ecf20Sopenharmony_ci opts->mmap_flush, opts->comp_level) < 0) { 8548c2ecf20Sopenharmony_ci if (errno == EPERM) { 8558c2ecf20Sopenharmony_ci pr_err("Permission error mapping pages.\n" 8568c2ecf20Sopenharmony_ci "Consider increasing " 8578c2ecf20Sopenharmony_ci "/proc/sys/kernel/perf_event_mlock_kb,\n" 8588c2ecf20Sopenharmony_ci "or try again with a smaller value of -m/--mmap_pages.\n" 8598c2ecf20Sopenharmony_ci "(current value: %u,%u)\n", 8608c2ecf20Sopenharmony_ci opts->mmap_pages, opts->auxtrace_mmap_pages); 8618c2ecf20Sopenharmony_ci return -errno; 8628c2ecf20Sopenharmony_ci } else { 8638c2ecf20Sopenharmony_ci pr_err("failed to mmap with %d (%s)\n", errno, 8648c2ecf20Sopenharmony_ci str_error_r(errno, msg, sizeof(msg))); 8658c2ecf20Sopenharmony_ci if (errno) 8668c2ecf20Sopenharmony_ci return -errno; 8678c2ecf20Sopenharmony_ci else 8688c2ecf20Sopenharmony_ci return -EINVAL; 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci return 0; 8728c2ecf20Sopenharmony_ci} 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_cistatic int record__mmap(struct record *rec) 8758c2ecf20Sopenharmony_ci{ 8768c2ecf20Sopenharmony_ci return record__mmap_evlist(rec, rec->evlist); 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic int record__open(struct record *rec) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci char msg[BUFSIZ]; 8828c2ecf20Sopenharmony_ci struct evsel *pos; 8838c2ecf20Sopenharmony_ci struct evlist *evlist = rec->evlist; 8848c2ecf20Sopenharmony_ci struct perf_session *session = rec->session; 8858c2ecf20Sopenharmony_ci struct record_opts *opts = &rec->opts; 8868c2ecf20Sopenharmony_ci int rc = 0; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci /* 8898c2ecf20Sopenharmony_ci * For initial_delay or system wide, we need to add a dummy event so 8908c2ecf20Sopenharmony_ci * that we can track PERF_RECORD_MMAP to cover the delay of waiting or 8918c2ecf20Sopenharmony_ci * event synthesis. 8928c2ecf20Sopenharmony_ci */ 8938c2ecf20Sopenharmony_ci if (opts->initial_delay || target__has_cpu(&opts->target)) { 8948c2ecf20Sopenharmony_ci pos = perf_evlist__get_tracking_event(evlist); 8958c2ecf20Sopenharmony_ci if (!evsel__is_dummy_event(pos)) { 8968c2ecf20Sopenharmony_ci /* Set up dummy event. */ 8978c2ecf20Sopenharmony_ci if (evlist__add_dummy(evlist)) 8988c2ecf20Sopenharmony_ci return -ENOMEM; 8998c2ecf20Sopenharmony_ci pos = evlist__last(evlist); 9008c2ecf20Sopenharmony_ci perf_evlist__set_tracking_event(evlist, pos); 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci /* 9048c2ecf20Sopenharmony_ci * Enable the dummy event when the process is forked for 9058c2ecf20Sopenharmony_ci * initial_delay, immediately for system wide. 9068c2ecf20Sopenharmony_ci */ 9078c2ecf20Sopenharmony_ci if (opts->initial_delay && !pos->immediate) 9088c2ecf20Sopenharmony_ci pos->core.attr.enable_on_exec = 1; 9098c2ecf20Sopenharmony_ci else 9108c2ecf20Sopenharmony_ci pos->immediate = 1; 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci perf_evlist__config(evlist, opts, &callchain_param); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, pos) { 9168c2ecf20Sopenharmony_citry_again: 9178c2ecf20Sopenharmony_ci if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) { 9188c2ecf20Sopenharmony_ci if (evsel__fallback(pos, errno, msg, sizeof(msg))) { 9198c2ecf20Sopenharmony_ci if (verbose > 0) 9208c2ecf20Sopenharmony_ci ui__warning("%s\n", msg); 9218c2ecf20Sopenharmony_ci goto try_again; 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci if ((errno == EINVAL || errno == EBADF) && 9248c2ecf20Sopenharmony_ci pos->leader != pos && 9258c2ecf20Sopenharmony_ci pos->weak_group) { 9268c2ecf20Sopenharmony_ci pos = perf_evlist__reset_weak_group(evlist, pos, true); 9278c2ecf20Sopenharmony_ci goto try_again; 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci rc = -errno; 9308c2ecf20Sopenharmony_ci evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg)); 9318c2ecf20Sopenharmony_ci ui__error("%s\n", msg); 9328c2ecf20Sopenharmony_ci goto out; 9338c2ecf20Sopenharmony_ci } 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci pos->supported = true; 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(evlist)) { 9398c2ecf20Sopenharmony_ci pr_warning( 9408c2ecf20Sopenharmony_ci"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 9418c2ecf20Sopenharmony_ci"check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n" 9428c2ecf20Sopenharmony_ci"Samples in kernel functions may not be resolved if a suitable vmlinux\n" 9438c2ecf20Sopenharmony_ci"file is not found in the buildid cache or in the vmlinux path.\n\n" 9448c2ecf20Sopenharmony_ci"Samples in kernel modules won't be resolved at all.\n\n" 9458c2ecf20Sopenharmony_ci"If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 9468c2ecf20Sopenharmony_ci"even with a suitable vmlinux or kallsyms file.\n\n"); 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci if (perf_evlist__apply_filters(evlist, &pos)) { 9508c2ecf20Sopenharmony_ci pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 9518c2ecf20Sopenharmony_ci pos->filter, evsel__name(pos), errno, 9528c2ecf20Sopenharmony_ci str_error_r(errno, msg, sizeof(msg))); 9538c2ecf20Sopenharmony_ci rc = -1; 9548c2ecf20Sopenharmony_ci goto out; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci rc = record__mmap(rec); 9588c2ecf20Sopenharmony_ci if (rc) 9598c2ecf20Sopenharmony_ci goto out; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci session->evlist = evlist; 9628c2ecf20Sopenharmony_ci perf_session__set_id_hdr_size(session); 9638c2ecf20Sopenharmony_ciout: 9648c2ecf20Sopenharmony_ci return rc; 9658c2ecf20Sopenharmony_ci} 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_cistatic int process_sample_event(struct perf_tool *tool, 9688c2ecf20Sopenharmony_ci union perf_event *event, 9698c2ecf20Sopenharmony_ci struct perf_sample *sample, 9708c2ecf20Sopenharmony_ci struct evsel *evsel, 9718c2ecf20Sopenharmony_ci struct machine *machine) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci struct record *rec = container_of(tool, struct record, tool); 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci if (rec->evlist->first_sample_time == 0) 9768c2ecf20Sopenharmony_ci rec->evlist->first_sample_time = sample->time; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci rec->evlist->last_sample_time = sample->time; 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (rec->buildid_all) 9818c2ecf20Sopenharmony_ci return 0; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci rec->samples++; 9848c2ecf20Sopenharmony_ci return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 9858c2ecf20Sopenharmony_ci} 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_cistatic int process_buildids(struct record *rec) 9888c2ecf20Sopenharmony_ci{ 9898c2ecf20Sopenharmony_ci struct perf_session *session = rec->session; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (perf_data__size(&rec->data) == 0) 9928c2ecf20Sopenharmony_ci return 0; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* 9958c2ecf20Sopenharmony_ci * During this process, it'll load kernel map and replace the 9968c2ecf20Sopenharmony_ci * dso->long_name to a real pathname it found. In this case 9978c2ecf20Sopenharmony_ci * we prefer the vmlinux path like 9988c2ecf20Sopenharmony_ci * /lib/modules/3.16.4/build/vmlinux 9998c2ecf20Sopenharmony_ci * 10008c2ecf20Sopenharmony_ci * rather than build-id path (in debug directory). 10018c2ecf20Sopenharmony_ci * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 10028c2ecf20Sopenharmony_ci */ 10038c2ecf20Sopenharmony_ci symbol_conf.ignore_vmlinux_buildid = true; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci /* 10068c2ecf20Sopenharmony_ci * If --buildid-all is given, it marks all DSO regardless of hits, 10078c2ecf20Sopenharmony_ci * so no need to process samples. But if timestamp_boundary is enabled, 10088c2ecf20Sopenharmony_ci * it still needs to walk on all samples to get the timestamps of 10098c2ecf20Sopenharmony_ci * first/last samples. 10108c2ecf20Sopenharmony_ci */ 10118c2ecf20Sopenharmony_ci if (rec->buildid_all && !rec->timestamp_boundary) 10128c2ecf20Sopenharmony_ci rec->tool.sample = NULL; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci return perf_session__process_events(session); 10158c2ecf20Sopenharmony_ci} 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_cistatic void perf_event__synthesize_guest_os(struct machine *machine, void *data) 10188c2ecf20Sopenharmony_ci{ 10198c2ecf20Sopenharmony_ci int err; 10208c2ecf20Sopenharmony_ci struct perf_tool *tool = data; 10218c2ecf20Sopenharmony_ci /* 10228c2ecf20Sopenharmony_ci *As for guest kernel when processing subcommand record&report, 10238c2ecf20Sopenharmony_ci *we arrange module mmap prior to guest kernel mmap and trigger 10248c2ecf20Sopenharmony_ci *a preload dso because default guest module symbols are loaded 10258c2ecf20Sopenharmony_ci *from guest kallsyms instead of /lib/modules/XXX/XXX. This 10268c2ecf20Sopenharmony_ci *method is used to avoid symbol missing when the first addr is 10278c2ecf20Sopenharmony_ci *in module instead of in guest kernel. 10288c2ecf20Sopenharmony_ci */ 10298c2ecf20Sopenharmony_ci err = perf_event__synthesize_modules(tool, process_synthesized_event, 10308c2ecf20Sopenharmony_ci machine); 10318c2ecf20Sopenharmony_ci if (err < 0) 10328c2ecf20Sopenharmony_ci pr_err("Couldn't record guest kernel [%d]'s reference" 10338c2ecf20Sopenharmony_ci " relocation symbol.\n", machine->pid); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci /* 10368c2ecf20Sopenharmony_ci * We use _stext for guest kernel because guest kernel's /proc/kallsyms 10378c2ecf20Sopenharmony_ci * have no _text sometimes. 10388c2ecf20Sopenharmony_ci */ 10398c2ecf20Sopenharmony_ci err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 10408c2ecf20Sopenharmony_ci machine); 10418c2ecf20Sopenharmony_ci if (err < 0) 10428c2ecf20Sopenharmony_ci pr_err("Couldn't record guest kernel [%d]'s reference" 10438c2ecf20Sopenharmony_ci " relocation symbol.\n", machine->pid); 10448c2ecf20Sopenharmony_ci} 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_cistatic struct perf_event_header finished_round_event = { 10478c2ecf20Sopenharmony_ci .size = sizeof(struct perf_event_header), 10488c2ecf20Sopenharmony_ci .type = PERF_RECORD_FINISHED_ROUND, 10498c2ecf20Sopenharmony_ci}; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_cistatic void record__adjust_affinity(struct record *rec, struct mmap *map) 10528c2ecf20Sopenharmony_ci{ 10538c2ecf20Sopenharmony_ci if (rec->opts.affinity != PERF_AFFINITY_SYS && 10548c2ecf20Sopenharmony_ci !bitmap_equal(rec->affinity_mask.bits, map->affinity_mask.bits, 10558c2ecf20Sopenharmony_ci rec->affinity_mask.nbits)) { 10568c2ecf20Sopenharmony_ci bitmap_zero(rec->affinity_mask.bits, rec->affinity_mask.nbits); 10578c2ecf20Sopenharmony_ci bitmap_or(rec->affinity_mask.bits, rec->affinity_mask.bits, 10588c2ecf20Sopenharmony_ci map->affinity_mask.bits, rec->affinity_mask.nbits); 10598c2ecf20Sopenharmony_ci sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&rec->affinity_mask), 10608c2ecf20Sopenharmony_ci (cpu_set_t *)rec->affinity_mask.bits); 10618c2ecf20Sopenharmony_ci if (verbose == 2) 10628c2ecf20Sopenharmony_ci mmap_cpu_mask__scnprintf(&rec->affinity_mask, "thread"); 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci} 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_cistatic size_t process_comp_header(void *record, size_t increment) 10678c2ecf20Sopenharmony_ci{ 10688c2ecf20Sopenharmony_ci struct perf_record_compressed *event = record; 10698c2ecf20Sopenharmony_ci size_t size = sizeof(*event); 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci if (increment) { 10728c2ecf20Sopenharmony_ci event->header.size += increment; 10738c2ecf20Sopenharmony_ci return increment; 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci event->header.type = PERF_RECORD_COMPRESSED; 10778c2ecf20Sopenharmony_ci event->header.size = size; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci return size; 10808c2ecf20Sopenharmony_ci} 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_cistatic size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 10838c2ecf20Sopenharmony_ci void *src, size_t src_size) 10848c2ecf20Sopenharmony_ci{ 10858c2ecf20Sopenharmony_ci size_t compressed; 10868c2ecf20Sopenharmony_ci size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size, 10898c2ecf20Sopenharmony_ci max_record_size, process_comp_header); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci session->bytes_transferred += src_size; 10928c2ecf20Sopenharmony_ci session->bytes_compressed += compressed; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci return compressed; 10958c2ecf20Sopenharmony_ci} 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_cistatic int record__mmap_read_evlist(struct record *rec, struct evlist *evlist, 10988c2ecf20Sopenharmony_ci bool overwrite, bool synch) 10998c2ecf20Sopenharmony_ci{ 11008c2ecf20Sopenharmony_ci u64 bytes_written = rec->bytes_written; 11018c2ecf20Sopenharmony_ci int i; 11028c2ecf20Sopenharmony_ci int rc = 0; 11038c2ecf20Sopenharmony_ci struct mmap *maps; 11048c2ecf20Sopenharmony_ci int trace_fd = rec->data.file.fd; 11058c2ecf20Sopenharmony_ci off_t off = 0; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci if (!evlist) 11088c2ecf20Sopenharmony_ci return 0; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci maps = overwrite ? evlist->overwrite_mmap : evlist->mmap; 11118c2ecf20Sopenharmony_ci if (!maps) 11128c2ecf20Sopenharmony_ci return 0; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 11158c2ecf20Sopenharmony_ci return 0; 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci if (record__aio_enabled(rec)) 11188c2ecf20Sopenharmony_ci off = record__aio_get_pos(trace_fd); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci for (i = 0; i < evlist->core.nr_mmaps; i++) { 11218c2ecf20Sopenharmony_ci u64 flush = 0; 11228c2ecf20Sopenharmony_ci struct mmap *map = &maps[i]; 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci if (map->core.base) { 11258c2ecf20Sopenharmony_ci record__adjust_affinity(rec, map); 11268c2ecf20Sopenharmony_ci if (synch) { 11278c2ecf20Sopenharmony_ci flush = map->core.flush; 11288c2ecf20Sopenharmony_ci map->core.flush = 1; 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci if (!record__aio_enabled(rec)) { 11318c2ecf20Sopenharmony_ci if (perf_mmap__push(map, rec, record__pushfn) < 0) { 11328c2ecf20Sopenharmony_ci if (synch) 11338c2ecf20Sopenharmony_ci map->core.flush = flush; 11348c2ecf20Sopenharmony_ci rc = -1; 11358c2ecf20Sopenharmony_ci goto out; 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci } else { 11388c2ecf20Sopenharmony_ci if (record__aio_push(rec, map, &off) < 0) { 11398c2ecf20Sopenharmony_ci record__aio_set_pos(trace_fd, off); 11408c2ecf20Sopenharmony_ci if (synch) 11418c2ecf20Sopenharmony_ci map->core.flush = flush; 11428c2ecf20Sopenharmony_ci rc = -1; 11438c2ecf20Sopenharmony_ci goto out; 11448c2ecf20Sopenharmony_ci } 11458c2ecf20Sopenharmony_ci } 11468c2ecf20Sopenharmony_ci if (synch) 11478c2ecf20Sopenharmony_ci map->core.flush = flush; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode && 11518c2ecf20Sopenharmony_ci !rec->opts.auxtrace_sample_mode && 11528c2ecf20Sopenharmony_ci record__auxtrace_mmap_read(rec, map) != 0) { 11538c2ecf20Sopenharmony_ci rc = -1; 11548c2ecf20Sopenharmony_ci goto out; 11558c2ecf20Sopenharmony_ci } 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci if (record__aio_enabled(rec)) 11598c2ecf20Sopenharmony_ci record__aio_set_pos(trace_fd, off); 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci /* 11628c2ecf20Sopenharmony_ci * Mark the round finished in case we wrote 11638c2ecf20Sopenharmony_ci * at least one event. 11648c2ecf20Sopenharmony_ci */ 11658c2ecf20Sopenharmony_ci if (bytes_written != rec->bytes_written) 11668c2ecf20Sopenharmony_ci rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event)); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci if (overwrite) 11698c2ecf20Sopenharmony_ci perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 11708c2ecf20Sopenharmony_ciout: 11718c2ecf20Sopenharmony_ci return rc; 11728c2ecf20Sopenharmony_ci} 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_cistatic int record__mmap_read_all(struct record *rec, bool synch) 11758c2ecf20Sopenharmony_ci{ 11768c2ecf20Sopenharmony_ci int err; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci err = record__mmap_read_evlist(rec, rec->evlist, false, synch); 11798c2ecf20Sopenharmony_ci if (err) 11808c2ecf20Sopenharmony_ci return err; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci return record__mmap_read_evlist(rec, rec->evlist, true, synch); 11838c2ecf20Sopenharmony_ci} 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_cistatic void record__init_features(struct record *rec) 11868c2ecf20Sopenharmony_ci{ 11878c2ecf20Sopenharmony_ci struct perf_session *session = rec->session; 11888c2ecf20Sopenharmony_ci int feat; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 11918c2ecf20Sopenharmony_ci perf_header__set_feat(&session->header, feat); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci if (rec->no_buildid) 11948c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci if (!have_tracepoints(&rec->evlist->core.entries)) 11978c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci if (!rec->opts.branch_stack) 12008c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci if (!rec->opts.full_auxtrace) 12038c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 12068c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_CLOCKID); 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci if (!rec->opts.use_clockid) 12098c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_CLOCK_DATA); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); 12128c2ecf20Sopenharmony_ci if (!record__comp_enabled(rec)) 12138c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_COMPRESSED); 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_STAT); 12168c2ecf20Sopenharmony_ci} 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_cistatic void 12198c2ecf20Sopenharmony_cirecord__finish_output(struct record *rec) 12208c2ecf20Sopenharmony_ci{ 12218c2ecf20Sopenharmony_ci struct perf_data *data = &rec->data; 12228c2ecf20Sopenharmony_ci int fd = perf_data__fd(data); 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci if (data->is_pipe) 12258c2ecf20Sopenharmony_ci return; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci rec->session->header.data_size += rec->bytes_written; 12288c2ecf20Sopenharmony_ci data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci if (!rec->no_buildid) { 12318c2ecf20Sopenharmony_ci process_buildids(rec); 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (rec->buildid_all) 12348c2ecf20Sopenharmony_ci dsos__hit_all(rec->session); 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci perf_session__write_header(rec->session, rec->evlist, fd, true); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci return; 12398c2ecf20Sopenharmony_ci} 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_cistatic int record__synthesize_workload(struct record *rec, bool tail) 12428c2ecf20Sopenharmony_ci{ 12438c2ecf20Sopenharmony_ci int err; 12448c2ecf20Sopenharmony_ci struct perf_thread_map *thread_map; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci if (rec->opts.tail_synthesize != tail) 12478c2ecf20Sopenharmony_ci return 0; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 12508c2ecf20Sopenharmony_ci if (thread_map == NULL) 12518c2ecf20Sopenharmony_ci return -1; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 12548c2ecf20Sopenharmony_ci process_synthesized_event, 12558c2ecf20Sopenharmony_ci &rec->session->machines.host, 12568c2ecf20Sopenharmony_ci rec->opts.sample_address); 12578c2ecf20Sopenharmony_ci perf_thread_map__put(thread_map); 12588c2ecf20Sopenharmony_ci return err; 12598c2ecf20Sopenharmony_ci} 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_cistatic int record__synthesize(struct record *rec, bool tail); 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_cistatic int 12648c2ecf20Sopenharmony_cirecord__switch_output(struct record *rec, bool at_exit) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci struct perf_data *data = &rec->data; 12678c2ecf20Sopenharmony_ci int fd, err; 12688c2ecf20Sopenharmony_ci char *new_filename; 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci /* Same Size: "2015122520103046"*/ 12718c2ecf20Sopenharmony_ci char timestamp[] = "InvalidTimestamp"; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci record__aio_mmap_read_sync(rec); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci record__synthesize(rec, true); 12768c2ecf20Sopenharmony_ci if (target__none(&rec->opts.target)) 12778c2ecf20Sopenharmony_ci record__synthesize_workload(rec, true); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci rec->samples = 0; 12808c2ecf20Sopenharmony_ci record__finish_output(rec); 12818c2ecf20Sopenharmony_ci err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 12828c2ecf20Sopenharmony_ci if (err) { 12838c2ecf20Sopenharmony_ci pr_err("Failed to get current timestamp\n"); 12848c2ecf20Sopenharmony_ci return -EINVAL; 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci fd = perf_data__switch(data, timestamp, 12888c2ecf20Sopenharmony_ci rec->session->header.data_offset, 12898c2ecf20Sopenharmony_ci at_exit, &new_filename); 12908c2ecf20Sopenharmony_ci if (fd >= 0 && !at_exit) { 12918c2ecf20Sopenharmony_ci rec->bytes_written = 0; 12928c2ecf20Sopenharmony_ci rec->session->header.data_size = 0; 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci if (!quiet) 12968c2ecf20Sopenharmony_ci fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 12978c2ecf20Sopenharmony_ci data->path, timestamp); 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci if (rec->switch_output.num_files) { 13008c2ecf20Sopenharmony_ci int n = rec->switch_output.cur_file + 1; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci if (n >= rec->switch_output.num_files) 13038c2ecf20Sopenharmony_ci n = 0; 13048c2ecf20Sopenharmony_ci rec->switch_output.cur_file = n; 13058c2ecf20Sopenharmony_ci if (rec->switch_output.filenames[n]) { 13068c2ecf20Sopenharmony_ci remove(rec->switch_output.filenames[n]); 13078c2ecf20Sopenharmony_ci zfree(&rec->switch_output.filenames[n]); 13088c2ecf20Sopenharmony_ci } 13098c2ecf20Sopenharmony_ci rec->switch_output.filenames[n] = new_filename; 13108c2ecf20Sopenharmony_ci } else { 13118c2ecf20Sopenharmony_ci free(new_filename); 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci /* Output tracking events */ 13158c2ecf20Sopenharmony_ci if (!at_exit) { 13168c2ecf20Sopenharmony_ci record__synthesize(rec, false); 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci /* 13198c2ecf20Sopenharmony_ci * In 'perf record --switch-output' without -a, 13208c2ecf20Sopenharmony_ci * record__synthesize() in record__switch_output() won't 13218c2ecf20Sopenharmony_ci * generate tracking events because there's no thread_map 13228c2ecf20Sopenharmony_ci * in evlist. Which causes newly created perf.data doesn't 13238c2ecf20Sopenharmony_ci * contain map and comm information. 13248c2ecf20Sopenharmony_ci * Create a fake thread_map and directly call 13258c2ecf20Sopenharmony_ci * perf_event__synthesize_thread_map() for those events. 13268c2ecf20Sopenharmony_ci */ 13278c2ecf20Sopenharmony_ci if (target__none(&rec->opts.target)) 13288c2ecf20Sopenharmony_ci record__synthesize_workload(rec, false); 13298c2ecf20Sopenharmony_ci } 13308c2ecf20Sopenharmony_ci return fd; 13318c2ecf20Sopenharmony_ci} 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_cistatic volatile int workload_exec_errno; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci/* 13368c2ecf20Sopenharmony_ci * perf_evlist__prepare_workload will send a SIGUSR1 13378c2ecf20Sopenharmony_ci * if the fork fails, since we asked by setting its 13388c2ecf20Sopenharmony_ci * want_signal to true. 13398c2ecf20Sopenharmony_ci */ 13408c2ecf20Sopenharmony_cistatic void workload_exec_failed_signal(int signo __maybe_unused, 13418c2ecf20Sopenharmony_ci siginfo_t *info, 13428c2ecf20Sopenharmony_ci void *ucontext __maybe_unused) 13438c2ecf20Sopenharmony_ci{ 13448c2ecf20Sopenharmony_ci workload_exec_errno = info->si_value.sival_int; 13458c2ecf20Sopenharmony_ci done = 1; 13468c2ecf20Sopenharmony_ci child_finished = 1; 13478c2ecf20Sopenharmony_ci} 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_cistatic void snapshot_sig_handler(int sig); 13508c2ecf20Sopenharmony_cistatic void alarm_sig_handler(int sig); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_cistatic const struct perf_event_mmap_page * 13538c2ecf20Sopenharmony_ciperf_evlist__pick_pc(struct evlist *evlist) 13548c2ecf20Sopenharmony_ci{ 13558c2ecf20Sopenharmony_ci if (evlist) { 13568c2ecf20Sopenharmony_ci if (evlist->mmap && evlist->mmap[0].core.base) 13578c2ecf20Sopenharmony_ci return evlist->mmap[0].core.base; 13588c2ecf20Sopenharmony_ci if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].core.base) 13598c2ecf20Sopenharmony_ci return evlist->overwrite_mmap[0].core.base; 13608c2ecf20Sopenharmony_ci } 13618c2ecf20Sopenharmony_ci return NULL; 13628c2ecf20Sopenharmony_ci} 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_cistatic const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 13658c2ecf20Sopenharmony_ci{ 13668c2ecf20Sopenharmony_ci const struct perf_event_mmap_page *pc; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci pc = perf_evlist__pick_pc(rec->evlist); 13698c2ecf20Sopenharmony_ci if (pc) 13708c2ecf20Sopenharmony_ci return pc; 13718c2ecf20Sopenharmony_ci return NULL; 13728c2ecf20Sopenharmony_ci} 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic int record__synthesize(struct record *rec, bool tail) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci struct perf_session *session = rec->session; 13778c2ecf20Sopenharmony_ci struct machine *machine = &session->machines.host; 13788c2ecf20Sopenharmony_ci struct perf_data *data = &rec->data; 13798c2ecf20Sopenharmony_ci struct record_opts *opts = &rec->opts; 13808c2ecf20Sopenharmony_ci struct perf_tool *tool = &rec->tool; 13818c2ecf20Sopenharmony_ci int fd = perf_data__fd(data); 13828c2ecf20Sopenharmony_ci int err = 0; 13838c2ecf20Sopenharmony_ci event_op f = process_synthesized_event; 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci if (rec->opts.tail_synthesize != tail) 13868c2ecf20Sopenharmony_ci return 0; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (data->is_pipe) { 13898c2ecf20Sopenharmony_ci /* 13908c2ecf20Sopenharmony_ci * We need to synthesize events first, because some 13918c2ecf20Sopenharmony_ci * features works on top of them (on report side). 13928c2ecf20Sopenharmony_ci */ 13938c2ecf20Sopenharmony_ci err = perf_event__synthesize_attrs(tool, rec->evlist, 13948c2ecf20Sopenharmony_ci process_synthesized_event); 13958c2ecf20Sopenharmony_ci if (err < 0) { 13968c2ecf20Sopenharmony_ci pr_err("Couldn't synthesize attrs.\n"); 13978c2ecf20Sopenharmony_ci goto out; 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci err = perf_event__synthesize_features(tool, session, rec->evlist, 14018c2ecf20Sopenharmony_ci process_synthesized_event); 14028c2ecf20Sopenharmony_ci if (err < 0) { 14038c2ecf20Sopenharmony_ci pr_err("Couldn't synthesize features.\n"); 14048c2ecf20Sopenharmony_ci return err; 14058c2ecf20Sopenharmony_ci } 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci if (have_tracepoints(&rec->evlist->core.entries)) { 14088c2ecf20Sopenharmony_ci /* 14098c2ecf20Sopenharmony_ci * FIXME err <= 0 here actually means that 14108c2ecf20Sopenharmony_ci * there were no tracepoints so its not really 14118c2ecf20Sopenharmony_ci * an error, just that we don't need to 14128c2ecf20Sopenharmony_ci * synthesize anything. We really have to 14138c2ecf20Sopenharmony_ci * return this more properly and also 14148c2ecf20Sopenharmony_ci * propagate errors that now are calling die() 14158c2ecf20Sopenharmony_ci */ 14168c2ecf20Sopenharmony_ci err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 14178c2ecf20Sopenharmony_ci process_synthesized_event); 14188c2ecf20Sopenharmony_ci if (err <= 0) { 14198c2ecf20Sopenharmony_ci pr_err("Couldn't record tracing data.\n"); 14208c2ecf20Sopenharmony_ci goto out; 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci rec->bytes_written += err; 14238c2ecf20Sopenharmony_ci } 14248c2ecf20Sopenharmony_ci } 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 14278c2ecf20Sopenharmony_ci process_synthesized_event, machine); 14288c2ecf20Sopenharmony_ci if (err) 14298c2ecf20Sopenharmony_ci goto out; 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci /* Synthesize id_index before auxtrace_info */ 14328c2ecf20Sopenharmony_ci if (rec->opts.auxtrace_sample_mode) { 14338c2ecf20Sopenharmony_ci err = perf_event__synthesize_id_index(tool, 14348c2ecf20Sopenharmony_ci process_synthesized_event, 14358c2ecf20Sopenharmony_ci session->evlist, machine); 14368c2ecf20Sopenharmony_ci if (err) 14378c2ecf20Sopenharmony_ci goto out; 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci if (rec->opts.full_auxtrace) { 14418c2ecf20Sopenharmony_ci err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 14428c2ecf20Sopenharmony_ci session, process_synthesized_event); 14438c2ecf20Sopenharmony_ci if (err) 14448c2ecf20Sopenharmony_ci goto out; 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci if (!perf_evlist__exclude_kernel(rec->evlist)) { 14488c2ecf20Sopenharmony_ci err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 14498c2ecf20Sopenharmony_ci machine); 14508c2ecf20Sopenharmony_ci WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 14518c2ecf20Sopenharmony_ci "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 14528c2ecf20Sopenharmony_ci "Check /proc/kallsyms permission or run as root.\n"); 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci err = perf_event__synthesize_modules(tool, process_synthesized_event, 14558c2ecf20Sopenharmony_ci machine); 14568c2ecf20Sopenharmony_ci WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 14578c2ecf20Sopenharmony_ci "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 14588c2ecf20Sopenharmony_ci "Check /proc/modules permission or run as root.\n"); 14598c2ecf20Sopenharmony_ci } 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci if (perf_guest) { 14628c2ecf20Sopenharmony_ci machines__process_guests(&session->machines, 14638c2ecf20Sopenharmony_ci perf_event__synthesize_guest_os, tool); 14648c2ecf20Sopenharmony_ci } 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci err = perf_event__synthesize_extra_attr(&rec->tool, 14678c2ecf20Sopenharmony_ci rec->evlist, 14688c2ecf20Sopenharmony_ci process_synthesized_event, 14698c2ecf20Sopenharmony_ci data->is_pipe); 14708c2ecf20Sopenharmony_ci if (err) 14718c2ecf20Sopenharmony_ci goto out; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads, 14748c2ecf20Sopenharmony_ci process_synthesized_event, 14758c2ecf20Sopenharmony_ci NULL); 14768c2ecf20Sopenharmony_ci if (err < 0) { 14778c2ecf20Sopenharmony_ci pr_err("Couldn't synthesize thread map.\n"); 14788c2ecf20Sopenharmony_ci return err; 14798c2ecf20Sopenharmony_ci } 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus, 14828c2ecf20Sopenharmony_ci process_synthesized_event, NULL); 14838c2ecf20Sopenharmony_ci if (err < 0) { 14848c2ecf20Sopenharmony_ci pr_err("Couldn't synthesize cpu map.\n"); 14858c2ecf20Sopenharmony_ci return err; 14868c2ecf20Sopenharmony_ci } 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci err = perf_event__synthesize_bpf_events(session, process_synthesized_event, 14898c2ecf20Sopenharmony_ci machine, opts); 14908c2ecf20Sopenharmony_ci if (err < 0) 14918c2ecf20Sopenharmony_ci pr_warning("Couldn't synthesize bpf events.\n"); 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci err = perf_event__synthesize_cgroups(tool, process_synthesized_event, 14948c2ecf20Sopenharmony_ci machine); 14958c2ecf20Sopenharmony_ci if (err < 0) 14968c2ecf20Sopenharmony_ci pr_warning("Couldn't synthesize cgroup events.\n"); 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci if (rec->opts.nr_threads_synthesize > 1) { 14998c2ecf20Sopenharmony_ci perf_set_multithreaded(); 15008c2ecf20Sopenharmony_ci f = process_locked_synthesized_event; 15018c2ecf20Sopenharmony_ci } 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->core.threads, 15048c2ecf20Sopenharmony_ci f, opts->sample_address, 15058c2ecf20Sopenharmony_ci rec->opts.nr_threads_synthesize); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci if (rec->opts.nr_threads_synthesize > 1) 15088c2ecf20Sopenharmony_ci perf_set_singlethreaded(); 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ciout: 15118c2ecf20Sopenharmony_ci return err; 15128c2ecf20Sopenharmony_ci} 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_cistatic int record__process_signal_event(union perf_event *event __maybe_unused, void *data) 15158c2ecf20Sopenharmony_ci{ 15168c2ecf20Sopenharmony_ci struct record *rec = data; 15178c2ecf20Sopenharmony_ci pthread_kill(rec->thread_id, SIGUSR2); 15188c2ecf20Sopenharmony_ci return 0; 15198c2ecf20Sopenharmony_ci} 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_cistatic int record__setup_sb_evlist(struct record *rec) 15228c2ecf20Sopenharmony_ci{ 15238c2ecf20Sopenharmony_ci struct record_opts *opts = &rec->opts; 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci if (rec->sb_evlist != NULL) { 15268c2ecf20Sopenharmony_ci /* 15278c2ecf20Sopenharmony_ci * We get here if --switch-output-event populated the 15288c2ecf20Sopenharmony_ci * sb_evlist, so associate a callback that will send a SIGUSR2 15298c2ecf20Sopenharmony_ci * to the main thread. 15308c2ecf20Sopenharmony_ci */ 15318c2ecf20Sopenharmony_ci evlist__set_cb(rec->sb_evlist, record__process_signal_event, rec); 15328c2ecf20Sopenharmony_ci rec->thread_id = pthread_self(); 15338c2ecf20Sopenharmony_ci } 15348c2ecf20Sopenharmony_ci#ifdef HAVE_LIBBPF_SUPPORT 15358c2ecf20Sopenharmony_ci if (!opts->no_bpf_event) { 15368c2ecf20Sopenharmony_ci if (rec->sb_evlist == NULL) { 15378c2ecf20Sopenharmony_ci rec->sb_evlist = evlist__new(); 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci if (rec->sb_evlist == NULL) { 15408c2ecf20Sopenharmony_ci pr_err("Couldn't create side band evlist.\n."); 15418c2ecf20Sopenharmony_ci return -1; 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci } 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci if (evlist__add_bpf_sb_event(rec->sb_evlist, &rec->session->header.env)) { 15468c2ecf20Sopenharmony_ci pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n."); 15478c2ecf20Sopenharmony_ci return -1; 15488c2ecf20Sopenharmony_ci } 15498c2ecf20Sopenharmony_ci } 15508c2ecf20Sopenharmony_ci#endif 15518c2ecf20Sopenharmony_ci if (perf_evlist__start_sb_thread(rec->sb_evlist, &rec->opts.target)) { 15528c2ecf20Sopenharmony_ci pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); 15538c2ecf20Sopenharmony_ci opts->no_bpf_event = true; 15548c2ecf20Sopenharmony_ci } 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci return 0; 15578c2ecf20Sopenharmony_ci} 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_cistatic int record__init_clock(struct record *rec) 15608c2ecf20Sopenharmony_ci{ 15618c2ecf20Sopenharmony_ci struct perf_session *session = rec->session; 15628c2ecf20Sopenharmony_ci struct timespec ref_clockid; 15638c2ecf20Sopenharmony_ci struct timeval ref_tod; 15648c2ecf20Sopenharmony_ci u64 ref; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci if (!rec->opts.use_clockid) 15678c2ecf20Sopenharmony_ci return 0; 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci if (rec->opts.use_clockid && rec->opts.clockid_res_ns) 15708c2ecf20Sopenharmony_ci session->header.env.clock.clockid_res_ns = rec->opts.clockid_res_ns; 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci session->header.env.clock.clockid = rec->opts.clockid; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci if (gettimeofday(&ref_tod, NULL) != 0) { 15758c2ecf20Sopenharmony_ci pr_err("gettimeofday failed, cannot set reference time.\n"); 15768c2ecf20Sopenharmony_ci return -1; 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci if (clock_gettime(rec->opts.clockid, &ref_clockid)) { 15808c2ecf20Sopenharmony_ci pr_err("clock_gettime failed, cannot set reference time.\n"); 15818c2ecf20Sopenharmony_ci return -1; 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci ref = (u64) ref_tod.tv_sec * NSEC_PER_SEC + 15858c2ecf20Sopenharmony_ci (u64) ref_tod.tv_usec * NSEC_PER_USEC; 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci session->header.env.clock.tod_ns = ref; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci ref = (u64) ref_clockid.tv_sec * NSEC_PER_SEC + 15908c2ecf20Sopenharmony_ci (u64) ref_clockid.tv_nsec; 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci session->header.env.clock.clockid_ns = ref; 15938c2ecf20Sopenharmony_ci return 0; 15948c2ecf20Sopenharmony_ci} 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_cistatic void hit_auxtrace_snapshot_trigger(struct record *rec) 15978c2ecf20Sopenharmony_ci{ 15988c2ecf20Sopenharmony_ci if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 15998c2ecf20Sopenharmony_ci trigger_hit(&auxtrace_snapshot_trigger); 16008c2ecf20Sopenharmony_ci auxtrace_record__snapshot_started = 1; 16018c2ecf20Sopenharmony_ci if (auxtrace_record__snapshot_start(rec->itr)) 16028c2ecf20Sopenharmony_ci trigger_error(&auxtrace_snapshot_trigger); 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci} 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_cistatic int __cmd_record(struct record *rec, int argc, const char **argv) 16078c2ecf20Sopenharmony_ci{ 16088c2ecf20Sopenharmony_ci int err; 16098c2ecf20Sopenharmony_ci int status = 0; 16108c2ecf20Sopenharmony_ci unsigned long waking = 0; 16118c2ecf20Sopenharmony_ci const bool forks = argc > 0; 16128c2ecf20Sopenharmony_ci struct perf_tool *tool = &rec->tool; 16138c2ecf20Sopenharmony_ci struct record_opts *opts = &rec->opts; 16148c2ecf20Sopenharmony_ci struct perf_data *data = &rec->data; 16158c2ecf20Sopenharmony_ci struct perf_session *session; 16168c2ecf20Sopenharmony_ci bool disabled = false, draining = false; 16178c2ecf20Sopenharmony_ci int fd; 16188c2ecf20Sopenharmony_ci float ratio = 0; 16198c2ecf20Sopenharmony_ci enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED; 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci atexit(record__sig_exit); 16228c2ecf20Sopenharmony_ci signal(SIGCHLD, sig_handler); 16238c2ecf20Sopenharmony_ci signal(SIGINT, sig_handler); 16248c2ecf20Sopenharmony_ci signal(SIGTERM, sig_handler); 16258c2ecf20Sopenharmony_ci signal(SIGSEGV, sigsegv_handler); 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci if (rec->opts.record_namespaces) 16288c2ecf20Sopenharmony_ci tool->namespace_events = true; 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci if (rec->opts.record_cgroup) { 16318c2ecf20Sopenharmony_ci#ifdef HAVE_FILE_HANDLE 16328c2ecf20Sopenharmony_ci tool->cgroup_events = true; 16338c2ecf20Sopenharmony_ci#else 16348c2ecf20Sopenharmony_ci pr_err("cgroup tracking is not supported\n"); 16358c2ecf20Sopenharmony_ci return -1; 16368c2ecf20Sopenharmony_ci#endif 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 16408c2ecf20Sopenharmony_ci signal(SIGUSR2, snapshot_sig_handler); 16418c2ecf20Sopenharmony_ci if (rec->opts.auxtrace_snapshot_mode) 16428c2ecf20Sopenharmony_ci trigger_on(&auxtrace_snapshot_trigger); 16438c2ecf20Sopenharmony_ci if (rec->switch_output.enabled) 16448c2ecf20Sopenharmony_ci trigger_on(&switch_output_trigger); 16458c2ecf20Sopenharmony_ci } else { 16468c2ecf20Sopenharmony_ci signal(SIGUSR2, SIG_IGN); 16478c2ecf20Sopenharmony_ci } 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci session = perf_session__new(data, false, tool); 16508c2ecf20Sopenharmony_ci if (IS_ERR(session)) { 16518c2ecf20Sopenharmony_ci pr_err("Perf session creation failed.\n"); 16528c2ecf20Sopenharmony_ci return PTR_ERR(session); 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci fd = perf_data__fd(data); 16568c2ecf20Sopenharmony_ci rec->session = session; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) { 16598c2ecf20Sopenharmony_ci pr_err("Compression initialization failed.\n"); 16608c2ecf20Sopenharmony_ci return -1; 16618c2ecf20Sopenharmony_ci } 16628c2ecf20Sopenharmony_ci#ifdef HAVE_EVENTFD_SUPPORT 16638c2ecf20Sopenharmony_ci done_fd = eventfd(0, EFD_NONBLOCK); 16648c2ecf20Sopenharmony_ci if (done_fd < 0) { 16658c2ecf20Sopenharmony_ci pr_err("Failed to create wakeup eventfd, error: %m\n"); 16668c2ecf20Sopenharmony_ci status = -1; 16678c2ecf20Sopenharmony_ci goto out_delete_session; 16688c2ecf20Sopenharmony_ci } 16698c2ecf20Sopenharmony_ci err = evlist__add_wakeup_eventfd(rec->evlist, done_fd); 16708c2ecf20Sopenharmony_ci if (err < 0) { 16718c2ecf20Sopenharmony_ci pr_err("Failed to add wakeup eventfd to poll list\n"); 16728c2ecf20Sopenharmony_ci status = err; 16738c2ecf20Sopenharmony_ci goto out_delete_session; 16748c2ecf20Sopenharmony_ci } 16758c2ecf20Sopenharmony_ci#endif // HAVE_EVENTFD_SUPPORT 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci session->header.env.comp_type = PERF_COMP_ZSTD; 16788c2ecf20Sopenharmony_ci session->header.env.comp_level = rec->opts.comp_level; 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci if (rec->opts.kcore && 16818c2ecf20Sopenharmony_ci !record__kcore_readable(&session->machines.host)) { 16828c2ecf20Sopenharmony_ci pr_err("ERROR: kcore is not readable.\n"); 16838c2ecf20Sopenharmony_ci return -1; 16848c2ecf20Sopenharmony_ci } 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci if (record__init_clock(rec)) 16878c2ecf20Sopenharmony_ci return -1; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci record__init_features(rec); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci if (forks) { 16928c2ecf20Sopenharmony_ci err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 16938c2ecf20Sopenharmony_ci argv, data->is_pipe, 16948c2ecf20Sopenharmony_ci workload_exec_failed_signal); 16958c2ecf20Sopenharmony_ci if (err < 0) { 16968c2ecf20Sopenharmony_ci pr_err("Couldn't run the workload!\n"); 16978c2ecf20Sopenharmony_ci status = err; 16988c2ecf20Sopenharmony_ci goto out_delete_session; 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci } 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci /* 17038c2ecf20Sopenharmony_ci * If we have just single event and are sending data 17048c2ecf20Sopenharmony_ci * through pipe, we need to force the ids allocation, 17058c2ecf20Sopenharmony_ci * because we synthesize event name through the pipe 17068c2ecf20Sopenharmony_ci * and need the id for that. 17078c2ecf20Sopenharmony_ci */ 17088c2ecf20Sopenharmony_ci if (data->is_pipe && rec->evlist->core.nr_entries == 1) 17098c2ecf20Sopenharmony_ci rec->opts.sample_id = true; 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci if (record__open(rec) != 0) { 17128c2ecf20Sopenharmony_ci err = -1; 17138c2ecf20Sopenharmony_ci goto out_child; 17148c2ecf20Sopenharmony_ci } 17158c2ecf20Sopenharmony_ci session->header.env.comp_mmap_len = session->evlist->core.mmap_len; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci if (rec->opts.kcore) { 17188c2ecf20Sopenharmony_ci err = record__kcore_copy(&session->machines.host, data); 17198c2ecf20Sopenharmony_ci if (err) { 17208c2ecf20Sopenharmony_ci pr_err("ERROR: Failed to copy kcore\n"); 17218c2ecf20Sopenharmony_ci goto out_child; 17228c2ecf20Sopenharmony_ci } 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci err = bpf__apply_obj_config(); 17268c2ecf20Sopenharmony_ci if (err) { 17278c2ecf20Sopenharmony_ci char errbuf[BUFSIZ]; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 17308c2ecf20Sopenharmony_ci pr_err("ERROR: Apply config to BPF failed: %s\n", 17318c2ecf20Sopenharmony_ci errbuf); 17328c2ecf20Sopenharmony_ci goto out_child; 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci /* 17368c2ecf20Sopenharmony_ci * Normally perf_session__new would do this, but it doesn't have the 17378c2ecf20Sopenharmony_ci * evlist. 17388c2ecf20Sopenharmony_ci */ 17398c2ecf20Sopenharmony_ci if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) { 17408c2ecf20Sopenharmony_ci pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 17418c2ecf20Sopenharmony_ci rec->tool.ordered_events = false; 17428c2ecf20Sopenharmony_ci } 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci if (!rec->evlist->nr_groups) 17458c2ecf20Sopenharmony_ci perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci if (data->is_pipe) { 17488c2ecf20Sopenharmony_ci err = perf_header__write_pipe(fd); 17498c2ecf20Sopenharmony_ci if (err < 0) 17508c2ecf20Sopenharmony_ci goto out_child; 17518c2ecf20Sopenharmony_ci } else { 17528c2ecf20Sopenharmony_ci err = perf_session__write_header(session, rec->evlist, fd, false); 17538c2ecf20Sopenharmony_ci if (err < 0) 17548c2ecf20Sopenharmony_ci goto out_child; 17558c2ecf20Sopenharmony_ci } 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci err = -1; 17588c2ecf20Sopenharmony_ci if (!rec->no_buildid 17598c2ecf20Sopenharmony_ci && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 17608c2ecf20Sopenharmony_ci pr_err("Couldn't generate buildids. " 17618c2ecf20Sopenharmony_ci "Use --no-buildid to profile anyway.\n"); 17628c2ecf20Sopenharmony_ci goto out_child; 17638c2ecf20Sopenharmony_ci } 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci err = record__setup_sb_evlist(rec); 17668c2ecf20Sopenharmony_ci if (err) 17678c2ecf20Sopenharmony_ci goto out_child; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci err = record__synthesize(rec, false); 17708c2ecf20Sopenharmony_ci if (err < 0) 17718c2ecf20Sopenharmony_ci goto out_child; 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci if (rec->realtime_prio) { 17748c2ecf20Sopenharmony_ci struct sched_param param; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci param.sched_priority = rec->realtime_prio; 17778c2ecf20Sopenharmony_ci if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 17788c2ecf20Sopenharmony_ci pr_err("Could not set realtime priority.\n"); 17798c2ecf20Sopenharmony_ci err = -1; 17808c2ecf20Sopenharmony_ci goto out_child; 17818c2ecf20Sopenharmony_ci } 17828c2ecf20Sopenharmony_ci } 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci /* 17858c2ecf20Sopenharmony_ci * When perf is starting the traced process, all the events 17868c2ecf20Sopenharmony_ci * (apart from group members) have enable_on_exec=1 set, 17878c2ecf20Sopenharmony_ci * so don't spoil it by prematurely enabling them. 17888c2ecf20Sopenharmony_ci */ 17898c2ecf20Sopenharmony_ci if (!target__none(&opts->target) && !opts->initial_delay) 17908c2ecf20Sopenharmony_ci evlist__enable(rec->evlist); 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci /* 17938c2ecf20Sopenharmony_ci * Let the child rip 17948c2ecf20Sopenharmony_ci */ 17958c2ecf20Sopenharmony_ci if (forks) { 17968c2ecf20Sopenharmony_ci struct machine *machine = &session->machines.host; 17978c2ecf20Sopenharmony_ci union perf_event *event; 17988c2ecf20Sopenharmony_ci pid_t tgid; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci event = malloc(sizeof(event->comm) + machine->id_hdr_size); 18018c2ecf20Sopenharmony_ci if (event == NULL) { 18028c2ecf20Sopenharmony_ci err = -ENOMEM; 18038c2ecf20Sopenharmony_ci goto out_child; 18048c2ecf20Sopenharmony_ci } 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci /* 18078c2ecf20Sopenharmony_ci * Some H/W events are generated before COMM event 18088c2ecf20Sopenharmony_ci * which is emitted during exec(), so perf script 18098c2ecf20Sopenharmony_ci * cannot see a correct process name for those events. 18108c2ecf20Sopenharmony_ci * Synthesize COMM event to prevent it. 18118c2ecf20Sopenharmony_ci */ 18128c2ecf20Sopenharmony_ci tgid = perf_event__synthesize_comm(tool, event, 18138c2ecf20Sopenharmony_ci rec->evlist->workload.pid, 18148c2ecf20Sopenharmony_ci process_synthesized_event, 18158c2ecf20Sopenharmony_ci machine); 18168c2ecf20Sopenharmony_ci free(event); 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci if (tgid == -1) 18198c2ecf20Sopenharmony_ci goto out_child; 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci event = malloc(sizeof(event->namespaces) + 18228c2ecf20Sopenharmony_ci (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 18238c2ecf20Sopenharmony_ci machine->id_hdr_size); 18248c2ecf20Sopenharmony_ci if (event == NULL) { 18258c2ecf20Sopenharmony_ci err = -ENOMEM; 18268c2ecf20Sopenharmony_ci goto out_child; 18278c2ecf20Sopenharmony_ci } 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci /* 18308c2ecf20Sopenharmony_ci * Synthesize NAMESPACES event for the command specified. 18318c2ecf20Sopenharmony_ci */ 18328c2ecf20Sopenharmony_ci perf_event__synthesize_namespaces(tool, event, 18338c2ecf20Sopenharmony_ci rec->evlist->workload.pid, 18348c2ecf20Sopenharmony_ci tgid, process_synthesized_event, 18358c2ecf20Sopenharmony_ci machine); 18368c2ecf20Sopenharmony_ci free(event); 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci perf_evlist__start_workload(rec->evlist); 18398c2ecf20Sopenharmony_ci } 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_ci if (evlist__initialize_ctlfd(rec->evlist, opts->ctl_fd, opts->ctl_fd_ack)) 18428c2ecf20Sopenharmony_ci goto out_child; 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci if (opts->initial_delay) { 18458c2ecf20Sopenharmony_ci pr_info(EVLIST_DISABLED_MSG); 18468c2ecf20Sopenharmony_ci if (opts->initial_delay > 0) { 18478c2ecf20Sopenharmony_ci usleep(opts->initial_delay * USEC_PER_MSEC); 18488c2ecf20Sopenharmony_ci evlist__enable(rec->evlist); 18498c2ecf20Sopenharmony_ci pr_info(EVLIST_ENABLED_MSG); 18508c2ecf20Sopenharmony_ci } 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci trigger_ready(&auxtrace_snapshot_trigger); 18548c2ecf20Sopenharmony_ci trigger_ready(&switch_output_trigger); 18558c2ecf20Sopenharmony_ci perf_hooks__invoke_record_start(); 18568c2ecf20Sopenharmony_ci for (;;) { 18578c2ecf20Sopenharmony_ci unsigned long long hits = rec->samples; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci /* 18608c2ecf20Sopenharmony_ci * rec->evlist->bkw_mmap_state is possible to be 18618c2ecf20Sopenharmony_ci * BKW_MMAP_EMPTY here: when done == true and 18628c2ecf20Sopenharmony_ci * hits != rec->samples in previous round. 18638c2ecf20Sopenharmony_ci * 18648c2ecf20Sopenharmony_ci * perf_evlist__toggle_bkw_mmap ensure we never 18658c2ecf20Sopenharmony_ci * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 18668c2ecf20Sopenharmony_ci */ 18678c2ecf20Sopenharmony_ci if (trigger_is_hit(&switch_output_trigger) || done || draining) 18688c2ecf20Sopenharmony_ci perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 18698c2ecf20Sopenharmony_ci 18708c2ecf20Sopenharmony_ci if (record__mmap_read_all(rec, false) < 0) { 18718c2ecf20Sopenharmony_ci trigger_error(&auxtrace_snapshot_trigger); 18728c2ecf20Sopenharmony_ci trigger_error(&switch_output_trigger); 18738c2ecf20Sopenharmony_ci err = -1; 18748c2ecf20Sopenharmony_ci goto out_child; 18758c2ecf20Sopenharmony_ci } 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_ci if (auxtrace_record__snapshot_started) { 18788c2ecf20Sopenharmony_ci auxtrace_record__snapshot_started = 0; 18798c2ecf20Sopenharmony_ci if (!trigger_is_error(&auxtrace_snapshot_trigger)) 18808c2ecf20Sopenharmony_ci record__read_auxtrace_snapshot(rec, false); 18818c2ecf20Sopenharmony_ci if (trigger_is_error(&auxtrace_snapshot_trigger)) { 18828c2ecf20Sopenharmony_ci pr_err("AUX area tracing snapshot failed\n"); 18838c2ecf20Sopenharmony_ci err = -1; 18848c2ecf20Sopenharmony_ci goto out_child; 18858c2ecf20Sopenharmony_ci } 18868c2ecf20Sopenharmony_ci } 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_ci if (trigger_is_hit(&switch_output_trigger)) { 18898c2ecf20Sopenharmony_ci /* 18908c2ecf20Sopenharmony_ci * If switch_output_trigger is hit, the data in 18918c2ecf20Sopenharmony_ci * overwritable ring buffer should have been collected, 18928c2ecf20Sopenharmony_ci * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 18938c2ecf20Sopenharmony_ci * 18948c2ecf20Sopenharmony_ci * If SIGUSR2 raise after or during record__mmap_read_all(), 18958c2ecf20Sopenharmony_ci * record__mmap_read_all() didn't collect data from 18968c2ecf20Sopenharmony_ci * overwritable ring buffer. Read again. 18978c2ecf20Sopenharmony_ci */ 18988c2ecf20Sopenharmony_ci if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 18998c2ecf20Sopenharmony_ci continue; 19008c2ecf20Sopenharmony_ci trigger_ready(&switch_output_trigger); 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci /* 19038c2ecf20Sopenharmony_ci * Reenable events in overwrite ring buffer after 19048c2ecf20Sopenharmony_ci * record__mmap_read_all(): we should have collected 19058c2ecf20Sopenharmony_ci * data from it. 19068c2ecf20Sopenharmony_ci */ 19078c2ecf20Sopenharmony_ci perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci if (!quiet) 19108c2ecf20Sopenharmony_ci fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 19118c2ecf20Sopenharmony_ci waking); 19128c2ecf20Sopenharmony_ci waking = 0; 19138c2ecf20Sopenharmony_ci fd = record__switch_output(rec, false); 19148c2ecf20Sopenharmony_ci if (fd < 0) { 19158c2ecf20Sopenharmony_ci pr_err("Failed to switch to new file\n"); 19168c2ecf20Sopenharmony_ci trigger_error(&switch_output_trigger); 19178c2ecf20Sopenharmony_ci err = fd; 19188c2ecf20Sopenharmony_ci goto out_child; 19198c2ecf20Sopenharmony_ci } 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci /* re-arm the alarm */ 19228c2ecf20Sopenharmony_ci if (rec->switch_output.time) 19238c2ecf20Sopenharmony_ci alarm(rec->switch_output.time); 19248c2ecf20Sopenharmony_ci } 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_ci if (hits == rec->samples) { 19278c2ecf20Sopenharmony_ci if (done || draining) 19288c2ecf20Sopenharmony_ci break; 19298c2ecf20Sopenharmony_ci err = evlist__poll(rec->evlist, -1); 19308c2ecf20Sopenharmony_ci /* 19318c2ecf20Sopenharmony_ci * Propagate error, only if there's any. Ignore positive 19328c2ecf20Sopenharmony_ci * number of returned events and interrupt error. 19338c2ecf20Sopenharmony_ci */ 19348c2ecf20Sopenharmony_ci if (err > 0 || (err < 0 && errno == EINTR)) 19358c2ecf20Sopenharmony_ci err = 0; 19368c2ecf20Sopenharmony_ci waking++; 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci if (evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 19398c2ecf20Sopenharmony_ci draining = true; 19408c2ecf20Sopenharmony_ci } 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) { 19438c2ecf20Sopenharmony_ci switch (cmd) { 19448c2ecf20Sopenharmony_ci case EVLIST_CTL_CMD_ENABLE: 19458c2ecf20Sopenharmony_ci pr_info(EVLIST_ENABLED_MSG); 19468c2ecf20Sopenharmony_ci break; 19478c2ecf20Sopenharmony_ci case EVLIST_CTL_CMD_DISABLE: 19488c2ecf20Sopenharmony_ci pr_info(EVLIST_DISABLED_MSG); 19498c2ecf20Sopenharmony_ci break; 19508c2ecf20Sopenharmony_ci case EVLIST_CTL_CMD_SNAPSHOT: 19518c2ecf20Sopenharmony_ci hit_auxtrace_snapshot_trigger(rec); 19528c2ecf20Sopenharmony_ci evlist__ctlfd_ack(rec->evlist); 19538c2ecf20Sopenharmony_ci break; 19548c2ecf20Sopenharmony_ci case EVLIST_CTL_CMD_ACK: 19558c2ecf20Sopenharmony_ci case EVLIST_CTL_CMD_UNSUPPORTED: 19568c2ecf20Sopenharmony_ci default: 19578c2ecf20Sopenharmony_ci break; 19588c2ecf20Sopenharmony_ci } 19598c2ecf20Sopenharmony_ci } 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci /* 19628c2ecf20Sopenharmony_ci * When perf is starting the traced process, at the end events 19638c2ecf20Sopenharmony_ci * die with the process and we wait for that. Thus no need to 19648c2ecf20Sopenharmony_ci * disable events in this case. 19658c2ecf20Sopenharmony_ci */ 19668c2ecf20Sopenharmony_ci if (done && !disabled && !target__none(&opts->target)) { 19678c2ecf20Sopenharmony_ci trigger_off(&auxtrace_snapshot_trigger); 19688c2ecf20Sopenharmony_ci evlist__disable(rec->evlist); 19698c2ecf20Sopenharmony_ci disabled = true; 19708c2ecf20Sopenharmony_ci } 19718c2ecf20Sopenharmony_ci } 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci trigger_off(&auxtrace_snapshot_trigger); 19748c2ecf20Sopenharmony_ci trigger_off(&switch_output_trigger); 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci if (opts->auxtrace_snapshot_on_exit) 19778c2ecf20Sopenharmony_ci record__auxtrace_snapshot_exit(rec); 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci if (forks && workload_exec_errno) { 19808c2ecf20Sopenharmony_ci char msg[STRERR_BUFSIZE]; 19818c2ecf20Sopenharmony_ci const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 19828c2ecf20Sopenharmony_ci pr_err("Workload failed: %s\n", emsg); 19838c2ecf20Sopenharmony_ci err = -1; 19848c2ecf20Sopenharmony_ci goto out_child; 19858c2ecf20Sopenharmony_ci } 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci if (!quiet) 19888c2ecf20Sopenharmony_ci fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_ci if (target__none(&rec->opts.target)) 19918c2ecf20Sopenharmony_ci record__synthesize_workload(rec, true); 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ciout_child: 19948c2ecf20Sopenharmony_ci evlist__finalize_ctlfd(rec->evlist); 19958c2ecf20Sopenharmony_ci record__mmap_read_all(rec, true); 19968c2ecf20Sopenharmony_ci record__aio_mmap_read_sync(rec); 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci if (rec->session->bytes_transferred && rec->session->bytes_compressed) { 19998c2ecf20Sopenharmony_ci ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed; 20008c2ecf20Sopenharmony_ci session->header.env.comp_ratio = ratio + 0.5; 20018c2ecf20Sopenharmony_ci } 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci if (forks) { 20048c2ecf20Sopenharmony_ci int exit_status; 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci if (!child_finished) 20078c2ecf20Sopenharmony_ci kill(rec->evlist->workload.pid, SIGTERM); 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci wait(&exit_status); 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci if (err < 0) 20128c2ecf20Sopenharmony_ci status = err; 20138c2ecf20Sopenharmony_ci else if (WIFEXITED(exit_status)) 20148c2ecf20Sopenharmony_ci status = WEXITSTATUS(exit_status); 20158c2ecf20Sopenharmony_ci else if (WIFSIGNALED(exit_status)) 20168c2ecf20Sopenharmony_ci signr = WTERMSIG(exit_status); 20178c2ecf20Sopenharmony_ci } else 20188c2ecf20Sopenharmony_ci status = err; 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci record__synthesize(rec, true); 20218c2ecf20Sopenharmony_ci /* this will be recalculated during process_buildids() */ 20228c2ecf20Sopenharmony_ci rec->samples = 0; 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_ci if (!err) { 20258c2ecf20Sopenharmony_ci if (!rec->timestamp_filename) { 20268c2ecf20Sopenharmony_ci record__finish_output(rec); 20278c2ecf20Sopenharmony_ci } else { 20288c2ecf20Sopenharmony_ci fd = record__switch_output(rec, true); 20298c2ecf20Sopenharmony_ci if (fd < 0) { 20308c2ecf20Sopenharmony_ci status = fd; 20318c2ecf20Sopenharmony_ci goto out_delete_session; 20328c2ecf20Sopenharmony_ci } 20338c2ecf20Sopenharmony_ci } 20348c2ecf20Sopenharmony_ci } 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci perf_hooks__invoke_record_end(); 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci if (!err && !quiet) { 20398c2ecf20Sopenharmony_ci char samples[128]; 20408c2ecf20Sopenharmony_ci const char *postfix = rec->timestamp_filename ? 20418c2ecf20Sopenharmony_ci ".<timestamp>" : ""; 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci if (rec->samples && !rec->opts.full_auxtrace) 20448c2ecf20Sopenharmony_ci scnprintf(samples, sizeof(samples), 20458c2ecf20Sopenharmony_ci " (%" PRIu64 " samples)", rec->samples); 20468c2ecf20Sopenharmony_ci else 20478c2ecf20Sopenharmony_ci samples[0] = '\0'; 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s", 20508c2ecf20Sopenharmony_ci perf_data__size(data) / 1024.0 / 1024.0, 20518c2ecf20Sopenharmony_ci data->path, postfix, samples); 20528c2ecf20Sopenharmony_ci if (ratio) { 20538c2ecf20Sopenharmony_ci fprintf(stderr, ", compressed (original %.3f MB, ratio is %.3f)", 20548c2ecf20Sopenharmony_ci rec->session->bytes_transferred / 1024.0 / 1024.0, 20558c2ecf20Sopenharmony_ci ratio); 20568c2ecf20Sopenharmony_ci } 20578c2ecf20Sopenharmony_ci fprintf(stderr, " ]\n"); 20588c2ecf20Sopenharmony_ci } 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ciout_delete_session: 20618c2ecf20Sopenharmony_ci#ifdef HAVE_EVENTFD_SUPPORT 20628c2ecf20Sopenharmony_ci if (done_fd >= 0) 20638c2ecf20Sopenharmony_ci close(done_fd); 20648c2ecf20Sopenharmony_ci#endif 20658c2ecf20Sopenharmony_ci zstd_fini(&session->zstd_data); 20668c2ecf20Sopenharmony_ci perf_session__delete(session); 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci if (!opts->no_bpf_event) 20698c2ecf20Sopenharmony_ci perf_evlist__stop_sb_thread(rec->sb_evlist); 20708c2ecf20Sopenharmony_ci return status; 20718c2ecf20Sopenharmony_ci} 20728c2ecf20Sopenharmony_ci 20738c2ecf20Sopenharmony_cistatic void callchain_debug(struct callchain_param *callchain) 20748c2ecf20Sopenharmony_ci{ 20758c2ecf20Sopenharmony_ci static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci pr_debug("callchain: type %s\n", str[callchain->record_mode]); 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci if (callchain->record_mode == CALLCHAIN_DWARF) 20808c2ecf20Sopenharmony_ci pr_debug("callchain: stack dump size %d\n", 20818c2ecf20Sopenharmony_ci callchain->dump_size); 20828c2ecf20Sopenharmony_ci} 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ciint record_opts__parse_callchain(struct record_opts *record, 20858c2ecf20Sopenharmony_ci struct callchain_param *callchain, 20868c2ecf20Sopenharmony_ci const char *arg, bool unset) 20878c2ecf20Sopenharmony_ci{ 20888c2ecf20Sopenharmony_ci int ret; 20898c2ecf20Sopenharmony_ci callchain->enabled = !unset; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci /* --no-call-graph */ 20928c2ecf20Sopenharmony_ci if (unset) { 20938c2ecf20Sopenharmony_ci callchain->record_mode = CALLCHAIN_NONE; 20948c2ecf20Sopenharmony_ci pr_debug("callchain: disabled\n"); 20958c2ecf20Sopenharmony_ci return 0; 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci ret = parse_callchain_record_opt(arg, callchain); 20998c2ecf20Sopenharmony_ci if (!ret) { 21008c2ecf20Sopenharmony_ci /* Enable data address sampling for DWARF unwind. */ 21018c2ecf20Sopenharmony_ci if (callchain->record_mode == CALLCHAIN_DWARF) 21028c2ecf20Sopenharmony_ci record->sample_address = true; 21038c2ecf20Sopenharmony_ci callchain_debug(callchain); 21048c2ecf20Sopenharmony_ci } 21058c2ecf20Sopenharmony_ci 21068c2ecf20Sopenharmony_ci return ret; 21078c2ecf20Sopenharmony_ci} 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ciint record_parse_callchain_opt(const struct option *opt, 21108c2ecf20Sopenharmony_ci const char *arg, 21118c2ecf20Sopenharmony_ci int unset) 21128c2ecf20Sopenharmony_ci{ 21138c2ecf20Sopenharmony_ci return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 21148c2ecf20Sopenharmony_ci} 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ciint record_callchain_opt(const struct option *opt, 21178c2ecf20Sopenharmony_ci const char *arg __maybe_unused, 21188c2ecf20Sopenharmony_ci int unset __maybe_unused) 21198c2ecf20Sopenharmony_ci{ 21208c2ecf20Sopenharmony_ci struct callchain_param *callchain = opt->value; 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci callchain->enabled = true; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci if (callchain->record_mode == CALLCHAIN_NONE) 21258c2ecf20Sopenharmony_ci callchain->record_mode = CALLCHAIN_FP; 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci callchain_debug(callchain); 21288c2ecf20Sopenharmony_ci return 0; 21298c2ecf20Sopenharmony_ci} 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_cistatic int perf_record_config(const char *var, const char *value, void *cb) 21328c2ecf20Sopenharmony_ci{ 21338c2ecf20Sopenharmony_ci struct record *rec = cb; 21348c2ecf20Sopenharmony_ci 21358c2ecf20Sopenharmony_ci if (!strcmp(var, "record.build-id")) { 21368c2ecf20Sopenharmony_ci if (!strcmp(value, "cache")) 21378c2ecf20Sopenharmony_ci rec->no_buildid_cache = false; 21388c2ecf20Sopenharmony_ci else if (!strcmp(value, "no-cache")) 21398c2ecf20Sopenharmony_ci rec->no_buildid_cache = true; 21408c2ecf20Sopenharmony_ci else if (!strcmp(value, "skip")) 21418c2ecf20Sopenharmony_ci rec->no_buildid = true; 21428c2ecf20Sopenharmony_ci else 21438c2ecf20Sopenharmony_ci return -1; 21448c2ecf20Sopenharmony_ci return 0; 21458c2ecf20Sopenharmony_ci } 21468c2ecf20Sopenharmony_ci if (!strcmp(var, "record.call-graph")) { 21478c2ecf20Sopenharmony_ci var = "call-graph.record-mode"; 21488c2ecf20Sopenharmony_ci return perf_default_config(var, value, cb); 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci#ifdef HAVE_AIO_SUPPORT 21518c2ecf20Sopenharmony_ci if (!strcmp(var, "record.aio")) { 21528c2ecf20Sopenharmony_ci rec->opts.nr_cblocks = strtol(value, NULL, 0); 21538c2ecf20Sopenharmony_ci if (!rec->opts.nr_cblocks) 21548c2ecf20Sopenharmony_ci rec->opts.nr_cblocks = nr_cblocks_default; 21558c2ecf20Sopenharmony_ci } 21568c2ecf20Sopenharmony_ci#endif 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci return 0; 21598c2ecf20Sopenharmony_ci} 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_cistatic int record__parse_affinity(const struct option *opt, const char *str, int unset) 21638c2ecf20Sopenharmony_ci{ 21648c2ecf20Sopenharmony_ci struct record_opts *opts = (struct record_opts *)opt->value; 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci if (unset || !str) 21678c2ecf20Sopenharmony_ci return 0; 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci if (!strcasecmp(str, "node")) 21708c2ecf20Sopenharmony_ci opts->affinity = PERF_AFFINITY_NODE; 21718c2ecf20Sopenharmony_ci else if (!strcasecmp(str, "cpu")) 21728c2ecf20Sopenharmony_ci opts->affinity = PERF_AFFINITY_CPU; 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci return 0; 21758c2ecf20Sopenharmony_ci} 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_cistatic int parse_output_max_size(const struct option *opt, 21788c2ecf20Sopenharmony_ci const char *str, int unset) 21798c2ecf20Sopenharmony_ci{ 21808c2ecf20Sopenharmony_ci unsigned long *s = (unsigned long *)opt->value; 21818c2ecf20Sopenharmony_ci static struct parse_tag tags_size[] = { 21828c2ecf20Sopenharmony_ci { .tag = 'B', .mult = 1 }, 21838c2ecf20Sopenharmony_ci { .tag = 'K', .mult = 1 << 10 }, 21848c2ecf20Sopenharmony_ci { .tag = 'M', .mult = 1 << 20 }, 21858c2ecf20Sopenharmony_ci { .tag = 'G', .mult = 1 << 30 }, 21868c2ecf20Sopenharmony_ci { .tag = 0 }, 21878c2ecf20Sopenharmony_ci }; 21888c2ecf20Sopenharmony_ci unsigned long val; 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci if (unset) { 21918c2ecf20Sopenharmony_ci *s = 0; 21928c2ecf20Sopenharmony_ci return 0; 21938c2ecf20Sopenharmony_ci } 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci val = parse_tag_value(str, tags_size); 21968c2ecf20Sopenharmony_ci if (val != (unsigned long) -1) { 21978c2ecf20Sopenharmony_ci *s = val; 21988c2ecf20Sopenharmony_ci return 0; 21998c2ecf20Sopenharmony_ci } 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci return -1; 22028c2ecf20Sopenharmony_ci} 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_cistatic int record__parse_mmap_pages(const struct option *opt, 22058c2ecf20Sopenharmony_ci const char *str, 22068c2ecf20Sopenharmony_ci int unset __maybe_unused) 22078c2ecf20Sopenharmony_ci{ 22088c2ecf20Sopenharmony_ci struct record_opts *opts = opt->value; 22098c2ecf20Sopenharmony_ci char *s, *p; 22108c2ecf20Sopenharmony_ci unsigned int mmap_pages; 22118c2ecf20Sopenharmony_ci int ret; 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci if (!str) 22148c2ecf20Sopenharmony_ci return -EINVAL; 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci s = strdup(str); 22178c2ecf20Sopenharmony_ci if (!s) 22188c2ecf20Sopenharmony_ci return -ENOMEM; 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_ci p = strchr(s, ','); 22218c2ecf20Sopenharmony_ci if (p) 22228c2ecf20Sopenharmony_ci *p = '\0'; 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci if (*s) { 22258c2ecf20Sopenharmony_ci ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 22268c2ecf20Sopenharmony_ci if (ret) 22278c2ecf20Sopenharmony_ci goto out_free; 22288c2ecf20Sopenharmony_ci opts->mmap_pages = mmap_pages; 22298c2ecf20Sopenharmony_ci } 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci if (!p) { 22328c2ecf20Sopenharmony_ci ret = 0; 22338c2ecf20Sopenharmony_ci goto out_free; 22348c2ecf20Sopenharmony_ci } 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 22378c2ecf20Sopenharmony_ci if (ret) 22388c2ecf20Sopenharmony_ci goto out_free; 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci opts->auxtrace_mmap_pages = mmap_pages; 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ciout_free: 22438c2ecf20Sopenharmony_ci free(s); 22448c2ecf20Sopenharmony_ci return ret; 22458c2ecf20Sopenharmony_ci} 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_cistatic int parse_control_option(const struct option *opt, 22488c2ecf20Sopenharmony_ci const char *str, 22498c2ecf20Sopenharmony_ci int unset __maybe_unused) 22508c2ecf20Sopenharmony_ci{ 22518c2ecf20Sopenharmony_ci struct record_opts *opts = opt->value; 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci return evlist__parse_control(str, &opts->ctl_fd, &opts->ctl_fd_ack, &opts->ctl_fd_close); 22548c2ecf20Sopenharmony_ci} 22558c2ecf20Sopenharmony_ci 22568c2ecf20Sopenharmony_cistatic void switch_output_size_warn(struct record *rec) 22578c2ecf20Sopenharmony_ci{ 22588c2ecf20Sopenharmony_ci u64 wakeup_size = evlist__mmap_size(rec->opts.mmap_pages); 22598c2ecf20Sopenharmony_ci struct switch_output *s = &rec->switch_output; 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci wakeup_size /= 2; 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_ci if (s->size < wakeup_size) { 22648c2ecf20Sopenharmony_ci char buf[100]; 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_ci unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 22678c2ecf20Sopenharmony_ci pr_warning("WARNING: switch-output data size lower than " 22688c2ecf20Sopenharmony_ci "wakeup kernel buffer size (%s) " 22698c2ecf20Sopenharmony_ci "expect bigger perf.data sizes\n", buf); 22708c2ecf20Sopenharmony_ci } 22718c2ecf20Sopenharmony_ci} 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_cistatic int switch_output_setup(struct record *rec) 22748c2ecf20Sopenharmony_ci{ 22758c2ecf20Sopenharmony_ci struct switch_output *s = &rec->switch_output; 22768c2ecf20Sopenharmony_ci static struct parse_tag tags_size[] = { 22778c2ecf20Sopenharmony_ci { .tag = 'B', .mult = 1 }, 22788c2ecf20Sopenharmony_ci { .tag = 'K', .mult = 1 << 10 }, 22798c2ecf20Sopenharmony_ci { .tag = 'M', .mult = 1 << 20 }, 22808c2ecf20Sopenharmony_ci { .tag = 'G', .mult = 1 << 30 }, 22818c2ecf20Sopenharmony_ci { .tag = 0 }, 22828c2ecf20Sopenharmony_ci }; 22838c2ecf20Sopenharmony_ci static struct parse_tag tags_time[] = { 22848c2ecf20Sopenharmony_ci { .tag = 's', .mult = 1 }, 22858c2ecf20Sopenharmony_ci { .tag = 'm', .mult = 60 }, 22868c2ecf20Sopenharmony_ci { .tag = 'h', .mult = 60*60 }, 22878c2ecf20Sopenharmony_ci { .tag = 'd', .mult = 60*60*24 }, 22888c2ecf20Sopenharmony_ci { .tag = 0 }, 22898c2ecf20Sopenharmony_ci }; 22908c2ecf20Sopenharmony_ci unsigned long val; 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci /* 22938c2ecf20Sopenharmony_ci * If we're using --switch-output-events, then we imply its 22948c2ecf20Sopenharmony_ci * --switch-output=signal, as we'll send a SIGUSR2 from the side band 22958c2ecf20Sopenharmony_ci * thread to its parent. 22968c2ecf20Sopenharmony_ci */ 22978c2ecf20Sopenharmony_ci if (rec->switch_output_event_set) 22988c2ecf20Sopenharmony_ci goto do_signal; 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci if (!s->set) 23018c2ecf20Sopenharmony_ci return 0; 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci if (!strcmp(s->str, "signal")) { 23048c2ecf20Sopenharmony_cido_signal: 23058c2ecf20Sopenharmony_ci s->signal = true; 23068c2ecf20Sopenharmony_ci pr_debug("switch-output with SIGUSR2 signal\n"); 23078c2ecf20Sopenharmony_ci goto enabled; 23088c2ecf20Sopenharmony_ci } 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci val = parse_tag_value(s->str, tags_size); 23118c2ecf20Sopenharmony_ci if (val != (unsigned long) -1) { 23128c2ecf20Sopenharmony_ci s->size = val; 23138c2ecf20Sopenharmony_ci pr_debug("switch-output with %s size threshold\n", s->str); 23148c2ecf20Sopenharmony_ci goto enabled; 23158c2ecf20Sopenharmony_ci } 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci val = parse_tag_value(s->str, tags_time); 23188c2ecf20Sopenharmony_ci if (val != (unsigned long) -1) { 23198c2ecf20Sopenharmony_ci s->time = val; 23208c2ecf20Sopenharmony_ci pr_debug("switch-output with %s time threshold (%lu seconds)\n", 23218c2ecf20Sopenharmony_ci s->str, s->time); 23228c2ecf20Sopenharmony_ci goto enabled; 23238c2ecf20Sopenharmony_ci } 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci return -1; 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_cienabled: 23288c2ecf20Sopenharmony_ci rec->timestamp_filename = true; 23298c2ecf20Sopenharmony_ci s->enabled = true; 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci if (s->size && !rec->opts.no_buffering) 23328c2ecf20Sopenharmony_ci switch_output_size_warn(rec); 23338c2ecf20Sopenharmony_ci 23348c2ecf20Sopenharmony_ci return 0; 23358c2ecf20Sopenharmony_ci} 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_cistatic const char * const __record_usage[] = { 23388c2ecf20Sopenharmony_ci "perf record [<options>] [<command>]", 23398c2ecf20Sopenharmony_ci "perf record [<options>] -- <command> [<options>]", 23408c2ecf20Sopenharmony_ci NULL 23418c2ecf20Sopenharmony_ci}; 23428c2ecf20Sopenharmony_ciconst char * const *record_usage = __record_usage; 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_cistatic int build_id__process_mmap(struct perf_tool *tool, union perf_event *event, 23458c2ecf20Sopenharmony_ci struct perf_sample *sample, struct machine *machine) 23468c2ecf20Sopenharmony_ci{ 23478c2ecf20Sopenharmony_ci /* 23488c2ecf20Sopenharmony_ci * We already have the kernel maps, put in place via perf_session__create_kernel_maps() 23498c2ecf20Sopenharmony_ci * no need to add them twice. 23508c2ecf20Sopenharmony_ci */ 23518c2ecf20Sopenharmony_ci if (!(event->header.misc & PERF_RECORD_MISC_USER)) 23528c2ecf20Sopenharmony_ci return 0; 23538c2ecf20Sopenharmony_ci return perf_event__process_mmap(tool, event, sample, machine); 23548c2ecf20Sopenharmony_ci} 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_cistatic int build_id__process_mmap2(struct perf_tool *tool, union perf_event *event, 23578c2ecf20Sopenharmony_ci struct perf_sample *sample, struct machine *machine) 23588c2ecf20Sopenharmony_ci{ 23598c2ecf20Sopenharmony_ci /* 23608c2ecf20Sopenharmony_ci * We already have the kernel maps, put in place via perf_session__create_kernel_maps() 23618c2ecf20Sopenharmony_ci * no need to add them twice. 23628c2ecf20Sopenharmony_ci */ 23638c2ecf20Sopenharmony_ci if (!(event->header.misc & PERF_RECORD_MISC_USER)) 23648c2ecf20Sopenharmony_ci return 0; 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci return perf_event__process_mmap2(tool, event, sample, machine); 23678c2ecf20Sopenharmony_ci} 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci/* 23708c2ecf20Sopenharmony_ci * XXX Ideally would be local to cmd_record() and passed to a record__new 23718c2ecf20Sopenharmony_ci * because we need to have access to it in record__exit, that is called 23728c2ecf20Sopenharmony_ci * after cmd_record() exits, but since record_options need to be accessible to 23738c2ecf20Sopenharmony_ci * builtin-script, leave it here. 23748c2ecf20Sopenharmony_ci * 23758c2ecf20Sopenharmony_ci * At least we don't ouch it in all the other functions here directly. 23768c2ecf20Sopenharmony_ci * 23778c2ecf20Sopenharmony_ci * Just say no to tons of global variables, sigh. 23788c2ecf20Sopenharmony_ci */ 23798c2ecf20Sopenharmony_cistatic struct record record = { 23808c2ecf20Sopenharmony_ci .opts = { 23818c2ecf20Sopenharmony_ci .sample_time = true, 23828c2ecf20Sopenharmony_ci .mmap_pages = UINT_MAX, 23838c2ecf20Sopenharmony_ci .user_freq = UINT_MAX, 23848c2ecf20Sopenharmony_ci .user_interval = ULLONG_MAX, 23858c2ecf20Sopenharmony_ci .freq = 4000, 23868c2ecf20Sopenharmony_ci .target = { 23878c2ecf20Sopenharmony_ci .uses_mmap = true, 23888c2ecf20Sopenharmony_ci .default_per_cpu = true, 23898c2ecf20Sopenharmony_ci }, 23908c2ecf20Sopenharmony_ci .mmap_flush = MMAP_FLUSH_DEFAULT, 23918c2ecf20Sopenharmony_ci .nr_threads_synthesize = 1, 23928c2ecf20Sopenharmony_ci .ctl_fd = -1, 23938c2ecf20Sopenharmony_ci .ctl_fd_ack = -1, 23948c2ecf20Sopenharmony_ci }, 23958c2ecf20Sopenharmony_ci .tool = { 23968c2ecf20Sopenharmony_ci .sample = process_sample_event, 23978c2ecf20Sopenharmony_ci .fork = perf_event__process_fork, 23988c2ecf20Sopenharmony_ci .exit = perf_event__process_exit, 23998c2ecf20Sopenharmony_ci .comm = perf_event__process_comm, 24008c2ecf20Sopenharmony_ci .namespaces = perf_event__process_namespaces, 24018c2ecf20Sopenharmony_ci .mmap = build_id__process_mmap, 24028c2ecf20Sopenharmony_ci .mmap2 = build_id__process_mmap2, 24038c2ecf20Sopenharmony_ci .ordered_events = true, 24048c2ecf20Sopenharmony_ci }, 24058c2ecf20Sopenharmony_ci}; 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_ciconst char record_callchain_help[] = CALLCHAIN_RECORD_HELP 24088c2ecf20Sopenharmony_ci "\n\t\t\t\tDefault: fp"; 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_cistatic bool dry_run; 24118c2ecf20Sopenharmony_ci 24128c2ecf20Sopenharmony_ci/* 24138c2ecf20Sopenharmony_ci * XXX Will stay a global variable till we fix builtin-script.c to stop messing 24148c2ecf20Sopenharmony_ci * with it and switch to use the library functions in perf_evlist that came 24158c2ecf20Sopenharmony_ci * from builtin-record.c, i.e. use record_opts, 24168c2ecf20Sopenharmony_ci * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 24178c2ecf20Sopenharmony_ci * using pipes, etc. 24188c2ecf20Sopenharmony_ci */ 24198c2ecf20Sopenharmony_cistatic struct option __record_options[] = { 24208c2ecf20Sopenharmony_ci OPT_CALLBACK('e', "event", &record.evlist, "event", 24218c2ecf20Sopenharmony_ci "event selector. use 'perf list' to list available events", 24228c2ecf20Sopenharmony_ci parse_events_option), 24238c2ecf20Sopenharmony_ci OPT_CALLBACK(0, "filter", &record.evlist, "filter", 24248c2ecf20Sopenharmony_ci "event filter", parse_filter), 24258c2ecf20Sopenharmony_ci OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 24268c2ecf20Sopenharmony_ci NULL, "don't record events from perf itself", 24278c2ecf20Sopenharmony_ci exclude_perf), 24288c2ecf20Sopenharmony_ci OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 24298c2ecf20Sopenharmony_ci "record events on existing process id"), 24308c2ecf20Sopenharmony_ci OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 24318c2ecf20Sopenharmony_ci "record events on existing thread id"), 24328c2ecf20Sopenharmony_ci OPT_INTEGER('r', "realtime", &record.realtime_prio, 24338c2ecf20Sopenharmony_ci "collect data with this RT SCHED_FIFO priority"), 24348c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 24358c2ecf20Sopenharmony_ci "collect data without buffering"), 24368c2ecf20Sopenharmony_ci OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 24378c2ecf20Sopenharmony_ci "collect raw sample records from all opened counters"), 24388c2ecf20Sopenharmony_ci OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 24398c2ecf20Sopenharmony_ci "system-wide collection from all CPUs"), 24408c2ecf20Sopenharmony_ci OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 24418c2ecf20Sopenharmony_ci "list of cpus to monitor"), 24428c2ecf20Sopenharmony_ci OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 24438c2ecf20Sopenharmony_ci OPT_STRING('o', "output", &record.data.path, "file", 24448c2ecf20Sopenharmony_ci "output file name"), 24458c2ecf20Sopenharmony_ci OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 24468c2ecf20Sopenharmony_ci &record.opts.no_inherit_set, 24478c2ecf20Sopenharmony_ci "child tasks do not inherit counters"), 24488c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 24498c2ecf20Sopenharmony_ci "synthesize non-sample events at the end of output"), 24508c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 24518c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "do not record bpf events"), 24528c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 24538c2ecf20Sopenharmony_ci "Fail if the specified frequency can't be used"), 24548c2ecf20Sopenharmony_ci OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 24558c2ecf20Sopenharmony_ci "profile at this frequency", 24568c2ecf20Sopenharmony_ci record__parse_freq), 24578c2ecf20Sopenharmony_ci OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 24588c2ecf20Sopenharmony_ci "number of mmap data pages and AUX area tracing mmap pages", 24598c2ecf20Sopenharmony_ci record__parse_mmap_pages), 24608c2ecf20Sopenharmony_ci OPT_CALLBACK(0, "mmap-flush", &record.opts, "number", 24618c2ecf20Sopenharmony_ci "Minimal number of bytes that is extracted from mmap data pages (default: 1)", 24628c2ecf20Sopenharmony_ci record__mmap_flush_parse), 24638c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "group", &record.opts.group, 24648c2ecf20Sopenharmony_ci "put the counters into a counter group"), 24658c2ecf20Sopenharmony_ci OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 24668c2ecf20Sopenharmony_ci NULL, "enables call-graph recording" , 24678c2ecf20Sopenharmony_ci &record_callchain_opt), 24688c2ecf20Sopenharmony_ci OPT_CALLBACK(0, "call-graph", &record.opts, 24698c2ecf20Sopenharmony_ci "record_mode[,record_size]", record_callchain_help, 24708c2ecf20Sopenharmony_ci &record_parse_callchain_opt), 24718c2ecf20Sopenharmony_ci OPT_INCR('v', "verbose", &verbose, 24728c2ecf20Sopenharmony_ci "be more verbose (show counter open errors, etc)"), 24738c2ecf20Sopenharmony_ci OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 24748c2ecf20Sopenharmony_ci OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 24758c2ecf20Sopenharmony_ci "per thread counts"), 24768c2ecf20Sopenharmony_ci OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 24778c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 24788c2ecf20Sopenharmony_ci "Record the sample physical addresses"), 24798c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 24808c2ecf20Sopenharmony_ci OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 24818c2ecf20Sopenharmony_ci &record.opts.sample_time_set, 24828c2ecf20Sopenharmony_ci "Record the sample timestamps"), 24838c2ecf20Sopenharmony_ci OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set, 24848c2ecf20Sopenharmony_ci "Record the sample period"), 24858c2ecf20Sopenharmony_ci OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 24868c2ecf20Sopenharmony_ci "don't sample"), 24878c2ecf20Sopenharmony_ci OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 24888c2ecf20Sopenharmony_ci &record.no_buildid_cache_set, 24898c2ecf20Sopenharmony_ci "do not update the buildid cache"), 24908c2ecf20Sopenharmony_ci OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 24918c2ecf20Sopenharmony_ci &record.no_buildid_set, 24928c2ecf20Sopenharmony_ci "do not collect buildids in perf.data"), 24938c2ecf20Sopenharmony_ci OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 24948c2ecf20Sopenharmony_ci "monitor event in cgroup name only", 24958c2ecf20Sopenharmony_ci parse_cgroups), 24968c2ecf20Sopenharmony_ci OPT_INTEGER('D', "delay", &record.opts.initial_delay, 24978c2ecf20Sopenharmony_ci "ms to wait before starting measurement after program start (-1: start with events disabled)"), 24988c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "kcore", &record.opts.kcore, "copy /proc/kcore"), 24998c2ecf20Sopenharmony_ci OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 25008c2ecf20Sopenharmony_ci "user to profile"), 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 25038c2ecf20Sopenharmony_ci "branch any", "sample any taken branches", 25048c2ecf20Sopenharmony_ci parse_branch_stack), 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 25078c2ecf20Sopenharmony_ci "branch filter mask", "branch stack filter modes", 25088c2ecf20Sopenharmony_ci parse_branch_stack), 25098c2ecf20Sopenharmony_ci OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 25108c2ecf20Sopenharmony_ci "sample by weight (on special events only)"), 25118c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 25128c2ecf20Sopenharmony_ci "sample transaction flags (special events only)"), 25138c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 25148c2ecf20Sopenharmony_ci "use per-thread mmaps"), 25158c2ecf20Sopenharmony_ci OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 25168c2ecf20Sopenharmony_ci "sample selected machine registers on interrupt," 25178c2ecf20Sopenharmony_ci " use '-I?' to list register names", parse_intr_regs), 25188c2ecf20Sopenharmony_ci OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 25198c2ecf20Sopenharmony_ci "sample selected machine registers on interrupt," 25208c2ecf20Sopenharmony_ci " use '--user-regs=?' to list register names", parse_user_regs), 25218c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 25228c2ecf20Sopenharmony_ci "Record running/enabled time of read (:S) events"), 25238c2ecf20Sopenharmony_ci OPT_CALLBACK('k', "clockid", &record.opts, 25248c2ecf20Sopenharmony_ci "clockid", "clockid to use for events, see clock_gettime()", 25258c2ecf20Sopenharmony_ci parse_clockid), 25268c2ecf20Sopenharmony_ci OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 25278c2ecf20Sopenharmony_ci "opts", "AUX area tracing Snapshot Mode", ""), 25288c2ecf20Sopenharmony_ci OPT_STRING_OPTARG(0, "aux-sample", &record.opts.auxtrace_sample_opts, 25298c2ecf20Sopenharmony_ci "opts", "sample AUX area", ""), 25308c2ecf20Sopenharmony_ci OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout, 25318c2ecf20Sopenharmony_ci "per thread proc mmap processing timeout in ms"), 25328c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 25338c2ecf20Sopenharmony_ci "Record namespaces events"), 25348c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "all-cgroups", &record.opts.record_cgroup, 25358c2ecf20Sopenharmony_ci "Record cgroup events"), 25368c2ecf20Sopenharmony_ci OPT_BOOLEAN_SET(0, "switch-events", &record.opts.record_switch_events, 25378c2ecf20Sopenharmony_ci &record.opts.record_switch_events_set, 25388c2ecf20Sopenharmony_ci "Record context switch events"), 25398c2ecf20Sopenharmony_ci OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 25408c2ecf20Sopenharmony_ci "Configure all used events to run in kernel space.", 25418c2ecf20Sopenharmony_ci PARSE_OPT_EXCLUSIVE), 25428c2ecf20Sopenharmony_ci OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 25438c2ecf20Sopenharmony_ci "Configure all used events to run in user space.", 25448c2ecf20Sopenharmony_ci PARSE_OPT_EXCLUSIVE), 25458c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains, 25468c2ecf20Sopenharmony_ci "collect kernel callchains"), 25478c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains, 25488c2ecf20Sopenharmony_ci "collect user callchains"), 25498c2ecf20Sopenharmony_ci OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 25508c2ecf20Sopenharmony_ci "clang binary to use for compiling BPF scriptlets"), 25518c2ecf20Sopenharmony_ci OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 25528c2ecf20Sopenharmony_ci "options passed to clang when compiling BPF scriptlets"), 25538c2ecf20Sopenharmony_ci OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 25548c2ecf20Sopenharmony_ci "file", "vmlinux pathname"), 25558c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 25568c2ecf20Sopenharmony_ci "Record build-id of all DSOs regardless of hits"), 25578c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 25588c2ecf20Sopenharmony_ci "append timestamp to output filename"), 25598c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 25608c2ecf20Sopenharmony_ci "Record timestamp boundary (time of first/last samples)"), 25618c2ecf20Sopenharmony_ci OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 25628c2ecf20Sopenharmony_ci &record.switch_output.set, "signal or size[BKMG] or time[smhd]", 25638c2ecf20Sopenharmony_ci "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold", 25648c2ecf20Sopenharmony_ci "signal"), 25658c2ecf20Sopenharmony_ci OPT_CALLBACK_SET(0, "switch-output-event", &record.sb_evlist, &record.switch_output_event_set, "switch output event", 25668c2ecf20Sopenharmony_ci "switch output event selector. use 'perf list' to list available events", 25678c2ecf20Sopenharmony_ci parse_events_option_new_evlist), 25688c2ecf20Sopenharmony_ci OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, 25698c2ecf20Sopenharmony_ci "Limit number of switch output generated files"), 25708c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "dry-run", &dry_run, 25718c2ecf20Sopenharmony_ci "Parse options then exit"), 25728c2ecf20Sopenharmony_ci#ifdef HAVE_AIO_SUPPORT 25738c2ecf20Sopenharmony_ci OPT_CALLBACK_OPTARG(0, "aio", &record.opts, 25748c2ecf20Sopenharmony_ci &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)", 25758c2ecf20Sopenharmony_ci record__aio_parse), 25768c2ecf20Sopenharmony_ci#endif 25778c2ecf20Sopenharmony_ci OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", 25788c2ecf20Sopenharmony_ci "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", 25798c2ecf20Sopenharmony_ci record__parse_affinity), 25808c2ecf20Sopenharmony_ci#ifdef HAVE_ZSTD_SUPPORT 25818c2ecf20Sopenharmony_ci OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default, 25828c2ecf20Sopenharmony_ci "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)", 25838c2ecf20Sopenharmony_ci record__parse_comp_level), 25848c2ecf20Sopenharmony_ci#endif 25858c2ecf20Sopenharmony_ci OPT_CALLBACK(0, "max-size", &record.output_max_size, 25868c2ecf20Sopenharmony_ci "size", "Limit the maximum size of the output file", parse_output_max_size), 25878c2ecf20Sopenharmony_ci OPT_UINTEGER(0, "num-thread-synthesize", 25888c2ecf20Sopenharmony_ci &record.opts.nr_threads_synthesize, 25898c2ecf20Sopenharmony_ci "number of threads to run for event synthesis"), 25908c2ecf20Sopenharmony_ci#ifdef HAVE_LIBPFM 25918c2ecf20Sopenharmony_ci OPT_CALLBACK(0, "pfm-events", &record.evlist, "event", 25928c2ecf20Sopenharmony_ci "libpfm4 event selector. use 'perf list' to list available events", 25938c2ecf20Sopenharmony_ci parse_libpfm_events_option), 25948c2ecf20Sopenharmony_ci#endif 25958c2ecf20Sopenharmony_ci OPT_CALLBACK(0, "control", &record.opts, "fd:ctl-fd[,ack-fd] or fifo:ctl-fifo[,ack-fifo]", 25968c2ecf20Sopenharmony_ci "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events,\n" 25978c2ecf20Sopenharmony_ci "\t\t\t 'snapshot': AUX area tracing snapshot).\n" 25988c2ecf20Sopenharmony_ci "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.\n" 25998c2ecf20Sopenharmony_ci "\t\t\t Alternatively, ctl-fifo / ack-fifo will be opened and used as ctl-fd / ack-fd.", 26008c2ecf20Sopenharmony_ci parse_control_option), 26018c2ecf20Sopenharmony_ci OPT_END() 26028c2ecf20Sopenharmony_ci}; 26038c2ecf20Sopenharmony_ci 26048c2ecf20Sopenharmony_cistruct option *record_options = __record_options; 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ciint cmd_record(int argc, const char **argv) 26078c2ecf20Sopenharmony_ci{ 26088c2ecf20Sopenharmony_ci int err; 26098c2ecf20Sopenharmony_ci struct record *rec = &record; 26108c2ecf20Sopenharmony_ci char errbuf[BUFSIZ]; 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci setlocale(LC_ALL, ""); 26138c2ecf20Sopenharmony_ci 26148c2ecf20Sopenharmony_ci#ifndef HAVE_LIBBPF_SUPPORT 26158c2ecf20Sopenharmony_ci# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 26168c2ecf20Sopenharmony_ci set_nobuild('\0', "clang-path", true); 26178c2ecf20Sopenharmony_ci set_nobuild('\0', "clang-opt", true); 26188c2ecf20Sopenharmony_ci# undef set_nobuild 26198c2ecf20Sopenharmony_ci#endif 26208c2ecf20Sopenharmony_ci 26218c2ecf20Sopenharmony_ci#ifndef HAVE_BPF_PROLOGUE 26228c2ecf20Sopenharmony_ci# if !defined (HAVE_DWARF_SUPPORT) 26238c2ecf20Sopenharmony_ci# define REASON "NO_DWARF=1" 26248c2ecf20Sopenharmony_ci# elif !defined (HAVE_LIBBPF_SUPPORT) 26258c2ecf20Sopenharmony_ci# define REASON "NO_LIBBPF=1" 26268c2ecf20Sopenharmony_ci# else 26278c2ecf20Sopenharmony_ci# define REASON "this architecture doesn't support BPF prologue" 26288c2ecf20Sopenharmony_ci# endif 26298c2ecf20Sopenharmony_ci# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 26308c2ecf20Sopenharmony_ci set_nobuild('\0', "vmlinux", true); 26318c2ecf20Sopenharmony_ci# undef set_nobuild 26328c2ecf20Sopenharmony_ci# undef REASON 26338c2ecf20Sopenharmony_ci#endif 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ci rec->opts.affinity = PERF_AFFINITY_SYS; 26368c2ecf20Sopenharmony_ci 26378c2ecf20Sopenharmony_ci rec->evlist = evlist__new(); 26388c2ecf20Sopenharmony_ci if (rec->evlist == NULL) 26398c2ecf20Sopenharmony_ci return -ENOMEM; 26408c2ecf20Sopenharmony_ci 26418c2ecf20Sopenharmony_ci err = perf_config(perf_record_config, rec); 26428c2ecf20Sopenharmony_ci if (err) 26438c2ecf20Sopenharmony_ci return err; 26448c2ecf20Sopenharmony_ci 26458c2ecf20Sopenharmony_ci argc = parse_options(argc, argv, record_options, record_usage, 26468c2ecf20Sopenharmony_ci PARSE_OPT_STOP_AT_NON_OPTION); 26478c2ecf20Sopenharmony_ci if (quiet) 26488c2ecf20Sopenharmony_ci perf_quiet_option(); 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_ci /* Make system wide (-a) the default target. */ 26518c2ecf20Sopenharmony_ci if (!argc && target__none(&rec->opts.target)) 26528c2ecf20Sopenharmony_ci rec->opts.target.system_wide = true; 26538c2ecf20Sopenharmony_ci 26548c2ecf20Sopenharmony_ci if (nr_cgroups && !rec->opts.target.system_wide) { 26558c2ecf20Sopenharmony_ci usage_with_options_msg(record_usage, record_options, 26568c2ecf20Sopenharmony_ci "cgroup monitoring only available in system-wide mode"); 26578c2ecf20Sopenharmony_ci 26588c2ecf20Sopenharmony_ci } 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci if (rec->opts.kcore) 26618c2ecf20Sopenharmony_ci rec->data.is_dir = true; 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci if (rec->opts.comp_level != 0) { 26648c2ecf20Sopenharmony_ci pr_debug("Compression enabled, disabling build id collection at the end of the session.\n"); 26658c2ecf20Sopenharmony_ci rec->no_buildid = true; 26668c2ecf20Sopenharmony_ci } 26678c2ecf20Sopenharmony_ci 26688c2ecf20Sopenharmony_ci if (rec->opts.record_switch_events && 26698c2ecf20Sopenharmony_ci !perf_can_record_switch_events()) { 26708c2ecf20Sopenharmony_ci ui__error("kernel does not support recording context switch events\n"); 26718c2ecf20Sopenharmony_ci parse_options_usage(record_usage, record_options, "switch-events", 0); 26728c2ecf20Sopenharmony_ci err = -EINVAL; 26738c2ecf20Sopenharmony_ci goto out_opts; 26748c2ecf20Sopenharmony_ci } 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_ci if (switch_output_setup(rec)) { 26778c2ecf20Sopenharmony_ci parse_options_usage(record_usage, record_options, "switch-output", 0); 26788c2ecf20Sopenharmony_ci err = -EINVAL; 26798c2ecf20Sopenharmony_ci goto out_opts; 26808c2ecf20Sopenharmony_ci } 26818c2ecf20Sopenharmony_ci 26828c2ecf20Sopenharmony_ci if (rec->switch_output.time) { 26838c2ecf20Sopenharmony_ci signal(SIGALRM, alarm_sig_handler); 26848c2ecf20Sopenharmony_ci alarm(rec->switch_output.time); 26858c2ecf20Sopenharmony_ci } 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci if (rec->switch_output.num_files) { 26888c2ecf20Sopenharmony_ci rec->switch_output.filenames = calloc(sizeof(char *), 26898c2ecf20Sopenharmony_ci rec->switch_output.num_files); 26908c2ecf20Sopenharmony_ci if (!rec->switch_output.filenames) { 26918c2ecf20Sopenharmony_ci err = -EINVAL; 26928c2ecf20Sopenharmony_ci goto out_opts; 26938c2ecf20Sopenharmony_ci } 26948c2ecf20Sopenharmony_ci } 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_ci /* 26978c2ecf20Sopenharmony_ci * Allow aliases to facilitate the lookup of symbols for address 26988c2ecf20Sopenharmony_ci * filters. Refer to auxtrace_parse_filters(). 26998c2ecf20Sopenharmony_ci */ 27008c2ecf20Sopenharmony_ci symbol_conf.allow_aliases = true; 27018c2ecf20Sopenharmony_ci 27028c2ecf20Sopenharmony_ci symbol__init(NULL); 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_ci if (rec->opts.affinity != PERF_AFFINITY_SYS) { 27058c2ecf20Sopenharmony_ci rec->affinity_mask.nbits = cpu__max_cpu(); 27068c2ecf20Sopenharmony_ci rec->affinity_mask.bits = bitmap_alloc(rec->affinity_mask.nbits); 27078c2ecf20Sopenharmony_ci if (!rec->affinity_mask.bits) { 27088c2ecf20Sopenharmony_ci pr_err("Failed to allocate thread mask for %zd cpus\n", rec->affinity_mask.nbits); 27098c2ecf20Sopenharmony_ci err = -ENOMEM; 27108c2ecf20Sopenharmony_ci goto out_opts; 27118c2ecf20Sopenharmony_ci } 27128c2ecf20Sopenharmony_ci pr_debug2("thread mask[%zd]: empty\n", rec->affinity_mask.nbits); 27138c2ecf20Sopenharmony_ci } 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ci err = record__auxtrace_init(rec); 27168c2ecf20Sopenharmony_ci if (err) 27178c2ecf20Sopenharmony_ci goto out; 27188c2ecf20Sopenharmony_ci 27198c2ecf20Sopenharmony_ci if (dry_run) 27208c2ecf20Sopenharmony_ci goto out; 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ci err = bpf__setup_stdout(rec->evlist); 27238c2ecf20Sopenharmony_ci if (err) { 27248c2ecf20Sopenharmony_ci bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 27258c2ecf20Sopenharmony_ci pr_err("ERROR: Setup BPF stdout failed: %s\n", 27268c2ecf20Sopenharmony_ci errbuf); 27278c2ecf20Sopenharmony_ci goto out; 27288c2ecf20Sopenharmony_ci } 27298c2ecf20Sopenharmony_ci 27308c2ecf20Sopenharmony_ci err = -ENOMEM; 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci if (rec->no_buildid_cache || rec->no_buildid) { 27338c2ecf20Sopenharmony_ci disable_buildid_cache(); 27348c2ecf20Sopenharmony_ci } else if (rec->switch_output.enabled) { 27358c2ecf20Sopenharmony_ci /* 27368c2ecf20Sopenharmony_ci * In 'perf record --switch-output', disable buildid 27378c2ecf20Sopenharmony_ci * generation by default to reduce data file switching 27388c2ecf20Sopenharmony_ci * overhead. Still generate buildid if they are required 27398c2ecf20Sopenharmony_ci * explicitly using 27408c2ecf20Sopenharmony_ci * 27418c2ecf20Sopenharmony_ci * perf record --switch-output --no-no-buildid \ 27428c2ecf20Sopenharmony_ci * --no-no-buildid-cache 27438c2ecf20Sopenharmony_ci * 27448c2ecf20Sopenharmony_ci * Following code equals to: 27458c2ecf20Sopenharmony_ci * 27468c2ecf20Sopenharmony_ci * if ((rec->no_buildid || !rec->no_buildid_set) && 27478c2ecf20Sopenharmony_ci * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 27488c2ecf20Sopenharmony_ci * disable_buildid_cache(); 27498c2ecf20Sopenharmony_ci */ 27508c2ecf20Sopenharmony_ci bool disable = true; 27518c2ecf20Sopenharmony_ci 27528c2ecf20Sopenharmony_ci if (rec->no_buildid_set && !rec->no_buildid) 27538c2ecf20Sopenharmony_ci disable = false; 27548c2ecf20Sopenharmony_ci if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 27558c2ecf20Sopenharmony_ci disable = false; 27568c2ecf20Sopenharmony_ci if (disable) { 27578c2ecf20Sopenharmony_ci rec->no_buildid = true; 27588c2ecf20Sopenharmony_ci rec->no_buildid_cache = true; 27598c2ecf20Sopenharmony_ci disable_buildid_cache(); 27608c2ecf20Sopenharmony_ci } 27618c2ecf20Sopenharmony_ci } 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci if (record.opts.overwrite) 27648c2ecf20Sopenharmony_ci record.opts.tail_synthesize = true; 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci if (rec->evlist->core.nr_entries == 0 && 27678c2ecf20Sopenharmony_ci __evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { 27688c2ecf20Sopenharmony_ci pr_err("Not enough memory for event selector list\n"); 27698c2ecf20Sopenharmony_ci goto out; 27708c2ecf20Sopenharmony_ci } 27718c2ecf20Sopenharmony_ci 27728c2ecf20Sopenharmony_ci if (rec->opts.target.tid && !rec->opts.no_inherit_set) 27738c2ecf20Sopenharmony_ci rec->opts.no_inherit = true; 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci err = target__validate(&rec->opts.target); 27768c2ecf20Sopenharmony_ci if (err) { 27778c2ecf20Sopenharmony_ci target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 27788c2ecf20Sopenharmony_ci ui__warning("%s\n", errbuf); 27798c2ecf20Sopenharmony_ci } 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci err = target__parse_uid(&rec->opts.target); 27828c2ecf20Sopenharmony_ci if (err) { 27838c2ecf20Sopenharmony_ci int saved_errno = errno; 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 27868c2ecf20Sopenharmony_ci ui__error("%s", errbuf); 27878c2ecf20Sopenharmony_ci 27888c2ecf20Sopenharmony_ci err = -saved_errno; 27898c2ecf20Sopenharmony_ci goto out; 27908c2ecf20Sopenharmony_ci } 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci /* Enable ignoring missing threads when -u/-p option is defined. */ 27938c2ecf20Sopenharmony_ci rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ci err = -ENOMEM; 27968c2ecf20Sopenharmony_ci if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 27978c2ecf20Sopenharmony_ci usage_with_options(record_usage, record_options); 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 28008c2ecf20Sopenharmony_ci if (err) 28018c2ecf20Sopenharmony_ci goto out; 28028c2ecf20Sopenharmony_ci 28038c2ecf20Sopenharmony_ci /* 28048c2ecf20Sopenharmony_ci * We take all buildids when the file contains 28058c2ecf20Sopenharmony_ci * AUX area tracing data because we do not decode the 28068c2ecf20Sopenharmony_ci * trace because it would take too long. 28078c2ecf20Sopenharmony_ci */ 28088c2ecf20Sopenharmony_ci if (rec->opts.full_auxtrace) 28098c2ecf20Sopenharmony_ci rec->buildid_all = true; 28108c2ecf20Sopenharmony_ci 28118c2ecf20Sopenharmony_ci if (rec->opts.text_poke) { 28128c2ecf20Sopenharmony_ci err = record__config_text_poke(rec->evlist); 28138c2ecf20Sopenharmony_ci if (err) { 28148c2ecf20Sopenharmony_ci pr_err("record__config_text_poke failed, error %d\n", err); 28158c2ecf20Sopenharmony_ci goto out; 28168c2ecf20Sopenharmony_ci } 28178c2ecf20Sopenharmony_ci } 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci if (record_opts__config(&rec->opts)) { 28208c2ecf20Sopenharmony_ci err = -EINVAL; 28218c2ecf20Sopenharmony_ci goto out; 28228c2ecf20Sopenharmony_ci } 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci if (rec->opts.nr_cblocks > nr_cblocks_max) 28258c2ecf20Sopenharmony_ci rec->opts.nr_cblocks = nr_cblocks_max; 28268c2ecf20Sopenharmony_ci pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks); 28278c2ecf20Sopenharmony_ci 28288c2ecf20Sopenharmony_ci pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); 28298c2ecf20Sopenharmony_ci pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); 28308c2ecf20Sopenharmony_ci 28318c2ecf20Sopenharmony_ci if (rec->opts.comp_level > comp_level_max) 28328c2ecf20Sopenharmony_ci rec->opts.comp_level = comp_level_max; 28338c2ecf20Sopenharmony_ci pr_debug("comp level: %d\n", rec->opts.comp_level); 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci err = __cmd_record(&record, argc, argv); 28368c2ecf20Sopenharmony_ciout: 28378c2ecf20Sopenharmony_ci bitmap_free(rec->affinity_mask.bits); 28388c2ecf20Sopenharmony_ci evlist__delete(rec->evlist); 28398c2ecf20Sopenharmony_ci symbol__exit(); 28408c2ecf20Sopenharmony_ci auxtrace_record__free(rec->itr); 28418c2ecf20Sopenharmony_ciout_opts: 28428c2ecf20Sopenharmony_ci evlist__close_control(rec->opts.ctl_fd, rec->opts.ctl_fd_ack, &rec->opts.ctl_fd_close); 28438c2ecf20Sopenharmony_ci return err; 28448c2ecf20Sopenharmony_ci} 28458c2ecf20Sopenharmony_ci 28468c2ecf20Sopenharmony_cistatic void snapshot_sig_handler(int sig __maybe_unused) 28478c2ecf20Sopenharmony_ci{ 28488c2ecf20Sopenharmony_ci struct record *rec = &record; 28498c2ecf20Sopenharmony_ci 28508c2ecf20Sopenharmony_ci hit_auxtrace_snapshot_trigger(rec); 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci if (switch_output_signal(rec)) 28538c2ecf20Sopenharmony_ci trigger_hit(&switch_output_trigger); 28548c2ecf20Sopenharmony_ci} 28558c2ecf20Sopenharmony_ci 28568c2ecf20Sopenharmony_cistatic void alarm_sig_handler(int sig __maybe_unused) 28578c2ecf20Sopenharmony_ci{ 28588c2ecf20Sopenharmony_ci struct record *rec = &record; 28598c2ecf20Sopenharmony_ci 28608c2ecf20Sopenharmony_ci if (switch_output_time(rec)) 28618c2ecf20Sopenharmony_ci trigger_hit(&switch_output_trigger); 28628c2ecf20Sopenharmony_ci} 2863