1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 286470930SIngo Molnar /* 386470930SIngo Molnar * builtin-record.c 486470930SIngo Molnar * 586470930SIngo Molnar * Builtin record command: Record the profile of a workload 686470930SIngo Molnar * (or a CPU, or a PID) into the perf.data output file - for 786470930SIngo Molnar * later analysis via perf report. 886470930SIngo Molnar */ 986470930SIngo Molnar #include "builtin.h" 1086470930SIngo Molnar 116122e4e4SArnaldo Carvalho de Melo #include "util/build-id.h" 124b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1386470930SIngo Molnar #include "util/parse-events.h" 1441840d21STaeung Song #include "util/config.h" 1586470930SIngo Molnar 168f651eaeSArnaldo Carvalho de Melo #include "util/callchain.h" 17f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 187c6a1c65SPeter Zijlstra #include "util/header.h" 1966e274f3SFrederic Weisbecker #include "util/event.h" 20361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 2169aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 228f28827aSFrederic Weisbecker #include "util/debug.h" 23e0fcfb08SArnaldo Carvalho de Melo #include "util/mmap.h" 24aeb00b1aSArnaldo Carvalho de Melo #include "util/target.h" 2594c744b6SArnaldo Carvalho de Melo #include "util/session.h" 2645694aa7SArnaldo Carvalho de Melo #include "util/tool.h" 278d06367fSArnaldo Carvalho de Melo #include "util/symbol.h" 28aeb00b1aSArnaldo Carvalho de Melo #include "util/record.h" 29a12b51c4SPaul Mackerras #include "util/cpumap.h" 30fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 31f5fc1412SJiri Olsa #include "util/data.h" 32bcc84ec6SStephane Eranian #include "util/perf_regs.h" 33ef149c25SAdrian Hunter #include "util/auxtrace.h" 3446bc29b9SAdrian Hunter #include "util/tsc.h" 35f00898f4SAndi Kleen #include "util/parse-branch-options.h" 36bcc84ec6SStephane Eranian #include "util/parse-regs-options.h" 3740c7d246SArnaldo Carvalho de Melo #include "util/perf_api_probe.h" 3871dc2326SWang Nan #include "util/llvm-utils.h" 398690a2a7SWang Nan #include "util/bpf-loader.h" 405f9cf599SWang Nan #include "util/trigger.h" 41a074865eSWang Nan #include "util/perf-hooks.h" 42f13de660SAlexey Budankov #include "util/cpu-set-sched.h" 43ea49e01cSArnaldo Carvalho de Melo #include "util/synthetic-events.h" 44c5e4027eSArnaldo Carvalho de Melo #include "util/time-utils.h" 4558db1d6eSArnaldo Carvalho de Melo #include "util/units.h" 467b612e29SSong Liu #include "util/bpf-event.h" 47d99c22eaSStephane Eranian #include "util/util.h" 4870943490SStephane Eranian #include "util/pfm.h" 49*6953beb4SJiri Olsa #include "util/clockid.h" 50d8871ea7SWang Nan #include "asm/bug.h" 51c1a604dfSArnaldo Carvalho de Melo #include "perf.h" 527c6a1c65SPeter Zijlstra 53a43783aeSArnaldo Carvalho de Melo #include <errno.h> 54fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 5567230479SArnaldo Carvalho de Melo #include <locale.h> 564208735dSArnaldo Carvalho de Melo #include <poll.h> 57d99c22eaSStephane Eranian #include <pthread.h> 5886470930SIngo Molnar #include <unistd.h> 5986470930SIngo Molnar #include <sched.h> 609607ad3aSArnaldo Carvalho de Melo #include <signal.h> 61da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 62da231338SAnand K Mistry #include <sys/eventfd.h> 63da231338SAnand K Mistry #endif 64a41794cdSArnaldo Carvalho de Melo #include <sys/mman.h> 654208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 66eeb399b5SAdrian Hunter #include <sys/types.h> 67eeb399b5SAdrian Hunter #include <sys/stat.h> 68eeb399b5SAdrian Hunter #include <fcntl.h> 696ef81c55SMamatha Inamdar #include <linux/err.h> 708520a98dSArnaldo Carvalho de Melo #include <linux/string.h> 710693e680SArnaldo Carvalho de Melo #include <linux/time64.h> 72d8f9da24SArnaldo Carvalho de Melo #include <linux/zalloc.h> 738384a260SAlexey Budankov #include <linux/bitmap.h> 7478da39faSBernhard Rosenkraenzer 751b43b704SJiri Olsa struct switch_output { 76dc0c6127SJiri Olsa bool enabled; 771b43b704SJiri Olsa bool signal; 78dc0c6127SJiri Olsa unsigned long size; 79bfacbe3bSJiri Olsa unsigned long time; 80cb4e1ebbSJiri Olsa const char *str; 81cb4e1ebbSJiri Olsa bool set; 8203724b2eSAndi Kleen char **filenames; 8303724b2eSAndi Kleen int num_files; 8403724b2eSAndi Kleen int cur_file; 851b43b704SJiri Olsa }; 861b43b704SJiri Olsa 878c6f45a7SArnaldo Carvalho de Melo struct record { 8845694aa7SArnaldo Carvalho de Melo struct perf_tool tool; 89b4006796SArnaldo Carvalho de Melo struct record_opts opts; 90d20deb64SArnaldo Carvalho de Melo u64 bytes_written; 918ceb41d7SJiri Olsa struct perf_data data; 92ef149c25SAdrian Hunter struct auxtrace_record *itr; 9363503dbaSJiri Olsa struct evlist *evlist; 94d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 95bc477d79SArnaldo Carvalho de Melo struct evlist *sb_evlist; 96899e5ffbSArnaldo Carvalho de Melo pthread_t thread_id; 97d20deb64SArnaldo Carvalho de Melo int realtime_prio; 98899e5ffbSArnaldo Carvalho de Melo bool switch_output_event_set; 99d20deb64SArnaldo Carvalho de Melo bool no_buildid; 100d2db9a98SWang Nan bool no_buildid_set; 101d20deb64SArnaldo Carvalho de Melo bool no_buildid_cache; 102d2db9a98SWang Nan bool no_buildid_cache_set; 1036156681bSNamhyung Kim bool buildid_all; 104ecfd7a9cSWang Nan bool timestamp_filename; 10568588bafSJin Yao bool timestamp_boundary; 1061b43b704SJiri Olsa struct switch_output switch_output; 1079f065194SYang Shi unsigned long long samples; 1088384a260SAlexey Budankov struct mmap_cpu_mask affinity_mask; 1096d575816SJiwei Sun unsigned long output_max_size; /* = 0: unlimited */ 1100f82ebc4SArnaldo Carvalho de Melo }; 11186470930SIngo Molnar 1126d575816SJiwei Sun static volatile int done; 1136d575816SJiwei Sun 114dc0c6127SJiri Olsa static volatile int auxtrace_record__snapshot_started; 115dc0c6127SJiri Olsa static DEFINE_TRIGGER(auxtrace_snapshot_trigger); 116dc0c6127SJiri Olsa static DEFINE_TRIGGER(switch_output_trigger); 117dc0c6127SJiri Olsa 1189d2ed645SAlexey Budankov static const char *affinity_tags[PERF_AFFINITY_MAX] = { 1199d2ed645SAlexey Budankov "SYS", "NODE", "CPU" 1209d2ed645SAlexey Budankov }; 1219d2ed645SAlexey Budankov 122dc0c6127SJiri Olsa static bool switch_output_signal(struct record *rec) 123dc0c6127SJiri Olsa { 124dc0c6127SJiri Olsa return rec->switch_output.signal && 125dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger); 126dc0c6127SJiri Olsa } 127dc0c6127SJiri Olsa 128dc0c6127SJiri Olsa static bool switch_output_size(struct record *rec) 129dc0c6127SJiri Olsa { 130dc0c6127SJiri Olsa return rec->switch_output.size && 131dc0c6127SJiri Olsa trigger_is_ready(&switch_output_trigger) && 132dc0c6127SJiri Olsa (rec->bytes_written >= rec->switch_output.size); 133dc0c6127SJiri Olsa } 134dc0c6127SJiri Olsa 135bfacbe3bSJiri Olsa static bool switch_output_time(struct record *rec) 136bfacbe3bSJiri Olsa { 137bfacbe3bSJiri Olsa return rec->switch_output.time && 138bfacbe3bSJiri Olsa trigger_is_ready(&switch_output_trigger); 139bfacbe3bSJiri Olsa } 140bfacbe3bSJiri Olsa 1416d575816SJiwei Sun static bool record__output_max_size_exceeded(struct record *rec) 1426d575816SJiwei Sun { 1436d575816SJiwei Sun return rec->output_max_size && 1446d575816SJiwei Sun (rec->bytes_written >= rec->output_max_size); 1456d575816SJiwei Sun } 1466d575816SJiwei Sun 147a5830532SJiri Olsa static int record__write(struct record *rec, struct mmap *map __maybe_unused, 148ded2b8feSJiri Olsa void *bf, size_t size) 149f5970550SPeter Zijlstra { 150ded2b8feSJiri Olsa struct perf_data_file *file = &rec->session->data->file; 151ded2b8feSJiri Olsa 152ded2b8feSJiri Olsa if (perf_data_file__write(file, bf, size) < 0) { 1534f624685SAdrian Hunter pr_err("failed to write perf data, error: %m\n"); 1548d3eca20SDavid Ahern return -1; 1558d3eca20SDavid Ahern } 156f5970550SPeter Zijlstra 157cf8b2e69SArnaldo Carvalho de Melo rec->bytes_written += size; 158dc0c6127SJiri Olsa 1596d575816SJiwei Sun if (record__output_max_size_exceeded(rec) && !done) { 1606d575816SJiwei Sun fprintf(stderr, "[ perf record: perf size limit reached (%" PRIu64 " KB)," 1616d575816SJiwei Sun " stopping session ]\n", 1626d575816SJiwei Sun rec->bytes_written >> 10); 1636d575816SJiwei Sun done = 1; 1646d575816SJiwei Sun } 1656d575816SJiwei Sun 166dc0c6127SJiri Olsa if (switch_output_size(rec)) 167dc0c6127SJiri Olsa trigger_hit(&switch_output_trigger); 168dc0c6127SJiri Olsa 1698d3eca20SDavid Ahern return 0; 170f5970550SPeter Zijlstra } 171f5970550SPeter Zijlstra 172ef781128SAlexey Budankov static int record__aio_enabled(struct record *rec); 173ef781128SAlexey Budankov static int record__comp_enabled(struct record *rec); 1745d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 1755d7f4116SAlexey Budankov void *src, size_t src_size); 1765d7f4116SAlexey Budankov 177d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 178d3d1af6fSAlexey Budankov static int record__aio_write(struct aiocb *cblock, int trace_fd, 179d3d1af6fSAlexey Budankov void *buf, size_t size, off_t off) 180d3d1af6fSAlexey Budankov { 181d3d1af6fSAlexey Budankov int rc; 182d3d1af6fSAlexey Budankov 183d3d1af6fSAlexey Budankov cblock->aio_fildes = trace_fd; 184d3d1af6fSAlexey Budankov cblock->aio_buf = buf; 185d3d1af6fSAlexey Budankov cblock->aio_nbytes = size; 186d3d1af6fSAlexey Budankov cblock->aio_offset = off; 187d3d1af6fSAlexey Budankov cblock->aio_sigevent.sigev_notify = SIGEV_NONE; 188d3d1af6fSAlexey Budankov 189d3d1af6fSAlexey Budankov do { 190d3d1af6fSAlexey Budankov rc = aio_write(cblock); 191d3d1af6fSAlexey Budankov if (rc == 0) { 192d3d1af6fSAlexey Budankov break; 193d3d1af6fSAlexey Budankov } else if (errno != EAGAIN) { 194d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 195d3d1af6fSAlexey Budankov pr_err("failed to queue perf data, error: %m\n"); 196d3d1af6fSAlexey Budankov break; 197d3d1af6fSAlexey Budankov } 198d3d1af6fSAlexey Budankov } while (1); 199d3d1af6fSAlexey Budankov 200d3d1af6fSAlexey Budankov return rc; 201d3d1af6fSAlexey Budankov } 202d3d1af6fSAlexey Budankov 203a5830532SJiri Olsa static int record__aio_complete(struct mmap *md, struct aiocb *cblock) 204d3d1af6fSAlexey Budankov { 205d3d1af6fSAlexey Budankov void *rem_buf; 206d3d1af6fSAlexey Budankov off_t rem_off; 207d3d1af6fSAlexey Budankov size_t rem_size; 208d3d1af6fSAlexey Budankov int rc, aio_errno; 209d3d1af6fSAlexey Budankov ssize_t aio_ret, written; 210d3d1af6fSAlexey Budankov 211d3d1af6fSAlexey Budankov aio_errno = aio_error(cblock); 212d3d1af6fSAlexey Budankov if (aio_errno == EINPROGRESS) 213d3d1af6fSAlexey Budankov return 0; 214d3d1af6fSAlexey Budankov 215d3d1af6fSAlexey Budankov written = aio_ret = aio_return(cblock); 216d3d1af6fSAlexey Budankov if (aio_ret < 0) { 217d3d1af6fSAlexey Budankov if (aio_errno != EINTR) 218d3d1af6fSAlexey Budankov pr_err("failed to write perf data, error: %m\n"); 219d3d1af6fSAlexey Budankov written = 0; 220d3d1af6fSAlexey Budankov } 221d3d1af6fSAlexey Budankov 222d3d1af6fSAlexey Budankov rem_size = cblock->aio_nbytes - written; 223d3d1af6fSAlexey Budankov 224d3d1af6fSAlexey Budankov if (rem_size == 0) { 225d3d1af6fSAlexey Budankov cblock->aio_fildes = -1; 226d3d1af6fSAlexey Budankov /* 227ef781128SAlexey Budankov * md->refcount is incremented in record__aio_pushfn() for 228ef781128SAlexey Budankov * every aio write request started in record__aio_push() so 229ef781128SAlexey Budankov * decrement it because the request is now complete. 230d3d1af6fSAlexey Budankov */ 23180e53d11SJiri Olsa perf_mmap__put(&md->core); 232d3d1af6fSAlexey Budankov rc = 1; 233d3d1af6fSAlexey Budankov } else { 234d3d1af6fSAlexey Budankov /* 235d3d1af6fSAlexey Budankov * aio write request may require restart with the 236d3d1af6fSAlexey Budankov * reminder if the kernel didn't write whole 237d3d1af6fSAlexey Budankov * chunk at once. 238d3d1af6fSAlexey Budankov */ 239d3d1af6fSAlexey Budankov rem_off = cblock->aio_offset + written; 240d3d1af6fSAlexey Budankov rem_buf = (void *)(cblock->aio_buf + written); 241d3d1af6fSAlexey Budankov record__aio_write(cblock, cblock->aio_fildes, 242d3d1af6fSAlexey Budankov rem_buf, rem_size, rem_off); 243d3d1af6fSAlexey Budankov rc = 0; 244d3d1af6fSAlexey Budankov } 245d3d1af6fSAlexey Budankov 246d3d1af6fSAlexey Budankov return rc; 247d3d1af6fSAlexey Budankov } 248d3d1af6fSAlexey Budankov 249a5830532SJiri Olsa static int record__aio_sync(struct mmap *md, bool sync_all) 250d3d1af6fSAlexey Budankov { 25193f20c0fSAlexey Budankov struct aiocb **aiocb = md->aio.aiocb; 25293f20c0fSAlexey Budankov struct aiocb *cblocks = md->aio.cblocks; 253d3d1af6fSAlexey Budankov struct timespec timeout = { 0, 1000 * 1000 * 1 }; /* 1ms */ 25493f20c0fSAlexey Budankov int i, do_suspend; 255d3d1af6fSAlexey Budankov 256d3d1af6fSAlexey Budankov do { 25793f20c0fSAlexey Budankov do_suspend = 0; 25893f20c0fSAlexey Budankov for (i = 0; i < md->aio.nr_cblocks; ++i) { 25993f20c0fSAlexey Budankov if (cblocks[i].aio_fildes == -1 || record__aio_complete(md, &cblocks[i])) { 26093f20c0fSAlexey Budankov if (sync_all) 26193f20c0fSAlexey Budankov aiocb[i] = NULL; 26293f20c0fSAlexey Budankov else 26393f20c0fSAlexey Budankov return i; 26493f20c0fSAlexey Budankov } else { 26593f20c0fSAlexey Budankov /* 26693f20c0fSAlexey Budankov * Started aio write is not complete yet 26793f20c0fSAlexey Budankov * so it has to be waited before the 26893f20c0fSAlexey Budankov * next allocation. 26993f20c0fSAlexey Budankov */ 27093f20c0fSAlexey Budankov aiocb[i] = &cblocks[i]; 27193f20c0fSAlexey Budankov do_suspend = 1; 27293f20c0fSAlexey Budankov } 27393f20c0fSAlexey Budankov } 27493f20c0fSAlexey Budankov if (!do_suspend) 27593f20c0fSAlexey Budankov return -1; 276d3d1af6fSAlexey Budankov 27793f20c0fSAlexey Budankov while (aio_suspend((const struct aiocb **)aiocb, md->aio.nr_cblocks, &timeout)) { 278d3d1af6fSAlexey Budankov if (!(errno == EAGAIN || errno == EINTR)) 279d3d1af6fSAlexey Budankov pr_err("failed to sync perf data, error: %m\n"); 280d3d1af6fSAlexey Budankov } 281d3d1af6fSAlexey Budankov } while (1); 282d3d1af6fSAlexey Budankov } 283d3d1af6fSAlexey Budankov 284ef781128SAlexey Budankov struct record_aio { 285ef781128SAlexey Budankov struct record *rec; 286ef781128SAlexey Budankov void *data; 287ef781128SAlexey Budankov size_t size; 288ef781128SAlexey Budankov }; 289ef781128SAlexey Budankov 290a5830532SJiri Olsa static int record__aio_pushfn(struct mmap *map, void *to, void *buf, size_t size) 291d3d1af6fSAlexey Budankov { 292ef781128SAlexey Budankov struct record_aio *aio = to; 293ef781128SAlexey Budankov 294ef781128SAlexey Budankov /* 295547740f7SJiri Olsa * map->core.base data pointed by buf is copied into free map->aio.data[] buffer 296ef781128SAlexey Budankov * to release space in the kernel buffer as fast as possible, calling 297ef781128SAlexey Budankov * perf_mmap__consume() from perf_mmap__push() function. 298ef781128SAlexey Budankov * 299ef781128SAlexey Budankov * That lets the kernel to proceed with storing more profiling data into 300ef781128SAlexey Budankov * the kernel buffer earlier than other per-cpu kernel buffers are handled. 301ef781128SAlexey Budankov * 302ef781128SAlexey Budankov * Coping can be done in two steps in case the chunk of profiling data 303ef781128SAlexey Budankov * crosses the upper bound of the kernel buffer. In this case we first move 304ef781128SAlexey Budankov * part of data from map->start till the upper bound and then the reminder 305ef781128SAlexey Budankov * from the beginning of the kernel buffer till the end of the data chunk. 306ef781128SAlexey Budankov */ 307ef781128SAlexey Budankov 308ef781128SAlexey Budankov if (record__comp_enabled(aio->rec)) { 309ef781128SAlexey Budankov size = zstd_compress(aio->rec->session, aio->data + aio->size, 310bf59b305SJiri Olsa mmap__mmap_len(map) - aio->size, 311ef781128SAlexey Budankov buf, size); 312ef781128SAlexey Budankov } else { 313ef781128SAlexey Budankov memcpy(aio->data + aio->size, buf, size); 314ef781128SAlexey Budankov } 315ef781128SAlexey Budankov 316ef781128SAlexey Budankov if (!aio->size) { 317ef781128SAlexey Budankov /* 318ef781128SAlexey Budankov * Increment map->refcount to guard map->aio.data[] buffer 319ef781128SAlexey Budankov * from premature deallocation because map object can be 320ef781128SAlexey Budankov * released earlier than aio write request started on 321ef781128SAlexey Budankov * map->aio.data[] buffer is complete. 322ef781128SAlexey Budankov * 323ef781128SAlexey Budankov * perf_mmap__put() is done at record__aio_complete() 324ef781128SAlexey Budankov * after started aio request completion or at record__aio_push() 325ef781128SAlexey Budankov * if the request failed to start. 326ef781128SAlexey Budankov */ 327e75710f0SJiri Olsa perf_mmap__get(&map->core); 328ef781128SAlexey Budankov } 329ef781128SAlexey Budankov 330ef781128SAlexey Budankov aio->size += size; 331ef781128SAlexey Budankov 332ef781128SAlexey Budankov return size; 333ef781128SAlexey Budankov } 334ef781128SAlexey Budankov 335a5830532SJiri Olsa static int record__aio_push(struct record *rec, struct mmap *map, off_t *off) 336ef781128SAlexey Budankov { 337ef781128SAlexey Budankov int ret, idx; 338ef781128SAlexey Budankov int trace_fd = rec->session->data->file.fd; 339ef781128SAlexey Budankov struct record_aio aio = { .rec = rec, .size = 0 }; 340ef781128SAlexey Budankov 341ef781128SAlexey Budankov /* 342ef781128SAlexey Budankov * Call record__aio_sync() to wait till map->aio.data[] buffer 343ef781128SAlexey Budankov * becomes available after previous aio write operation. 344ef781128SAlexey Budankov */ 345ef781128SAlexey Budankov 346ef781128SAlexey Budankov idx = record__aio_sync(map, false); 347ef781128SAlexey Budankov aio.data = map->aio.data[idx]; 348ef781128SAlexey Budankov ret = perf_mmap__push(map, &aio, record__aio_pushfn); 349ef781128SAlexey Budankov if (ret != 0) /* ret > 0 - no data, ret < 0 - error */ 350ef781128SAlexey Budankov return ret; 351d3d1af6fSAlexey Budankov 352d3d1af6fSAlexey Budankov rec->samples++; 353ef781128SAlexey Budankov ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off); 354d3d1af6fSAlexey Budankov if (!ret) { 355ef781128SAlexey Budankov *off += aio.size; 356ef781128SAlexey Budankov rec->bytes_written += aio.size; 357d3d1af6fSAlexey Budankov if (switch_output_size(rec)) 358d3d1af6fSAlexey Budankov trigger_hit(&switch_output_trigger); 359ef781128SAlexey Budankov } else { 360ef781128SAlexey Budankov /* 361ef781128SAlexey Budankov * Decrement map->refcount incremented in record__aio_pushfn() 362ef781128SAlexey Budankov * back if record__aio_write() operation failed to start, otherwise 363ef781128SAlexey Budankov * map->refcount is decremented in record__aio_complete() after 364ef781128SAlexey Budankov * aio write operation finishes successfully. 365ef781128SAlexey Budankov */ 36680e53d11SJiri Olsa perf_mmap__put(&map->core); 367d3d1af6fSAlexey Budankov } 368d3d1af6fSAlexey Budankov 369d3d1af6fSAlexey Budankov return ret; 370d3d1af6fSAlexey Budankov } 371d3d1af6fSAlexey Budankov 372d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd) 373d3d1af6fSAlexey Budankov { 374d3d1af6fSAlexey Budankov return lseek(trace_fd, 0, SEEK_CUR); 375d3d1af6fSAlexey Budankov } 376d3d1af6fSAlexey Budankov 377d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd, off_t pos) 378d3d1af6fSAlexey Budankov { 379d3d1af6fSAlexey Budankov lseek(trace_fd, pos, SEEK_SET); 380d3d1af6fSAlexey Budankov } 381d3d1af6fSAlexey Budankov 382d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec) 383d3d1af6fSAlexey Budankov { 384d3d1af6fSAlexey Budankov int i; 38563503dbaSJiri Olsa struct evlist *evlist = rec->evlist; 386a5830532SJiri Olsa struct mmap *maps = evlist->mmap; 387d3d1af6fSAlexey Budankov 388ef781128SAlexey Budankov if (!record__aio_enabled(rec)) 389d3d1af6fSAlexey Budankov return; 390d3d1af6fSAlexey Budankov 391c976ee11SJiri Olsa for (i = 0; i < evlist->core.nr_mmaps; i++) { 392a5830532SJiri Olsa struct mmap *map = &maps[i]; 393d3d1af6fSAlexey Budankov 394547740f7SJiri Olsa if (map->core.base) 39593f20c0fSAlexey Budankov record__aio_sync(map, true); 396d3d1af6fSAlexey Budankov } 397d3d1af6fSAlexey Budankov } 398d3d1af6fSAlexey Budankov 399d3d1af6fSAlexey Budankov static int nr_cblocks_default = 1; 40093f20c0fSAlexey Budankov static int nr_cblocks_max = 4; 401d3d1af6fSAlexey Budankov 402d3d1af6fSAlexey Budankov static int record__aio_parse(const struct option *opt, 40393f20c0fSAlexey Budankov const char *str, 404d3d1af6fSAlexey Budankov int unset) 405d3d1af6fSAlexey Budankov { 406d3d1af6fSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 407d3d1af6fSAlexey Budankov 40893f20c0fSAlexey Budankov if (unset) { 409d3d1af6fSAlexey Budankov opts->nr_cblocks = 0; 41093f20c0fSAlexey Budankov } else { 41193f20c0fSAlexey Budankov if (str) 41293f20c0fSAlexey Budankov opts->nr_cblocks = strtol(str, NULL, 0); 41393f20c0fSAlexey Budankov if (!opts->nr_cblocks) 414d3d1af6fSAlexey Budankov opts->nr_cblocks = nr_cblocks_default; 41593f20c0fSAlexey Budankov } 416d3d1af6fSAlexey Budankov 417d3d1af6fSAlexey Budankov return 0; 418d3d1af6fSAlexey Budankov } 419d3d1af6fSAlexey Budankov #else /* HAVE_AIO_SUPPORT */ 42093f20c0fSAlexey Budankov static int nr_cblocks_max = 0; 42193f20c0fSAlexey Budankov 422a5830532SJiri Olsa static int record__aio_push(struct record *rec __maybe_unused, struct mmap *map __maybe_unused, 423ef781128SAlexey Budankov off_t *off __maybe_unused) 424d3d1af6fSAlexey Budankov { 425d3d1af6fSAlexey Budankov return -1; 426d3d1af6fSAlexey Budankov } 427d3d1af6fSAlexey Budankov 428d3d1af6fSAlexey Budankov static off_t record__aio_get_pos(int trace_fd __maybe_unused) 429d3d1af6fSAlexey Budankov { 430d3d1af6fSAlexey Budankov return -1; 431d3d1af6fSAlexey Budankov } 432d3d1af6fSAlexey Budankov 433d3d1af6fSAlexey Budankov static void record__aio_set_pos(int trace_fd __maybe_unused, off_t pos __maybe_unused) 434d3d1af6fSAlexey Budankov { 435d3d1af6fSAlexey Budankov } 436d3d1af6fSAlexey Budankov 437d3d1af6fSAlexey Budankov static void record__aio_mmap_read_sync(struct record *rec __maybe_unused) 438d3d1af6fSAlexey Budankov { 439d3d1af6fSAlexey Budankov } 440d3d1af6fSAlexey Budankov #endif 441d3d1af6fSAlexey Budankov 442d3d1af6fSAlexey Budankov static int record__aio_enabled(struct record *rec) 443d3d1af6fSAlexey Budankov { 444d3d1af6fSAlexey Budankov return rec->opts.nr_cblocks > 0; 445d3d1af6fSAlexey Budankov } 446d3d1af6fSAlexey Budankov 447470530bbSAlexey Budankov #define MMAP_FLUSH_DEFAULT 1 448470530bbSAlexey Budankov static int record__mmap_flush_parse(const struct option *opt, 449470530bbSAlexey Budankov const char *str, 450470530bbSAlexey Budankov int unset) 451470530bbSAlexey Budankov { 452470530bbSAlexey Budankov int flush_max; 453470530bbSAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 454470530bbSAlexey Budankov static struct parse_tag tags[] = { 455470530bbSAlexey Budankov { .tag = 'B', .mult = 1 }, 456470530bbSAlexey Budankov { .tag = 'K', .mult = 1 << 10 }, 457470530bbSAlexey Budankov { .tag = 'M', .mult = 1 << 20 }, 458470530bbSAlexey Budankov { .tag = 'G', .mult = 1 << 30 }, 459470530bbSAlexey Budankov { .tag = 0 }, 460470530bbSAlexey Budankov }; 461470530bbSAlexey Budankov 462470530bbSAlexey Budankov if (unset) 463470530bbSAlexey Budankov return 0; 464470530bbSAlexey Budankov 465470530bbSAlexey Budankov if (str) { 466470530bbSAlexey Budankov opts->mmap_flush = parse_tag_value(str, tags); 467470530bbSAlexey Budankov if (opts->mmap_flush == (int)-1) 468470530bbSAlexey Budankov opts->mmap_flush = strtol(str, NULL, 0); 469470530bbSAlexey Budankov } 470470530bbSAlexey Budankov 471470530bbSAlexey Budankov if (!opts->mmap_flush) 472470530bbSAlexey Budankov opts->mmap_flush = MMAP_FLUSH_DEFAULT; 473470530bbSAlexey Budankov 4749521b5f2SJiri Olsa flush_max = evlist__mmap_size(opts->mmap_pages); 475470530bbSAlexey Budankov flush_max /= 4; 476470530bbSAlexey Budankov if (opts->mmap_flush > flush_max) 477470530bbSAlexey Budankov opts->mmap_flush = flush_max; 478470530bbSAlexey Budankov 479470530bbSAlexey Budankov return 0; 480470530bbSAlexey Budankov } 481470530bbSAlexey Budankov 482504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT 483504c1ad1SAlexey Budankov static unsigned int comp_level_default = 1; 484504c1ad1SAlexey Budankov 485504c1ad1SAlexey Budankov static int record__parse_comp_level(const struct option *opt, const char *str, int unset) 486504c1ad1SAlexey Budankov { 487504c1ad1SAlexey Budankov struct record_opts *opts = opt->value; 488504c1ad1SAlexey Budankov 489504c1ad1SAlexey Budankov if (unset) { 490504c1ad1SAlexey Budankov opts->comp_level = 0; 491504c1ad1SAlexey Budankov } else { 492504c1ad1SAlexey Budankov if (str) 493504c1ad1SAlexey Budankov opts->comp_level = strtol(str, NULL, 0); 494504c1ad1SAlexey Budankov if (!opts->comp_level) 495504c1ad1SAlexey Budankov opts->comp_level = comp_level_default; 496504c1ad1SAlexey Budankov } 497504c1ad1SAlexey Budankov 498504c1ad1SAlexey Budankov return 0; 499504c1ad1SAlexey Budankov } 500504c1ad1SAlexey Budankov #endif 50151255a8aSAlexey Budankov static unsigned int comp_level_max = 22; 50251255a8aSAlexey Budankov 50342e1fd80SAlexey Budankov static int record__comp_enabled(struct record *rec) 50442e1fd80SAlexey Budankov { 50542e1fd80SAlexey Budankov return rec->opts.comp_level > 0; 50642e1fd80SAlexey Budankov } 50742e1fd80SAlexey Budankov 50845694aa7SArnaldo Carvalho de Melo static int process_synthesized_event(struct perf_tool *tool, 509d20deb64SArnaldo Carvalho de Melo union perf_event *event, 5101d037ca1SIrina Tirdea struct perf_sample *sample __maybe_unused, 5111d037ca1SIrina Tirdea struct machine *machine __maybe_unused) 512234fbbf5SArnaldo Carvalho de Melo { 5138c6f45a7SArnaldo Carvalho de Melo struct record *rec = container_of(tool, struct record, tool); 514ded2b8feSJiri Olsa return record__write(rec, NULL, event, event->header.size); 515234fbbf5SArnaldo Carvalho de Melo } 516234fbbf5SArnaldo Carvalho de Melo 517d99c22eaSStephane Eranian static int process_locked_synthesized_event(struct perf_tool *tool, 518d99c22eaSStephane Eranian union perf_event *event, 519d99c22eaSStephane Eranian struct perf_sample *sample __maybe_unused, 520d99c22eaSStephane Eranian struct machine *machine __maybe_unused) 521d99c22eaSStephane Eranian { 522d99c22eaSStephane Eranian static pthread_mutex_t synth_lock = PTHREAD_MUTEX_INITIALIZER; 523d99c22eaSStephane Eranian int ret; 524d99c22eaSStephane Eranian 525d99c22eaSStephane Eranian pthread_mutex_lock(&synth_lock); 526d99c22eaSStephane Eranian ret = process_synthesized_event(tool, event, sample, machine); 527d99c22eaSStephane Eranian pthread_mutex_unlock(&synth_lock); 528d99c22eaSStephane Eranian return ret; 529d99c22eaSStephane Eranian } 530d99c22eaSStephane Eranian 531a5830532SJiri Olsa static int record__pushfn(struct mmap *map, void *to, void *bf, size_t size) 532d37f1586SArnaldo Carvalho de Melo { 533d37f1586SArnaldo Carvalho de Melo struct record *rec = to; 534d37f1586SArnaldo Carvalho de Melo 5355d7f4116SAlexey Budankov if (record__comp_enabled(rec)) { 536bf59b305SJiri Olsa size = zstd_compress(rec->session, map->data, mmap__mmap_len(map), bf, size); 5375d7f4116SAlexey Budankov bf = map->data; 5385d7f4116SAlexey Budankov } 5395d7f4116SAlexey Budankov 540d37f1586SArnaldo Carvalho de Melo rec->samples++; 541ded2b8feSJiri Olsa return record__write(rec, map, bf, size); 542d37f1586SArnaldo Carvalho de Melo } 543d37f1586SArnaldo Carvalho de Melo 5442dd6d8a1SAdrian Hunter static volatile int signr = -1; 5452dd6d8a1SAdrian Hunter static volatile int child_finished; 546da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 547da231338SAnand K Mistry static int done_fd = -1; 548da231338SAnand K Mistry #endif 549c0bdc1c4SWang Nan 5502dd6d8a1SAdrian Hunter static void sig_handler(int sig) 5512dd6d8a1SAdrian Hunter { 5522dd6d8a1SAdrian Hunter if (sig == SIGCHLD) 5532dd6d8a1SAdrian Hunter child_finished = 1; 5542dd6d8a1SAdrian Hunter else 5552dd6d8a1SAdrian Hunter signr = sig; 5562dd6d8a1SAdrian Hunter 5572dd6d8a1SAdrian Hunter done = 1; 558da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 559da231338SAnand K Mistry { 560da231338SAnand K Mistry u64 tmp = 1; 561da231338SAnand K Mistry /* 562da231338SAnand K Mistry * It is possible for this signal handler to run after done is checked 563da231338SAnand K Mistry * in the main loop, but before the perf counter fds are polled. If this 564da231338SAnand K Mistry * happens, the poll() will continue to wait even though done is set, 565da231338SAnand K Mistry * and will only break out if either another signal is received, or the 566da231338SAnand K Mistry * counters are ready for read. To ensure the poll() doesn't sleep when 567da231338SAnand K Mistry * done is set, use an eventfd (done_fd) to wake up the poll(). 568da231338SAnand K Mistry */ 569da231338SAnand K Mistry if (write(done_fd, &tmp, sizeof(tmp)) < 0) 570da231338SAnand K Mistry pr_err("failed to signal wakeup fd, error: %m\n"); 571da231338SAnand K Mistry } 572da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT 5732dd6d8a1SAdrian Hunter } 5742dd6d8a1SAdrian Hunter 575a074865eSWang Nan static void sigsegv_handler(int sig) 576a074865eSWang Nan { 577a074865eSWang Nan perf_hooks__recover(); 578a074865eSWang Nan sighandler_dump_stack(sig); 579a074865eSWang Nan } 580a074865eSWang Nan 5812dd6d8a1SAdrian Hunter static void record__sig_exit(void) 5822dd6d8a1SAdrian Hunter { 5832dd6d8a1SAdrian Hunter if (signr == -1) 5842dd6d8a1SAdrian Hunter return; 5852dd6d8a1SAdrian Hunter 5862dd6d8a1SAdrian Hunter signal(signr, SIG_DFL); 5872dd6d8a1SAdrian Hunter raise(signr); 5882dd6d8a1SAdrian Hunter } 5892dd6d8a1SAdrian Hunter 590e31f0d01SAdrian Hunter #ifdef HAVE_AUXTRACE_SUPPORT 591e31f0d01SAdrian Hunter 592ef149c25SAdrian Hunter static int record__process_auxtrace(struct perf_tool *tool, 593a5830532SJiri Olsa struct mmap *map, 594ef149c25SAdrian Hunter union perf_event *event, void *data1, 595ef149c25SAdrian Hunter size_t len1, void *data2, size_t len2) 596ef149c25SAdrian Hunter { 597ef149c25SAdrian Hunter struct record *rec = container_of(tool, struct record, tool); 5988ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 599ef149c25SAdrian Hunter size_t padding; 600ef149c25SAdrian Hunter u8 pad[8] = {0}; 601ef149c25SAdrian Hunter 60246e201efSAdrian Hunter if (!perf_data__is_pipe(data) && perf_data__is_single_file(data)) { 60399fa2984SAdrian Hunter off_t file_offset; 6048ceb41d7SJiri Olsa int fd = perf_data__fd(data); 60599fa2984SAdrian Hunter int err; 60699fa2984SAdrian Hunter 60799fa2984SAdrian Hunter file_offset = lseek(fd, 0, SEEK_CUR); 60899fa2984SAdrian Hunter if (file_offset == -1) 60999fa2984SAdrian Hunter return -1; 61099fa2984SAdrian Hunter err = auxtrace_index__auxtrace_event(&rec->session->auxtrace_index, 61199fa2984SAdrian Hunter event, file_offset); 61299fa2984SAdrian Hunter if (err) 61399fa2984SAdrian Hunter return err; 61499fa2984SAdrian Hunter } 61599fa2984SAdrian Hunter 616ef149c25SAdrian Hunter /* event.auxtrace.size includes padding, see __auxtrace_mmap__read() */ 617ef149c25SAdrian Hunter padding = (len1 + len2) & 7; 618ef149c25SAdrian Hunter if (padding) 619ef149c25SAdrian Hunter padding = 8 - padding; 620ef149c25SAdrian Hunter 621ded2b8feSJiri Olsa record__write(rec, map, event, event->header.size); 622ded2b8feSJiri Olsa record__write(rec, map, data1, len1); 623ef149c25SAdrian Hunter if (len2) 624ded2b8feSJiri Olsa record__write(rec, map, data2, len2); 625ded2b8feSJiri Olsa record__write(rec, map, &pad, padding); 626ef149c25SAdrian Hunter 627ef149c25SAdrian Hunter return 0; 628ef149c25SAdrian Hunter } 629ef149c25SAdrian Hunter 630ef149c25SAdrian Hunter static int record__auxtrace_mmap_read(struct record *rec, 631a5830532SJiri Olsa struct mmap *map) 632ef149c25SAdrian Hunter { 633ef149c25SAdrian Hunter int ret; 634ef149c25SAdrian Hunter 635e035f4caSJiri Olsa ret = auxtrace_mmap__read(map, rec->itr, &rec->tool, 636ef149c25SAdrian Hunter record__process_auxtrace); 637ef149c25SAdrian Hunter if (ret < 0) 638ef149c25SAdrian Hunter return ret; 639ef149c25SAdrian Hunter 640ef149c25SAdrian Hunter if (ret) 641ef149c25SAdrian Hunter rec->samples++; 642ef149c25SAdrian Hunter 643ef149c25SAdrian Hunter return 0; 644ef149c25SAdrian Hunter } 645ef149c25SAdrian Hunter 6462dd6d8a1SAdrian Hunter static int record__auxtrace_mmap_read_snapshot(struct record *rec, 647a5830532SJiri Olsa struct mmap *map) 6482dd6d8a1SAdrian Hunter { 6492dd6d8a1SAdrian Hunter int ret; 6502dd6d8a1SAdrian Hunter 651e035f4caSJiri Olsa ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool, 6522dd6d8a1SAdrian Hunter record__process_auxtrace, 6532dd6d8a1SAdrian Hunter rec->opts.auxtrace_snapshot_size); 6542dd6d8a1SAdrian Hunter if (ret < 0) 6552dd6d8a1SAdrian Hunter return ret; 6562dd6d8a1SAdrian Hunter 6572dd6d8a1SAdrian Hunter if (ret) 6582dd6d8a1SAdrian Hunter rec->samples++; 6592dd6d8a1SAdrian Hunter 6602dd6d8a1SAdrian Hunter return 0; 6612dd6d8a1SAdrian Hunter } 6622dd6d8a1SAdrian Hunter 6632dd6d8a1SAdrian Hunter static int record__auxtrace_read_snapshot_all(struct record *rec) 6642dd6d8a1SAdrian Hunter { 6652dd6d8a1SAdrian Hunter int i; 6662dd6d8a1SAdrian Hunter int rc = 0; 6672dd6d8a1SAdrian Hunter 668c976ee11SJiri Olsa for (i = 0; i < rec->evlist->core.nr_mmaps; i++) { 669a5830532SJiri Olsa struct mmap *map = &rec->evlist->mmap[i]; 6702dd6d8a1SAdrian Hunter 671e035f4caSJiri Olsa if (!map->auxtrace_mmap.base) 6722dd6d8a1SAdrian Hunter continue; 6732dd6d8a1SAdrian Hunter 674e035f4caSJiri Olsa if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) { 6752dd6d8a1SAdrian Hunter rc = -1; 6762dd6d8a1SAdrian Hunter goto out; 6772dd6d8a1SAdrian Hunter } 6782dd6d8a1SAdrian Hunter } 6792dd6d8a1SAdrian Hunter out: 6802dd6d8a1SAdrian Hunter return rc; 6812dd6d8a1SAdrian Hunter } 6822dd6d8a1SAdrian Hunter 683ce7b0e42SAlexander Shishkin static void record__read_auxtrace_snapshot(struct record *rec, bool on_exit) 6842dd6d8a1SAdrian Hunter { 6852dd6d8a1SAdrian Hunter pr_debug("Recording AUX area tracing snapshot\n"); 6862dd6d8a1SAdrian Hunter if (record__auxtrace_read_snapshot_all(rec) < 0) { 6875f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 6882dd6d8a1SAdrian Hunter } else { 689ce7b0e42SAlexander Shishkin if (auxtrace_record__snapshot_finish(rec->itr, on_exit)) 6905f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 6915f9cf599SWang Nan else 6925f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 6932dd6d8a1SAdrian Hunter } 6942dd6d8a1SAdrian Hunter } 6952dd6d8a1SAdrian Hunter 696ce7b0e42SAlexander Shishkin static int record__auxtrace_snapshot_exit(struct record *rec) 697ce7b0e42SAlexander Shishkin { 698ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger)) 699ce7b0e42SAlexander Shishkin return 0; 700ce7b0e42SAlexander Shishkin 701ce7b0e42SAlexander Shishkin if (!auxtrace_record__snapshot_started && 702ce7b0e42SAlexander Shishkin auxtrace_record__snapshot_start(rec->itr)) 703ce7b0e42SAlexander Shishkin return -1; 704ce7b0e42SAlexander Shishkin 705ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, true); 706ce7b0e42SAlexander Shishkin if (trigger_is_error(&auxtrace_snapshot_trigger)) 707ce7b0e42SAlexander Shishkin return -1; 708ce7b0e42SAlexander Shishkin 709ce7b0e42SAlexander Shishkin return 0; 710ce7b0e42SAlexander Shishkin } 711ce7b0e42SAlexander Shishkin 7124b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec) 7134b5ea3bdSAdrian Hunter { 7144b5ea3bdSAdrian Hunter int err; 7154b5ea3bdSAdrian Hunter 7164b5ea3bdSAdrian Hunter if (!rec->itr) { 7174b5ea3bdSAdrian Hunter rec->itr = auxtrace_record__init(rec->evlist, &err); 7184b5ea3bdSAdrian Hunter if (err) 7194b5ea3bdSAdrian Hunter return err; 7204b5ea3bdSAdrian Hunter } 7214b5ea3bdSAdrian Hunter 7224b5ea3bdSAdrian Hunter err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 7234b5ea3bdSAdrian Hunter rec->opts.auxtrace_snapshot_opts); 7244b5ea3bdSAdrian Hunter if (err) 7254b5ea3bdSAdrian Hunter return err; 7264b5ea3bdSAdrian Hunter 727c0a6de06SAdrian Hunter err = auxtrace_parse_sample_options(rec->itr, rec->evlist, &rec->opts, 728c0a6de06SAdrian Hunter rec->opts.auxtrace_sample_opts); 729c0a6de06SAdrian Hunter if (err) 730c0a6de06SAdrian Hunter return err; 731c0a6de06SAdrian Hunter 7324b5ea3bdSAdrian Hunter return auxtrace_parse_filters(rec->evlist); 7334b5ea3bdSAdrian Hunter } 7344b5ea3bdSAdrian Hunter 735e31f0d01SAdrian Hunter #else 736e31f0d01SAdrian Hunter 737e31f0d01SAdrian Hunter static inline 738e31f0d01SAdrian Hunter int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 739a5830532SJiri Olsa struct mmap *map __maybe_unused) 740e31f0d01SAdrian Hunter { 741e31f0d01SAdrian Hunter return 0; 742e31f0d01SAdrian Hunter } 743e31f0d01SAdrian Hunter 7442dd6d8a1SAdrian Hunter static inline 745ce7b0e42SAlexander Shishkin void record__read_auxtrace_snapshot(struct record *rec __maybe_unused, 746ce7b0e42SAlexander Shishkin bool on_exit __maybe_unused) 7472dd6d8a1SAdrian Hunter { 7482dd6d8a1SAdrian Hunter } 7492dd6d8a1SAdrian Hunter 7502dd6d8a1SAdrian Hunter static inline 7512dd6d8a1SAdrian Hunter int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) 7522dd6d8a1SAdrian Hunter { 7532dd6d8a1SAdrian Hunter return 0; 7542dd6d8a1SAdrian Hunter } 7552dd6d8a1SAdrian Hunter 756ce7b0e42SAlexander Shishkin static inline 757ce7b0e42SAlexander Shishkin int record__auxtrace_snapshot_exit(struct record *rec __maybe_unused) 758ce7b0e42SAlexander Shishkin { 759ce7b0e42SAlexander Shishkin return 0; 760ce7b0e42SAlexander Shishkin } 761ce7b0e42SAlexander Shishkin 7624b5ea3bdSAdrian Hunter static int record__auxtrace_init(struct record *rec __maybe_unused) 7634b5ea3bdSAdrian Hunter { 7644b5ea3bdSAdrian Hunter return 0; 7654b5ea3bdSAdrian Hunter } 7664b5ea3bdSAdrian Hunter 767e31f0d01SAdrian Hunter #endif 768e31f0d01SAdrian Hunter 769246eba8eSAdrian Hunter static int record__config_text_poke(struct evlist *evlist) 770246eba8eSAdrian Hunter { 771246eba8eSAdrian Hunter struct evsel *evsel; 772246eba8eSAdrian Hunter int err; 773246eba8eSAdrian Hunter 774246eba8eSAdrian Hunter /* Nothing to do if text poke is already configured */ 775246eba8eSAdrian Hunter evlist__for_each_entry(evlist, evsel) { 776246eba8eSAdrian Hunter if (evsel->core.attr.text_poke) 777246eba8eSAdrian Hunter return 0; 778246eba8eSAdrian Hunter } 779246eba8eSAdrian Hunter 780246eba8eSAdrian Hunter err = parse_events(evlist, "dummy:u", NULL); 781246eba8eSAdrian Hunter if (err) 782246eba8eSAdrian Hunter return err; 783246eba8eSAdrian Hunter 784246eba8eSAdrian Hunter evsel = evlist__last(evlist); 785246eba8eSAdrian Hunter 786246eba8eSAdrian Hunter evsel->core.attr.freq = 0; 787246eba8eSAdrian Hunter evsel->core.attr.sample_period = 1; 788246eba8eSAdrian Hunter evsel->core.attr.text_poke = 1; 789246eba8eSAdrian Hunter evsel->core.attr.ksymbol = 1; 790246eba8eSAdrian Hunter 791246eba8eSAdrian Hunter evsel->core.system_wide = true; 792246eba8eSAdrian Hunter evsel->no_aux_samples = true; 793246eba8eSAdrian Hunter evsel->immediate = true; 794246eba8eSAdrian Hunter 795246eba8eSAdrian Hunter /* Text poke must be collected on all CPUs */ 796246eba8eSAdrian Hunter perf_cpu_map__put(evsel->core.own_cpus); 797246eba8eSAdrian Hunter evsel->core.own_cpus = perf_cpu_map__new(NULL); 798246eba8eSAdrian Hunter perf_cpu_map__put(evsel->core.cpus); 799246eba8eSAdrian Hunter evsel->core.cpus = perf_cpu_map__get(evsel->core.own_cpus); 800246eba8eSAdrian Hunter 801246eba8eSAdrian Hunter evsel__set_sample_bit(evsel, TIME); 802246eba8eSAdrian Hunter 803246eba8eSAdrian Hunter return 0; 804246eba8eSAdrian Hunter } 805246eba8eSAdrian Hunter 806eeb399b5SAdrian Hunter static bool record__kcore_readable(struct machine *machine) 807eeb399b5SAdrian Hunter { 808eeb399b5SAdrian Hunter char kcore[PATH_MAX]; 809eeb399b5SAdrian Hunter int fd; 810eeb399b5SAdrian Hunter 811eeb399b5SAdrian Hunter scnprintf(kcore, sizeof(kcore), "%s/proc/kcore", machine->root_dir); 812eeb399b5SAdrian Hunter 813eeb399b5SAdrian Hunter fd = open(kcore, O_RDONLY); 814eeb399b5SAdrian Hunter if (fd < 0) 815eeb399b5SAdrian Hunter return false; 816eeb399b5SAdrian Hunter 817eeb399b5SAdrian Hunter close(fd); 818eeb399b5SAdrian Hunter 819eeb399b5SAdrian Hunter return true; 820eeb399b5SAdrian Hunter } 821eeb399b5SAdrian Hunter 822eeb399b5SAdrian Hunter static int record__kcore_copy(struct machine *machine, struct perf_data *data) 823eeb399b5SAdrian Hunter { 824eeb399b5SAdrian Hunter char from_dir[PATH_MAX]; 825eeb399b5SAdrian Hunter char kcore_dir[PATH_MAX]; 826eeb399b5SAdrian Hunter int ret; 827eeb399b5SAdrian Hunter 828eeb399b5SAdrian Hunter snprintf(from_dir, sizeof(from_dir), "%s/proc", machine->root_dir); 829eeb399b5SAdrian Hunter 830eeb399b5SAdrian Hunter ret = perf_data__make_kcore_dir(data, kcore_dir, sizeof(kcore_dir)); 831eeb399b5SAdrian Hunter if (ret) 832eeb399b5SAdrian Hunter return ret; 833eeb399b5SAdrian Hunter 834eeb399b5SAdrian Hunter return kcore_copy(from_dir, kcore_dir); 835eeb399b5SAdrian Hunter } 836eeb399b5SAdrian Hunter 837cda57a8cSWang Nan static int record__mmap_evlist(struct record *rec, 83863503dbaSJiri Olsa struct evlist *evlist) 839cda57a8cSWang Nan { 840cda57a8cSWang Nan struct record_opts *opts = &rec->opts; 841c0a6de06SAdrian Hunter bool auxtrace_overwrite = opts->auxtrace_snapshot_mode || 842c0a6de06SAdrian Hunter opts->auxtrace_sample_mode; 843cda57a8cSWang Nan char msg[512]; 844cda57a8cSWang Nan 845f13de660SAlexey Budankov if (opts->affinity != PERF_AFFINITY_SYS) 846f13de660SAlexey Budankov cpu__setup_cpunode_map(); 847f13de660SAlexey Budankov 8489521b5f2SJiri Olsa if (evlist__mmap_ex(evlist, opts->mmap_pages, 849cda57a8cSWang Nan opts->auxtrace_mmap_pages, 850c0a6de06SAdrian Hunter auxtrace_overwrite, 851470530bbSAlexey Budankov opts->nr_cblocks, opts->affinity, 85251255a8aSAlexey Budankov opts->mmap_flush, opts->comp_level) < 0) { 853cda57a8cSWang Nan if (errno == EPERM) { 854cda57a8cSWang Nan pr_err("Permission error mapping pages.\n" 855cda57a8cSWang Nan "Consider increasing " 856cda57a8cSWang Nan "/proc/sys/kernel/perf_event_mlock_kb,\n" 857cda57a8cSWang Nan "or try again with a smaller value of -m/--mmap_pages.\n" 858cda57a8cSWang Nan "(current value: %u,%u)\n", 859cda57a8cSWang Nan opts->mmap_pages, opts->auxtrace_mmap_pages); 860cda57a8cSWang Nan return -errno; 861cda57a8cSWang Nan } else { 862cda57a8cSWang Nan pr_err("failed to mmap with %d (%s)\n", errno, 863c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 864cda57a8cSWang Nan if (errno) 865cda57a8cSWang Nan return -errno; 866cda57a8cSWang Nan else 867cda57a8cSWang Nan return -EINVAL; 868cda57a8cSWang Nan } 869cda57a8cSWang Nan } 870cda57a8cSWang Nan return 0; 871cda57a8cSWang Nan } 872cda57a8cSWang Nan 873cda57a8cSWang Nan static int record__mmap(struct record *rec) 874cda57a8cSWang Nan { 875cda57a8cSWang Nan return record__mmap_evlist(rec, rec->evlist); 876cda57a8cSWang Nan } 877cda57a8cSWang Nan 8788c6f45a7SArnaldo Carvalho de Melo static int record__open(struct record *rec) 879dd7927f4SArnaldo Carvalho de Melo { 880d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 88132dcd021SJiri Olsa struct evsel *pos; 88263503dbaSJiri Olsa struct evlist *evlist = rec->evlist; 883d20deb64SArnaldo Carvalho de Melo struct perf_session *session = rec->session; 884b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 8858d3eca20SDavid Ahern int rc = 0; 886dd7927f4SArnaldo Carvalho de Melo 887d3dbf43cSArnaldo Carvalho de Melo /* 8880a892c1cSIan Rogers * For initial_delay or system wide, we need to add a dummy event so 8890a892c1cSIan Rogers * that we can track PERF_RECORD_MMAP to cover the delay of waiting or 8900a892c1cSIan Rogers * event synthesis. 891d3dbf43cSArnaldo Carvalho de Melo */ 8920a892c1cSIan Rogers if (opts->initial_delay || target__has_cpu(&opts->target)) { 893442ad225SAdrian Hunter pos = perf_evlist__get_tracking_event(evlist); 894442ad225SAdrian Hunter if (!evsel__is_dummy_event(pos)) { 895442ad225SAdrian Hunter /* Set up dummy event. */ 896e251abeeSArnaldo Carvalho de Melo if (evlist__add_dummy(evlist)) 897d3dbf43cSArnaldo Carvalho de Melo return -ENOMEM; 898515dbe48SJiri Olsa pos = evlist__last(evlist); 899442ad225SAdrian Hunter perf_evlist__set_tracking_event(evlist, pos); 900442ad225SAdrian Hunter } 901442ad225SAdrian Hunter 9020a892c1cSIan Rogers /* 9030a892c1cSIan Rogers * Enable the dummy event when the process is forked for 9040a892c1cSIan Rogers * initial_delay, immediately for system wide. 9050a892c1cSIan Rogers */ 906442ad225SAdrian Hunter if (opts->initial_delay && !pos->immediate) 9071fc632ceSJiri Olsa pos->core.attr.enable_on_exec = 1; 9080a892c1cSIan Rogers else 9090a892c1cSIan Rogers pos->immediate = 1; 910d3dbf43cSArnaldo Carvalho de Melo } 911d3dbf43cSArnaldo Carvalho de Melo 912e68ae9cfSArnaldo Carvalho de Melo perf_evlist__config(evlist, opts, &callchain_param); 913cac21425SJiri Olsa 914e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evlist, pos) { 9153da297a6SIngo Molnar try_again: 916af663bd0SJiri Olsa if (evsel__open(pos, pos->core.cpus, pos->core.threads) < 0) { 917ae430892SArnaldo Carvalho de Melo if (evsel__fallback(pos, errno, msg, sizeof(msg))) { 918bb963e16SNamhyung Kim if (verbose > 0) 919c0a54341SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 9203da297a6SIngo Molnar goto try_again; 9213da297a6SIngo Molnar } 922cf99ad14SAndi Kleen if ((errno == EINVAL || errno == EBADF) && 923cf99ad14SAndi Kleen pos->leader != pos && 924cf99ad14SAndi Kleen pos->weak_group) { 9254804e011SAndi Kleen pos = perf_evlist__reset_weak_group(evlist, pos, true); 926cf99ad14SAndi Kleen goto try_again; 927cf99ad14SAndi Kleen } 92856e52e85SArnaldo Carvalho de Melo rc = -errno; 9292bb72dbbSArnaldo Carvalho de Melo evsel__open_strerror(pos, &opts->target, errno, msg, sizeof(msg)); 93056e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 9318d3eca20SDavid Ahern goto out; 9327c6a1c65SPeter Zijlstra } 933bfd8f72cSAndi Kleen 934bfd8f72cSAndi Kleen pos->supported = true; 9357c6a1c65SPeter Zijlstra } 9367c6a1c65SPeter Zijlstra 937c8b567c8SArnaldo Carvalho de Melo if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(evlist)) { 938c8b567c8SArnaldo Carvalho de Melo pr_warning( 939c8b567c8SArnaldo Carvalho de Melo "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 940c8b567c8SArnaldo Carvalho de Melo "check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n" 941c8b567c8SArnaldo Carvalho de Melo "Samples in kernel functions may not be resolved if a suitable vmlinux\n" 942c8b567c8SArnaldo Carvalho de Melo "file is not found in the buildid cache or in the vmlinux path.\n\n" 943c8b567c8SArnaldo Carvalho de Melo "Samples in kernel modules won't be resolved at all.\n\n" 944c8b567c8SArnaldo Carvalho de Melo "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 945c8b567c8SArnaldo Carvalho de Melo "even with a suitable vmlinux or kallsyms file.\n\n"); 946c8b567c8SArnaldo Carvalho de Melo } 947c8b567c8SArnaldo Carvalho de Melo 94823d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evlist, &pos)) { 94962d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 9508ab2e96dSArnaldo Carvalho de Melo pos->filter, evsel__name(pos), errno, 951c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 9528d3eca20SDavid Ahern rc = -1; 9538d3eca20SDavid Ahern goto out; 9540a102479SFrederic Weisbecker } 9550a102479SFrederic Weisbecker 956cda57a8cSWang Nan rc = record__mmap(rec); 957cda57a8cSWang Nan if (rc) 9588d3eca20SDavid Ahern goto out; 9590a27d7f9SArnaldo Carvalho de Melo 960a91e5431SArnaldo Carvalho de Melo session->evlist = evlist; 9617b56cce2SArnaldo Carvalho de Melo perf_session__set_id_hdr_size(session); 9628d3eca20SDavid Ahern out: 9638d3eca20SDavid Ahern return rc; 964a91e5431SArnaldo Carvalho de Melo } 965a91e5431SArnaldo Carvalho de Melo 966e3d59112SNamhyung Kim static int process_sample_event(struct perf_tool *tool, 967e3d59112SNamhyung Kim union perf_event *event, 968e3d59112SNamhyung Kim struct perf_sample *sample, 96932dcd021SJiri Olsa struct evsel *evsel, 970e3d59112SNamhyung Kim struct machine *machine) 971e3d59112SNamhyung Kim { 972e3d59112SNamhyung Kim struct record *rec = container_of(tool, struct record, tool); 973e3d59112SNamhyung Kim 97468588bafSJin Yao if (rec->evlist->first_sample_time == 0) 97568588bafSJin Yao rec->evlist->first_sample_time = sample->time; 976e3d59112SNamhyung Kim 97768588bafSJin Yao rec->evlist->last_sample_time = sample->time; 97868588bafSJin Yao 97968588bafSJin Yao if (rec->buildid_all) 98068588bafSJin Yao return 0; 98168588bafSJin Yao 98268588bafSJin Yao rec->samples++; 983e3d59112SNamhyung Kim return build_id__mark_dso_hit(tool, event, sample, evsel, machine); 984e3d59112SNamhyung Kim } 985e3d59112SNamhyung Kim 9868c6f45a7SArnaldo Carvalho de Melo static int process_buildids(struct record *rec) 9876122e4e4SArnaldo Carvalho de Melo { 988f5fc1412SJiri Olsa struct perf_session *session = rec->session; 9896122e4e4SArnaldo Carvalho de Melo 99045112e89SJiri Olsa if (perf_data__size(&rec->data) == 0) 9919f591fd7SArnaldo Carvalho de Melo return 0; 9929f591fd7SArnaldo Carvalho de Melo 99300dc8657SNamhyung Kim /* 99400dc8657SNamhyung Kim * During this process, it'll load kernel map and replace the 99500dc8657SNamhyung Kim * dso->long_name to a real pathname it found. In this case 99600dc8657SNamhyung Kim * we prefer the vmlinux path like 99700dc8657SNamhyung Kim * /lib/modules/3.16.4/build/vmlinux 99800dc8657SNamhyung Kim * 99900dc8657SNamhyung Kim * rather than build-id path (in debug directory). 100000dc8657SNamhyung Kim * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551 100100dc8657SNamhyung Kim */ 100200dc8657SNamhyung Kim symbol_conf.ignore_vmlinux_buildid = true; 100300dc8657SNamhyung Kim 10046156681bSNamhyung Kim /* 10056156681bSNamhyung Kim * If --buildid-all is given, it marks all DSO regardless of hits, 100668588bafSJin Yao * so no need to process samples. But if timestamp_boundary is enabled, 100768588bafSJin Yao * it still needs to walk on all samples to get the timestamps of 100868588bafSJin Yao * first/last samples. 10096156681bSNamhyung Kim */ 101068588bafSJin Yao if (rec->buildid_all && !rec->timestamp_boundary) 10116156681bSNamhyung Kim rec->tool.sample = NULL; 10126156681bSNamhyung Kim 1013b7b61cbeSArnaldo Carvalho de Melo return perf_session__process_events(session); 10146122e4e4SArnaldo Carvalho de Melo } 10156122e4e4SArnaldo Carvalho de Melo 10168115d60cSArnaldo Carvalho de Melo static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 1017a1645ce1SZhang, Yanmin { 1018a1645ce1SZhang, Yanmin int err; 101945694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = data; 1020a1645ce1SZhang, Yanmin /* 1021a1645ce1SZhang, Yanmin *As for guest kernel when processing subcommand record&report, 1022a1645ce1SZhang, Yanmin *we arrange module mmap prior to guest kernel mmap and trigger 1023a1645ce1SZhang, Yanmin *a preload dso because default guest module symbols are loaded 1024a1645ce1SZhang, Yanmin *from guest kallsyms instead of /lib/modules/XXX/XXX. This 1025a1645ce1SZhang, Yanmin *method is used to avoid symbol missing when the first addr is 1026a1645ce1SZhang, Yanmin *in module instead of in guest kernel. 1027a1645ce1SZhang, Yanmin */ 102845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_modules(tool, process_synthesized_event, 1029743eb868SArnaldo Carvalho de Melo machine); 1030a1645ce1SZhang, Yanmin if (err < 0) 1031a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 103223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 1033a1645ce1SZhang, Yanmin 1034a1645ce1SZhang, Yanmin /* 1035a1645ce1SZhang, Yanmin * We use _stext for guest kernel because guest kernel's /proc/kallsyms 1036a1645ce1SZhang, Yanmin * have no _text sometimes. 1037a1645ce1SZhang, Yanmin */ 103845694aa7SArnaldo Carvalho de Melo err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 10390ae617beSAdrian Hunter machine); 1040a1645ce1SZhang, Yanmin if (err < 0) 1041a1645ce1SZhang, Yanmin pr_err("Couldn't record guest kernel [%d]'s reference" 104223346f21SArnaldo Carvalho de Melo " relocation symbol.\n", machine->pid); 1043a1645ce1SZhang, Yanmin } 1044a1645ce1SZhang, Yanmin 104598402807SFrederic Weisbecker static struct perf_event_header finished_round_event = { 104698402807SFrederic Weisbecker .size = sizeof(struct perf_event_header), 104798402807SFrederic Weisbecker .type = PERF_RECORD_FINISHED_ROUND, 104898402807SFrederic Weisbecker }; 104998402807SFrederic Weisbecker 1050a5830532SJiri Olsa static void record__adjust_affinity(struct record *rec, struct mmap *map) 1051f13de660SAlexey Budankov { 1052f13de660SAlexey Budankov if (rec->opts.affinity != PERF_AFFINITY_SYS && 10538384a260SAlexey Budankov !bitmap_equal(rec->affinity_mask.bits, map->affinity_mask.bits, 10548384a260SAlexey Budankov rec->affinity_mask.nbits)) { 10558384a260SAlexey Budankov bitmap_zero(rec->affinity_mask.bits, rec->affinity_mask.nbits); 10568384a260SAlexey Budankov bitmap_or(rec->affinity_mask.bits, rec->affinity_mask.bits, 10578384a260SAlexey Budankov map->affinity_mask.bits, rec->affinity_mask.nbits); 10588384a260SAlexey Budankov sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&rec->affinity_mask), 10598384a260SAlexey Budankov (cpu_set_t *)rec->affinity_mask.bits); 10608384a260SAlexey Budankov if (verbose == 2) 10618384a260SAlexey Budankov mmap_cpu_mask__scnprintf(&rec->affinity_mask, "thread"); 1062f13de660SAlexey Budankov } 1063f13de660SAlexey Budankov } 1064f13de660SAlexey Budankov 10655d7f4116SAlexey Budankov static size_t process_comp_header(void *record, size_t increment) 10665d7f4116SAlexey Budankov { 106772932371SJiri Olsa struct perf_record_compressed *event = record; 10685d7f4116SAlexey Budankov size_t size = sizeof(*event); 10695d7f4116SAlexey Budankov 10705d7f4116SAlexey Budankov if (increment) { 10715d7f4116SAlexey Budankov event->header.size += increment; 10725d7f4116SAlexey Budankov return increment; 10735d7f4116SAlexey Budankov } 10745d7f4116SAlexey Budankov 10755d7f4116SAlexey Budankov event->header.type = PERF_RECORD_COMPRESSED; 10765d7f4116SAlexey Budankov event->header.size = size; 10775d7f4116SAlexey Budankov 10785d7f4116SAlexey Budankov return size; 10795d7f4116SAlexey Budankov } 10805d7f4116SAlexey Budankov 10815d7f4116SAlexey Budankov static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 10825d7f4116SAlexey Budankov void *src, size_t src_size) 10835d7f4116SAlexey Budankov { 10845d7f4116SAlexey Budankov size_t compressed; 108572932371SJiri Olsa size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct perf_record_compressed) - 1; 10865d7f4116SAlexey Budankov 10875d7f4116SAlexey Budankov compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size, 10885d7f4116SAlexey Budankov max_record_size, process_comp_header); 10895d7f4116SAlexey Budankov 10905d7f4116SAlexey Budankov session->bytes_transferred += src_size; 10915d7f4116SAlexey Budankov session->bytes_compressed += compressed; 10925d7f4116SAlexey Budankov 10935d7f4116SAlexey Budankov return compressed; 10945d7f4116SAlexey Budankov } 10955d7f4116SAlexey Budankov 109663503dbaSJiri Olsa static int record__mmap_read_evlist(struct record *rec, struct evlist *evlist, 1097470530bbSAlexey Budankov bool overwrite, bool synch) 109898402807SFrederic Weisbecker { 1099dcabb507SJiri Olsa u64 bytes_written = rec->bytes_written; 11000e2e63ddSPeter Zijlstra int i; 11018d3eca20SDavid Ahern int rc = 0; 1102a5830532SJiri Olsa struct mmap *maps; 1103d3d1af6fSAlexey Budankov int trace_fd = rec->data.file.fd; 1104ef781128SAlexey Budankov off_t off = 0; 110598402807SFrederic Weisbecker 1106cb21686bSWang Nan if (!evlist) 1107cb21686bSWang Nan return 0; 1108ef149c25SAdrian Hunter 11090b72d69aSWang Nan maps = overwrite ? evlist->overwrite_mmap : evlist->mmap; 1110a4ea0ec4SWang Nan if (!maps) 1111a4ea0ec4SWang Nan return 0; 1112cb21686bSWang Nan 11130b72d69aSWang Nan if (overwrite && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) 111454cc54deSWang Nan return 0; 111554cc54deSWang Nan 1116d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 1117d3d1af6fSAlexey Budankov off = record__aio_get_pos(trace_fd); 1118d3d1af6fSAlexey Budankov 1119c976ee11SJiri Olsa for (i = 0; i < evlist->core.nr_mmaps; i++) { 1120470530bbSAlexey Budankov u64 flush = 0; 1121a5830532SJiri Olsa struct mmap *map = &maps[i]; 1122a4ea0ec4SWang Nan 1123547740f7SJiri Olsa if (map->core.base) { 1124f13de660SAlexey Budankov record__adjust_affinity(rec, map); 1125470530bbSAlexey Budankov if (synch) { 112665aa2e6bSJiri Olsa flush = map->core.flush; 112765aa2e6bSJiri Olsa map->core.flush = 1; 1128470530bbSAlexey Budankov } 1129d3d1af6fSAlexey Budankov if (!record__aio_enabled(rec)) { 1130ef781128SAlexey Budankov if (perf_mmap__push(map, rec, record__pushfn) < 0) { 1131470530bbSAlexey Budankov if (synch) 113265aa2e6bSJiri Olsa map->core.flush = flush; 11338d3eca20SDavid Ahern rc = -1; 11348d3eca20SDavid Ahern goto out; 11358d3eca20SDavid Ahern } 1136d3d1af6fSAlexey Budankov } else { 1137ef781128SAlexey Budankov if (record__aio_push(rec, map, &off) < 0) { 1138d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 1139470530bbSAlexey Budankov if (synch) 114065aa2e6bSJiri Olsa map->core.flush = flush; 1141d3d1af6fSAlexey Budankov rc = -1; 1142d3d1af6fSAlexey Budankov goto out; 1143d3d1af6fSAlexey Budankov } 1144d3d1af6fSAlexey Budankov } 1145470530bbSAlexey Budankov if (synch) 114665aa2e6bSJiri Olsa map->core.flush = flush; 11478d3eca20SDavid Ahern } 1148ef149c25SAdrian Hunter 1149e035f4caSJiri Olsa if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode && 1150c0a6de06SAdrian Hunter !rec->opts.auxtrace_sample_mode && 1151e035f4caSJiri Olsa record__auxtrace_mmap_read(rec, map) != 0) { 1152ef149c25SAdrian Hunter rc = -1; 1153ef149c25SAdrian Hunter goto out; 1154ef149c25SAdrian Hunter } 115598402807SFrederic Weisbecker } 115698402807SFrederic Weisbecker 1157d3d1af6fSAlexey Budankov if (record__aio_enabled(rec)) 1158d3d1af6fSAlexey Budankov record__aio_set_pos(trace_fd, off); 1159d3d1af6fSAlexey Budankov 1160dcabb507SJiri Olsa /* 1161dcabb507SJiri Olsa * Mark the round finished in case we wrote 1162dcabb507SJiri Olsa * at least one event. 1163dcabb507SJiri Olsa */ 1164dcabb507SJiri Olsa if (bytes_written != rec->bytes_written) 1165ded2b8feSJiri Olsa rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event)); 11668d3eca20SDavid Ahern 11670b72d69aSWang Nan if (overwrite) 116854cc54deSWang Nan perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 11698d3eca20SDavid Ahern out: 11708d3eca20SDavid Ahern return rc; 117198402807SFrederic Weisbecker } 117298402807SFrederic Weisbecker 1173470530bbSAlexey Budankov static int record__mmap_read_all(struct record *rec, bool synch) 1174cb21686bSWang Nan { 1175cb21686bSWang Nan int err; 1176cb21686bSWang Nan 1177470530bbSAlexey Budankov err = record__mmap_read_evlist(rec, rec->evlist, false, synch); 1178cb21686bSWang Nan if (err) 1179cb21686bSWang Nan return err; 1180cb21686bSWang Nan 1181470530bbSAlexey Budankov return record__mmap_read_evlist(rec, rec->evlist, true, synch); 1182cb21686bSWang Nan } 1183cb21686bSWang Nan 11848c6f45a7SArnaldo Carvalho de Melo static void record__init_features(struct record *rec) 118557706abcSDavid Ahern { 118657706abcSDavid Ahern struct perf_session *session = rec->session; 118757706abcSDavid Ahern int feat; 118857706abcSDavid Ahern 118957706abcSDavid Ahern for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 119057706abcSDavid Ahern perf_header__set_feat(&session->header, feat); 119157706abcSDavid Ahern 119257706abcSDavid Ahern if (rec->no_buildid) 119357706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 119457706abcSDavid Ahern 1195ce9036a6SJiri Olsa if (!have_tracepoints(&rec->evlist->core.entries)) 119657706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 119757706abcSDavid Ahern 119857706abcSDavid Ahern if (!rec->opts.branch_stack) 119957706abcSDavid Ahern perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 1200ef149c25SAdrian Hunter 1201ef149c25SAdrian Hunter if (!rec->opts.full_auxtrace) 1202ef149c25SAdrian Hunter perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 1203ffa517adSJiri Olsa 1204cf790516SAlexey Budankov if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns)) 1205cf790516SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_CLOCKID); 1206cf790516SAlexey Budankov 1207258031c0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); 120842e1fd80SAlexey Budankov if (!record__comp_enabled(rec)) 120942e1fd80SAlexey Budankov perf_header__clear_feat(&session->header, HEADER_COMPRESSED); 1210258031c0SJiri Olsa 1211ffa517adSJiri Olsa perf_header__clear_feat(&session->header, HEADER_STAT); 121257706abcSDavid Ahern } 121357706abcSDavid Ahern 1214e1ab48baSWang Nan static void 1215e1ab48baSWang Nan record__finish_output(struct record *rec) 1216e1ab48baSWang Nan { 12178ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 12188ceb41d7SJiri Olsa int fd = perf_data__fd(data); 1219e1ab48baSWang Nan 12208ceb41d7SJiri Olsa if (data->is_pipe) 1221e1ab48baSWang Nan return; 1222e1ab48baSWang Nan 1223e1ab48baSWang Nan rec->session->header.data_size += rec->bytes_written; 122445112e89SJiri Olsa data->file.size = lseek(perf_data__fd(data), 0, SEEK_CUR); 1225e1ab48baSWang Nan 1226e1ab48baSWang Nan if (!rec->no_buildid) { 1227e1ab48baSWang Nan process_buildids(rec); 1228e1ab48baSWang Nan 1229e1ab48baSWang Nan if (rec->buildid_all) 1230e1ab48baSWang Nan dsos__hit_all(rec->session); 1231e1ab48baSWang Nan } 1232e1ab48baSWang Nan perf_session__write_header(rec->session, rec->evlist, fd, true); 1233e1ab48baSWang Nan 1234e1ab48baSWang Nan return; 1235e1ab48baSWang Nan } 1236e1ab48baSWang Nan 12374ea648aeSWang Nan static int record__synthesize_workload(struct record *rec, bool tail) 1238be7b0c9eSWang Nan { 12399d6aae72SArnaldo Carvalho de Melo int err; 12409749b90eSJiri Olsa struct perf_thread_map *thread_map; 1241be7b0c9eSWang Nan 12424ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 12434ea648aeSWang Nan return 0; 12444ea648aeSWang Nan 12459d6aae72SArnaldo Carvalho de Melo thread_map = thread_map__new_by_tid(rec->evlist->workload.pid); 12469d6aae72SArnaldo Carvalho de Melo if (thread_map == NULL) 12479d6aae72SArnaldo Carvalho de Melo return -1; 12489d6aae72SArnaldo Carvalho de Melo 12499d6aae72SArnaldo Carvalho de Melo err = perf_event__synthesize_thread_map(&rec->tool, thread_map, 1250be7b0c9eSWang Nan process_synthesized_event, 1251be7b0c9eSWang Nan &rec->session->machines.host, 12523fcb10e4SMark Drayton rec->opts.sample_address); 12537836e52eSJiri Olsa perf_thread_map__put(thread_map); 12549d6aae72SArnaldo Carvalho de Melo return err; 1255be7b0c9eSWang Nan } 1256be7b0c9eSWang Nan 12574ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail); 12583c1cb7e3SWang Nan 1259ecfd7a9cSWang Nan static int 1260ecfd7a9cSWang Nan record__switch_output(struct record *rec, bool at_exit) 1261ecfd7a9cSWang Nan { 12628ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1263ecfd7a9cSWang Nan int fd, err; 126403724b2eSAndi Kleen char *new_filename; 1265ecfd7a9cSWang Nan 1266ecfd7a9cSWang Nan /* Same Size: "2015122520103046"*/ 1267ecfd7a9cSWang Nan char timestamp[] = "InvalidTimestamp"; 1268ecfd7a9cSWang Nan 1269d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 1270d3d1af6fSAlexey Budankov 12714ea648aeSWang Nan record__synthesize(rec, true); 12724ea648aeSWang Nan if (target__none(&rec->opts.target)) 12734ea648aeSWang Nan record__synthesize_workload(rec, true); 12744ea648aeSWang Nan 1275ecfd7a9cSWang Nan rec->samples = 0; 1276ecfd7a9cSWang Nan record__finish_output(rec); 1277ecfd7a9cSWang Nan err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 1278ecfd7a9cSWang Nan if (err) { 1279ecfd7a9cSWang Nan pr_err("Failed to get current timestamp\n"); 1280ecfd7a9cSWang Nan return -EINVAL; 1281ecfd7a9cSWang Nan } 1282ecfd7a9cSWang Nan 12838ceb41d7SJiri Olsa fd = perf_data__switch(data, timestamp, 1284ecfd7a9cSWang Nan rec->session->header.data_offset, 128503724b2eSAndi Kleen at_exit, &new_filename); 1286ecfd7a9cSWang Nan if (fd >= 0 && !at_exit) { 1287ecfd7a9cSWang Nan rec->bytes_written = 0; 1288ecfd7a9cSWang Nan rec->session->header.data_size = 0; 1289ecfd7a9cSWang Nan } 1290ecfd7a9cSWang Nan 1291ecfd7a9cSWang Nan if (!quiet) 1292ecfd7a9cSWang Nan fprintf(stderr, "[ perf record: Dump %s.%s ]\n", 12932d4f2799SJiri Olsa data->path, timestamp); 12943c1cb7e3SWang Nan 129503724b2eSAndi Kleen if (rec->switch_output.num_files) { 129603724b2eSAndi Kleen int n = rec->switch_output.cur_file + 1; 129703724b2eSAndi Kleen 129803724b2eSAndi Kleen if (n >= rec->switch_output.num_files) 129903724b2eSAndi Kleen n = 0; 130003724b2eSAndi Kleen rec->switch_output.cur_file = n; 130103724b2eSAndi Kleen if (rec->switch_output.filenames[n]) { 130203724b2eSAndi Kleen remove(rec->switch_output.filenames[n]); 1303d8f9da24SArnaldo Carvalho de Melo zfree(&rec->switch_output.filenames[n]); 130403724b2eSAndi Kleen } 130503724b2eSAndi Kleen rec->switch_output.filenames[n] = new_filename; 130603724b2eSAndi Kleen } else { 130703724b2eSAndi Kleen free(new_filename); 130803724b2eSAndi Kleen } 130903724b2eSAndi Kleen 13103c1cb7e3SWang Nan /* Output tracking events */ 1311be7b0c9eSWang Nan if (!at_exit) { 13124ea648aeSWang Nan record__synthesize(rec, false); 13133c1cb7e3SWang Nan 1314be7b0c9eSWang Nan /* 1315be7b0c9eSWang Nan * In 'perf record --switch-output' without -a, 1316be7b0c9eSWang Nan * record__synthesize() in record__switch_output() won't 1317be7b0c9eSWang Nan * generate tracking events because there's no thread_map 1318be7b0c9eSWang Nan * in evlist. Which causes newly created perf.data doesn't 1319be7b0c9eSWang Nan * contain map and comm information. 1320be7b0c9eSWang Nan * Create a fake thread_map and directly call 1321be7b0c9eSWang Nan * perf_event__synthesize_thread_map() for those events. 1322be7b0c9eSWang Nan */ 1323be7b0c9eSWang Nan if (target__none(&rec->opts.target)) 13244ea648aeSWang Nan record__synthesize_workload(rec, false); 1325be7b0c9eSWang Nan } 1326ecfd7a9cSWang Nan return fd; 1327ecfd7a9cSWang Nan } 1328ecfd7a9cSWang Nan 1329f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 1330f33cbe72SArnaldo Carvalho de Melo 1331f33cbe72SArnaldo Carvalho de Melo /* 1332f33cbe72SArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 1333f33cbe72SArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 1334f33cbe72SArnaldo Carvalho de Melo * want_signal to true. 1335f33cbe72SArnaldo Carvalho de Melo */ 133645604710SNamhyung Kim static void workload_exec_failed_signal(int signo __maybe_unused, 133745604710SNamhyung Kim siginfo_t *info, 1338f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 1339f33cbe72SArnaldo Carvalho de Melo { 1340f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 1341f33cbe72SArnaldo Carvalho de Melo done = 1; 1342f33cbe72SArnaldo Carvalho de Melo child_finished = 1; 1343f33cbe72SArnaldo Carvalho de Melo } 1344f33cbe72SArnaldo Carvalho de Melo 13452dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig); 1346bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig); 13472dd6d8a1SAdrian Hunter 1348ee667f94SWang Nan static const struct perf_event_mmap_page * 134963503dbaSJiri Olsa perf_evlist__pick_pc(struct evlist *evlist) 1350ee667f94SWang Nan { 1351b2cb615dSWang Nan if (evlist) { 1352547740f7SJiri Olsa if (evlist->mmap && evlist->mmap[0].core.base) 1353547740f7SJiri Olsa return evlist->mmap[0].core.base; 1354547740f7SJiri Olsa if (evlist->overwrite_mmap && evlist->overwrite_mmap[0].core.base) 1355547740f7SJiri Olsa return evlist->overwrite_mmap[0].core.base; 1356b2cb615dSWang Nan } 1357ee667f94SWang Nan return NULL; 1358ee667f94SWang Nan } 1359ee667f94SWang Nan 1360c45628b0SWang Nan static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) 1361c45628b0SWang Nan { 1362ee667f94SWang Nan const struct perf_event_mmap_page *pc; 1363ee667f94SWang Nan 1364ee667f94SWang Nan pc = perf_evlist__pick_pc(rec->evlist); 1365ee667f94SWang Nan if (pc) 1366ee667f94SWang Nan return pc; 1367c45628b0SWang Nan return NULL; 1368c45628b0SWang Nan } 1369c45628b0SWang Nan 13704ea648aeSWang Nan static int record__synthesize(struct record *rec, bool tail) 1371c45c86ebSWang Nan { 1372c45c86ebSWang Nan struct perf_session *session = rec->session; 1373c45c86ebSWang Nan struct machine *machine = &session->machines.host; 13748ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1375c45c86ebSWang Nan struct record_opts *opts = &rec->opts; 1376c45c86ebSWang Nan struct perf_tool *tool = &rec->tool; 13778ceb41d7SJiri Olsa int fd = perf_data__fd(data); 1378c45c86ebSWang Nan int err = 0; 1379d99c22eaSStephane Eranian event_op f = process_synthesized_event; 1380c45c86ebSWang Nan 13814ea648aeSWang Nan if (rec->opts.tail_synthesize != tail) 13824ea648aeSWang Nan return 0; 13834ea648aeSWang Nan 13848ceb41d7SJiri Olsa if (data->is_pipe) { 1385a2015516SJiri Olsa /* 1386a2015516SJiri Olsa * We need to synthesize events first, because some 1387a2015516SJiri Olsa * features works on top of them (on report side). 1388a2015516SJiri Olsa */ 1389318ec184SJiri Olsa err = perf_event__synthesize_attrs(tool, rec->evlist, 1390c45c86ebSWang Nan process_synthesized_event); 1391c45c86ebSWang Nan if (err < 0) { 1392c45c86ebSWang Nan pr_err("Couldn't synthesize attrs.\n"); 1393c45c86ebSWang Nan goto out; 1394c45c86ebSWang Nan } 1395c45c86ebSWang Nan 1396a2015516SJiri Olsa err = perf_event__synthesize_features(tool, session, rec->evlist, 1397a2015516SJiri Olsa process_synthesized_event); 1398a2015516SJiri Olsa if (err < 0) { 1399a2015516SJiri Olsa pr_err("Couldn't synthesize features.\n"); 1400a2015516SJiri Olsa return err; 1401a2015516SJiri Olsa } 1402a2015516SJiri Olsa 1403ce9036a6SJiri Olsa if (have_tracepoints(&rec->evlist->core.entries)) { 1404c45c86ebSWang Nan /* 1405c45c86ebSWang Nan * FIXME err <= 0 here actually means that 1406c45c86ebSWang Nan * there were no tracepoints so its not really 1407c45c86ebSWang Nan * an error, just that we don't need to 1408c45c86ebSWang Nan * synthesize anything. We really have to 1409c45c86ebSWang Nan * return this more properly and also 1410c45c86ebSWang Nan * propagate errors that now are calling die() 1411c45c86ebSWang Nan */ 1412c45c86ebSWang Nan err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist, 1413c45c86ebSWang Nan process_synthesized_event); 1414c45c86ebSWang Nan if (err <= 0) { 1415c45c86ebSWang Nan pr_err("Couldn't record tracing data.\n"); 1416c45c86ebSWang Nan goto out; 1417c45c86ebSWang Nan } 1418c45c86ebSWang Nan rec->bytes_written += err; 1419c45c86ebSWang Nan } 1420c45c86ebSWang Nan } 1421c45c86ebSWang Nan 1422c45628b0SWang Nan err = perf_event__synth_time_conv(record__pick_pc(rec), tool, 142346bc29b9SAdrian Hunter process_synthesized_event, machine); 142446bc29b9SAdrian Hunter if (err) 142546bc29b9SAdrian Hunter goto out; 142646bc29b9SAdrian Hunter 1427c0a6de06SAdrian Hunter /* Synthesize id_index before auxtrace_info */ 1428c0a6de06SAdrian Hunter if (rec->opts.auxtrace_sample_mode) { 1429c0a6de06SAdrian Hunter err = perf_event__synthesize_id_index(tool, 1430c0a6de06SAdrian Hunter process_synthesized_event, 1431c0a6de06SAdrian Hunter session->evlist, machine); 1432c0a6de06SAdrian Hunter if (err) 1433c0a6de06SAdrian Hunter goto out; 1434c0a6de06SAdrian Hunter } 1435c0a6de06SAdrian Hunter 1436c45c86ebSWang Nan if (rec->opts.full_auxtrace) { 1437c45c86ebSWang Nan err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 1438c45c86ebSWang Nan session, process_synthesized_event); 1439c45c86ebSWang Nan if (err) 1440c45c86ebSWang Nan goto out; 1441c45c86ebSWang Nan } 1442c45c86ebSWang Nan 14436c443954SArnaldo Carvalho de Melo if (!perf_evlist__exclude_kernel(rec->evlist)) { 1444c45c86ebSWang Nan err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event, 1445c45c86ebSWang Nan machine); 1446c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n" 1447c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1448c45c86ebSWang Nan "Check /proc/kallsyms permission or run as root.\n"); 1449c45c86ebSWang Nan 1450c45c86ebSWang Nan err = perf_event__synthesize_modules(tool, process_synthesized_event, 1451c45c86ebSWang Nan machine); 1452c45c86ebSWang Nan WARN_ONCE(err < 0, "Couldn't record kernel module information.\n" 1453c45c86ebSWang Nan "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 1454c45c86ebSWang Nan "Check /proc/modules permission or run as root.\n"); 14556c443954SArnaldo Carvalho de Melo } 1456c45c86ebSWang Nan 1457c45c86ebSWang Nan if (perf_guest) { 1458c45c86ebSWang Nan machines__process_guests(&session->machines, 1459c45c86ebSWang Nan perf_event__synthesize_guest_os, tool); 1460c45c86ebSWang Nan } 1461c45c86ebSWang Nan 1462bfd8f72cSAndi Kleen err = perf_event__synthesize_extra_attr(&rec->tool, 1463bfd8f72cSAndi Kleen rec->evlist, 1464bfd8f72cSAndi Kleen process_synthesized_event, 1465bfd8f72cSAndi Kleen data->is_pipe); 1466bfd8f72cSAndi Kleen if (err) 1467bfd8f72cSAndi Kleen goto out; 1468bfd8f72cSAndi Kleen 146903617c22SJiri Olsa err = perf_event__synthesize_thread_map2(&rec->tool, rec->evlist->core.threads, 1470373565d2SAndi Kleen process_synthesized_event, 1471373565d2SAndi Kleen NULL); 1472373565d2SAndi Kleen if (err < 0) { 1473373565d2SAndi Kleen pr_err("Couldn't synthesize thread map.\n"); 1474373565d2SAndi Kleen return err; 1475373565d2SAndi Kleen } 1476373565d2SAndi Kleen 1477f72f901dSJiri Olsa err = perf_event__synthesize_cpu_map(&rec->tool, rec->evlist->core.cpus, 1478373565d2SAndi Kleen process_synthesized_event, NULL); 1479373565d2SAndi Kleen if (err < 0) { 1480373565d2SAndi Kleen pr_err("Couldn't synthesize cpu map.\n"); 1481373565d2SAndi Kleen return err; 1482373565d2SAndi Kleen } 1483373565d2SAndi Kleen 1484e5416950SSong Liu err = perf_event__synthesize_bpf_events(session, process_synthesized_event, 14857b612e29SSong Liu machine, opts); 14867b612e29SSong Liu if (err < 0) 14877b612e29SSong Liu pr_warning("Couldn't synthesize bpf events.\n"); 14887b612e29SSong Liu 1489ab64069fSNamhyung Kim err = perf_event__synthesize_cgroups(tool, process_synthesized_event, 1490ab64069fSNamhyung Kim machine); 1491ab64069fSNamhyung Kim if (err < 0) 1492ab64069fSNamhyung Kim pr_warning("Couldn't synthesize cgroup events.\n"); 1493ab64069fSNamhyung Kim 1494d99c22eaSStephane Eranian if (rec->opts.nr_threads_synthesize > 1) { 1495d99c22eaSStephane Eranian perf_set_multithreaded(); 1496d99c22eaSStephane Eranian f = process_locked_synthesized_event; 1497d99c22eaSStephane Eranian } 1498d99c22eaSStephane Eranian 149903617c22SJiri Olsa err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->core.threads, 1500d99c22eaSStephane Eranian f, opts->sample_address, 1501d99c22eaSStephane Eranian rec->opts.nr_threads_synthesize); 1502d99c22eaSStephane Eranian 1503d99c22eaSStephane Eranian if (rec->opts.nr_threads_synthesize > 1) 1504d99c22eaSStephane Eranian perf_set_singlethreaded(); 1505d99c22eaSStephane Eranian 1506c45c86ebSWang Nan out: 1507c45c86ebSWang Nan return err; 1508c45c86ebSWang Nan } 1509c45c86ebSWang Nan 1510899e5ffbSArnaldo Carvalho de Melo static int record__process_signal_event(union perf_event *event __maybe_unused, void *data) 1511899e5ffbSArnaldo Carvalho de Melo { 1512899e5ffbSArnaldo Carvalho de Melo struct record *rec = data; 1513899e5ffbSArnaldo Carvalho de Melo pthread_kill(rec->thread_id, SIGUSR2); 1514899e5ffbSArnaldo Carvalho de Melo return 0; 1515899e5ffbSArnaldo Carvalho de Melo } 1516899e5ffbSArnaldo Carvalho de Melo 151723cbb41cSArnaldo Carvalho de Melo static int record__setup_sb_evlist(struct record *rec) 151823cbb41cSArnaldo Carvalho de Melo { 151923cbb41cSArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 152023cbb41cSArnaldo Carvalho de Melo 152123cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist != NULL) { 152223cbb41cSArnaldo Carvalho de Melo /* 152323cbb41cSArnaldo Carvalho de Melo * We get here if --switch-output-event populated the 152423cbb41cSArnaldo Carvalho de Melo * sb_evlist, so associate a callback that will send a SIGUSR2 152523cbb41cSArnaldo Carvalho de Melo * to the main thread. 152623cbb41cSArnaldo Carvalho de Melo */ 152723cbb41cSArnaldo Carvalho de Melo evlist__set_cb(rec->sb_evlist, record__process_signal_event, rec); 152823cbb41cSArnaldo Carvalho de Melo rec->thread_id = pthread_self(); 152923cbb41cSArnaldo Carvalho de Melo } 153023cbb41cSArnaldo Carvalho de Melo 153123cbb41cSArnaldo Carvalho de Melo if (!opts->no_bpf_event) { 153223cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist == NULL) { 153323cbb41cSArnaldo Carvalho de Melo rec->sb_evlist = evlist__new(); 153423cbb41cSArnaldo Carvalho de Melo 153523cbb41cSArnaldo Carvalho de Melo if (rec->sb_evlist == NULL) { 153623cbb41cSArnaldo Carvalho de Melo pr_err("Couldn't create side band evlist.\n."); 153723cbb41cSArnaldo Carvalho de Melo return -1; 153823cbb41cSArnaldo Carvalho de Melo } 153923cbb41cSArnaldo Carvalho de Melo } 154023cbb41cSArnaldo Carvalho de Melo 154123cbb41cSArnaldo Carvalho de Melo if (evlist__add_bpf_sb_event(rec->sb_evlist, &rec->session->header.env)) { 154223cbb41cSArnaldo Carvalho de Melo pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n."); 154323cbb41cSArnaldo Carvalho de Melo return -1; 154423cbb41cSArnaldo Carvalho de Melo } 154523cbb41cSArnaldo Carvalho de Melo } 154623cbb41cSArnaldo Carvalho de Melo 154723cbb41cSArnaldo Carvalho de Melo if (perf_evlist__start_sb_thread(rec->sb_evlist, &rec->opts.target)) { 154823cbb41cSArnaldo Carvalho de Melo pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); 154923cbb41cSArnaldo Carvalho de Melo opts->no_bpf_event = true; 155023cbb41cSArnaldo Carvalho de Melo } 155123cbb41cSArnaldo Carvalho de Melo 155223cbb41cSArnaldo Carvalho de Melo return 0; 155323cbb41cSArnaldo Carvalho de Melo } 155423cbb41cSArnaldo Carvalho de Melo 15558c6f45a7SArnaldo Carvalho de Melo static int __cmd_record(struct record *rec, int argc, const char **argv) 155686470930SIngo Molnar { 155757706abcSDavid Ahern int err; 155845604710SNamhyung Kim int status = 0; 15598b412664SPeter Zijlstra unsigned long waking = 0; 156046be604bSZhang, Yanmin const bool forks = argc > 0; 156145694aa7SArnaldo Carvalho de Melo struct perf_tool *tool = &rec->tool; 1562b4006796SArnaldo Carvalho de Melo struct record_opts *opts = &rec->opts; 15638ceb41d7SJiri Olsa struct perf_data *data = &rec->data; 1564d20deb64SArnaldo Carvalho de Melo struct perf_session *session; 15656dcf45efSArnaldo Carvalho de Melo bool disabled = false, draining = false; 156642aa276fSNamhyung Kim int fd; 1567d3c8c08eSAlexey Budankov float ratio = 0; 1568acce0223SAlexey Budankov enum evlist_ctl_cmd cmd = EVLIST_CTL_CMD_UNSUPPORTED; 156986470930SIngo Molnar 157045604710SNamhyung Kim atexit(record__sig_exit); 1571f5970550SPeter Zijlstra signal(SIGCHLD, sig_handler); 1572f5970550SPeter Zijlstra signal(SIGINT, sig_handler); 1573804f7ac7SDavid Ahern signal(SIGTERM, sig_handler); 1574a074865eSWang Nan signal(SIGSEGV, sigsegv_handler); 1575c0bdc1c4SWang Nan 1576f3b3614aSHari Bathini if (rec->opts.record_namespaces) 1577f3b3614aSHari Bathini tool->namespace_events = true; 1578f3b3614aSHari Bathini 15798fb4b679SNamhyung Kim if (rec->opts.record_cgroup) { 15808fb4b679SNamhyung Kim #ifdef HAVE_FILE_HANDLE 15818fb4b679SNamhyung Kim tool->cgroup_events = true; 15828fb4b679SNamhyung Kim #else 15838fb4b679SNamhyung Kim pr_err("cgroup tracking is not supported\n"); 15848fb4b679SNamhyung Kim return -1; 15858fb4b679SNamhyung Kim #endif 15868fb4b679SNamhyung Kim } 15878fb4b679SNamhyung Kim 1588dc0c6127SJiri Olsa if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) { 15892dd6d8a1SAdrian Hunter signal(SIGUSR2, snapshot_sig_handler); 15903c1cb7e3SWang Nan if (rec->opts.auxtrace_snapshot_mode) 15915f9cf599SWang Nan trigger_on(&auxtrace_snapshot_trigger); 1592dc0c6127SJiri Olsa if (rec->switch_output.enabled) 15933c1cb7e3SWang Nan trigger_on(&switch_output_trigger); 1594c0bdc1c4SWang Nan } else { 15952dd6d8a1SAdrian Hunter signal(SIGUSR2, SIG_IGN); 1596c0bdc1c4SWang Nan } 1597f5970550SPeter Zijlstra 15988ceb41d7SJiri Olsa session = perf_session__new(data, false, tool); 15996ef81c55SMamatha Inamdar if (IS_ERR(session)) { 1600ffa91880SAdrien BAK pr_err("Perf session creation failed.\n"); 16016ef81c55SMamatha Inamdar return PTR_ERR(session); 1602a9a70bbcSArnaldo Carvalho de Melo } 1603a9a70bbcSArnaldo Carvalho de Melo 16048ceb41d7SJiri Olsa fd = perf_data__fd(data); 1605d20deb64SArnaldo Carvalho de Melo rec->session = session; 1606d20deb64SArnaldo Carvalho de Melo 16075d7f4116SAlexey Budankov if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) { 16085d7f4116SAlexey Budankov pr_err("Compression initialization failed.\n"); 16095d7f4116SAlexey Budankov return -1; 16105d7f4116SAlexey Budankov } 1611da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 1612da231338SAnand K Mistry done_fd = eventfd(0, EFD_NONBLOCK); 1613da231338SAnand K Mistry if (done_fd < 0) { 1614da231338SAnand K Mistry pr_err("Failed to create wakeup eventfd, error: %m\n"); 1615da231338SAnand K Mistry status = -1; 1616da231338SAnand K Mistry goto out_delete_session; 1617da231338SAnand K Mistry } 1618da231338SAnand K Mistry err = evlist__add_pollfd(rec->evlist, done_fd); 1619da231338SAnand K Mistry if (err < 0) { 1620da231338SAnand K Mistry pr_err("Failed to add wakeup eventfd to poll list\n"); 1621da231338SAnand K Mistry status = err; 1622da231338SAnand K Mistry goto out_delete_session; 1623da231338SAnand K Mistry } 1624da231338SAnand K Mistry #endif // HAVE_EVENTFD_SUPPORT 16255d7f4116SAlexey Budankov 16265d7f4116SAlexey Budankov session->header.env.comp_type = PERF_COMP_ZSTD; 16275d7f4116SAlexey Budankov session->header.env.comp_level = rec->opts.comp_level; 16285d7f4116SAlexey Budankov 1629eeb399b5SAdrian Hunter if (rec->opts.kcore && 1630eeb399b5SAdrian Hunter !record__kcore_readable(&session->machines.host)) { 1631eeb399b5SAdrian Hunter pr_err("ERROR: kcore is not readable.\n"); 1632eeb399b5SAdrian Hunter return -1; 1633eeb399b5SAdrian Hunter } 1634eeb399b5SAdrian Hunter 16358c6f45a7SArnaldo Carvalho de Melo record__init_features(rec); 1636330aa675SStephane Eranian 1637cf790516SAlexey Budankov if (rec->opts.use_clockid && rec->opts.clockid_res_ns) 1638cf790516SAlexey Budankov session->header.env.clockid_res_ns = rec->opts.clockid_res_ns; 1639cf790516SAlexey Budankov 1640d4db3f16SArnaldo Carvalho de Melo if (forks) { 16413e2be2daSArnaldo Carvalho de Melo err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 16428ceb41d7SJiri Olsa argv, data->is_pipe, 1643735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal); 164435b9d88eSArnaldo Carvalho de Melo if (err < 0) { 164535b9d88eSArnaldo Carvalho de Melo pr_err("Couldn't run the workload!\n"); 164645604710SNamhyung Kim status = err; 164735b9d88eSArnaldo Carvalho de Melo goto out_delete_session; 1648856e9660SPeter Zijlstra } 1649856e9660SPeter Zijlstra } 1650856e9660SPeter Zijlstra 1651ad46e48cSJiri Olsa /* 1652ad46e48cSJiri Olsa * If we have just single event and are sending data 1653ad46e48cSJiri Olsa * through pipe, we need to force the ids allocation, 1654ad46e48cSJiri Olsa * because we synthesize event name through the pipe 1655ad46e48cSJiri Olsa * and need the id for that. 1656ad46e48cSJiri Olsa */ 16576484d2f9SJiri Olsa if (data->is_pipe && rec->evlist->core.nr_entries == 1) 1658ad46e48cSJiri Olsa rec->opts.sample_id = true; 1659ad46e48cSJiri Olsa 16608c6f45a7SArnaldo Carvalho de Melo if (record__open(rec) != 0) { 16618d3eca20SDavid Ahern err = -1; 166245604710SNamhyung Kim goto out_child; 16638d3eca20SDavid Ahern } 1664f6fa4375SJiri Olsa session->header.env.comp_mmap_len = session->evlist->core.mmap_len; 166586470930SIngo Molnar 1666eeb399b5SAdrian Hunter if (rec->opts.kcore) { 1667eeb399b5SAdrian Hunter err = record__kcore_copy(&session->machines.host, data); 1668eeb399b5SAdrian Hunter if (err) { 1669eeb399b5SAdrian Hunter pr_err("ERROR: Failed to copy kcore\n"); 1670eeb399b5SAdrian Hunter goto out_child; 1671eeb399b5SAdrian Hunter } 1672eeb399b5SAdrian Hunter } 1673eeb399b5SAdrian Hunter 16748690a2a7SWang Nan err = bpf__apply_obj_config(); 16758690a2a7SWang Nan if (err) { 16768690a2a7SWang Nan char errbuf[BUFSIZ]; 16778690a2a7SWang Nan 16788690a2a7SWang Nan bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf)); 16798690a2a7SWang Nan pr_err("ERROR: Apply config to BPF failed: %s\n", 16808690a2a7SWang Nan errbuf); 16818690a2a7SWang Nan goto out_child; 16828690a2a7SWang Nan } 16838690a2a7SWang Nan 1684cca8482cSAdrian Hunter /* 1685cca8482cSAdrian Hunter * Normally perf_session__new would do this, but it doesn't have the 1686cca8482cSAdrian Hunter * evlist. 1687cca8482cSAdrian Hunter */ 16888cedf3a5SArnaldo Carvalho de Melo if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) { 1689cca8482cSAdrian Hunter pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); 1690cca8482cSAdrian Hunter rec->tool.ordered_events = false; 1691cca8482cSAdrian Hunter } 1692cca8482cSAdrian Hunter 16933e2be2daSArnaldo Carvalho de Melo if (!rec->evlist->nr_groups) 1694a8bb559bSNamhyung Kim perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 1695a8bb559bSNamhyung Kim 16968ceb41d7SJiri Olsa if (data->is_pipe) { 169742aa276fSNamhyung Kim err = perf_header__write_pipe(fd); 1698529870e3STom Zanussi if (err < 0) 169945604710SNamhyung Kim goto out_child; 1700563aecb2SJiri Olsa } else { 170142aa276fSNamhyung Kim err = perf_session__write_header(session, rec->evlist, fd, false); 1702d5eed904SArnaldo Carvalho de Melo if (err < 0) 170345604710SNamhyung Kim goto out_child; 1704d5eed904SArnaldo Carvalho de Melo } 17057c6a1c65SPeter Zijlstra 1706b38d85efSArnaldo Carvalho de Melo err = -1; 1707d3665498SDavid Ahern if (!rec->no_buildid 1708e20960c0SRobert Richter && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 1709d3665498SDavid Ahern pr_err("Couldn't generate buildids. " 1710e20960c0SRobert Richter "Use --no-buildid to profile anyway.\n"); 171145604710SNamhyung Kim goto out_child; 1712e20960c0SRobert Richter } 1713e20960c0SRobert Richter 171423cbb41cSArnaldo Carvalho de Melo err = record__setup_sb_evlist(rec); 171523cbb41cSArnaldo Carvalho de Melo if (err) 1716b38d85efSArnaldo Carvalho de Melo goto out_child; 1717657ee553SSong Liu 17184ea648aeSWang Nan err = record__synthesize(rec, false); 1719c45c86ebSWang Nan if (err < 0) 172045604710SNamhyung Kim goto out_child; 17218d3eca20SDavid Ahern 1722d20deb64SArnaldo Carvalho de Melo if (rec->realtime_prio) { 172386470930SIngo Molnar struct sched_param param; 172486470930SIngo Molnar 1725d20deb64SArnaldo Carvalho de Melo param.sched_priority = rec->realtime_prio; 172686470930SIngo Molnar if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 17276beba7adSArnaldo Carvalho de Melo pr_err("Could not set realtime priority.\n"); 17288d3eca20SDavid Ahern err = -1; 172945604710SNamhyung Kim goto out_child; 173086470930SIngo Molnar } 173186470930SIngo Molnar } 173286470930SIngo Molnar 1733774cb499SJiri Olsa /* 1734774cb499SJiri Olsa * When perf is starting the traced process, all the events 1735774cb499SJiri Olsa * (apart from group members) have enable_on_exec=1 set, 1736774cb499SJiri Olsa * so don't spoil it by prematurely enabling them. 1737774cb499SJiri Olsa */ 17386619a53eSAndi Kleen if (!target__none(&opts->target) && !opts->initial_delay) 17391c87f165SJiri Olsa evlist__enable(rec->evlist); 1740764e16a3SDavid Ahern 1741856e9660SPeter Zijlstra /* 1742856e9660SPeter Zijlstra * Let the child rip 1743856e9660SPeter Zijlstra */ 1744e803cf97SNamhyung Kim if (forks) { 174520a8a3cfSJiri Olsa struct machine *machine = &session->machines.host; 1746e5bed564SNamhyung Kim union perf_event *event; 1747e907caf3SHari Bathini pid_t tgid; 1748e5bed564SNamhyung Kim 1749e5bed564SNamhyung Kim event = malloc(sizeof(event->comm) + machine->id_hdr_size); 1750e5bed564SNamhyung Kim if (event == NULL) { 1751e5bed564SNamhyung Kim err = -ENOMEM; 1752e5bed564SNamhyung Kim goto out_child; 1753e5bed564SNamhyung Kim } 1754e5bed564SNamhyung Kim 1755e803cf97SNamhyung Kim /* 1756e803cf97SNamhyung Kim * Some H/W events are generated before COMM event 1757e803cf97SNamhyung Kim * which is emitted during exec(), so perf script 1758e803cf97SNamhyung Kim * cannot see a correct process name for those events. 1759e803cf97SNamhyung Kim * Synthesize COMM event to prevent it. 1760e803cf97SNamhyung Kim */ 1761e907caf3SHari Bathini tgid = perf_event__synthesize_comm(tool, event, 1762e803cf97SNamhyung Kim rec->evlist->workload.pid, 1763e803cf97SNamhyung Kim process_synthesized_event, 1764e803cf97SNamhyung Kim machine); 1765e5bed564SNamhyung Kim free(event); 1766e803cf97SNamhyung Kim 1767e907caf3SHari Bathini if (tgid == -1) 1768e907caf3SHari Bathini goto out_child; 1769e907caf3SHari Bathini 1770e907caf3SHari Bathini event = malloc(sizeof(event->namespaces) + 1771e907caf3SHari Bathini (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) + 1772e907caf3SHari Bathini machine->id_hdr_size); 1773e907caf3SHari Bathini if (event == NULL) { 1774e907caf3SHari Bathini err = -ENOMEM; 1775e907caf3SHari Bathini goto out_child; 1776e907caf3SHari Bathini } 1777e907caf3SHari Bathini 1778e907caf3SHari Bathini /* 1779e907caf3SHari Bathini * Synthesize NAMESPACES event for the command specified. 1780e907caf3SHari Bathini */ 1781e907caf3SHari Bathini perf_event__synthesize_namespaces(tool, event, 1782e907caf3SHari Bathini rec->evlist->workload.pid, 1783e907caf3SHari Bathini tgid, process_synthesized_event, 1784e907caf3SHari Bathini machine); 1785e907caf3SHari Bathini free(event); 1786e907caf3SHari Bathini 17873e2be2daSArnaldo Carvalho de Melo perf_evlist__start_workload(rec->evlist); 1788e803cf97SNamhyung Kim } 1789856e9660SPeter Zijlstra 17901d078ccbSAlexey Budankov if (evlist__initialize_ctlfd(rec->evlist, opts->ctl_fd, opts->ctl_fd_ack)) 17911d078ccbSAlexey Budankov goto out_child; 17921d078ccbSAlexey Budankov 17936619a53eSAndi Kleen if (opts->initial_delay) { 179468cd3b45SAlexey Budankov pr_info(EVLIST_DISABLED_MSG); 179568cd3b45SAlexey Budankov if (opts->initial_delay > 0) { 17960693e680SArnaldo Carvalho de Melo usleep(opts->initial_delay * USEC_PER_MSEC); 17971c87f165SJiri Olsa evlist__enable(rec->evlist); 179868cd3b45SAlexey Budankov pr_info(EVLIST_ENABLED_MSG); 179968cd3b45SAlexey Budankov } 18006619a53eSAndi Kleen } 18016619a53eSAndi Kleen 18025f9cf599SWang Nan trigger_ready(&auxtrace_snapshot_trigger); 18033c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 1804a074865eSWang Nan perf_hooks__invoke_record_start(); 1805649c48a9SPeter Zijlstra for (;;) { 18069f065194SYang Shi unsigned long long hits = rec->samples; 180786470930SIngo Molnar 180805737464SWang Nan /* 180905737464SWang Nan * rec->evlist->bkw_mmap_state is possible to be 181005737464SWang Nan * BKW_MMAP_EMPTY here: when done == true and 181105737464SWang Nan * hits != rec->samples in previous round. 181205737464SWang Nan * 181305737464SWang Nan * perf_evlist__toggle_bkw_mmap ensure we never 181405737464SWang Nan * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. 181505737464SWang Nan */ 181605737464SWang Nan if (trigger_is_hit(&switch_output_trigger) || done || draining) 181705737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); 181805737464SWang Nan 1819470530bbSAlexey Budankov if (record__mmap_read_all(rec, false) < 0) { 18205f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 18213c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 18228d3eca20SDavid Ahern err = -1; 182345604710SNamhyung Kim goto out_child; 18248d3eca20SDavid Ahern } 182586470930SIngo Molnar 18262dd6d8a1SAdrian Hunter if (auxtrace_record__snapshot_started) { 18272dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 0; 18285f9cf599SWang Nan if (!trigger_is_error(&auxtrace_snapshot_trigger)) 1829ce7b0e42SAlexander Shishkin record__read_auxtrace_snapshot(rec, false); 18305f9cf599SWang Nan if (trigger_is_error(&auxtrace_snapshot_trigger)) { 18312dd6d8a1SAdrian Hunter pr_err("AUX area tracing snapshot failed\n"); 18322dd6d8a1SAdrian Hunter err = -1; 18332dd6d8a1SAdrian Hunter goto out_child; 18342dd6d8a1SAdrian Hunter } 18352dd6d8a1SAdrian Hunter } 18362dd6d8a1SAdrian Hunter 18373c1cb7e3SWang Nan if (trigger_is_hit(&switch_output_trigger)) { 183805737464SWang Nan /* 183905737464SWang Nan * If switch_output_trigger is hit, the data in 184005737464SWang Nan * overwritable ring buffer should have been collected, 184105737464SWang Nan * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. 184205737464SWang Nan * 184305737464SWang Nan * If SIGUSR2 raise after or during record__mmap_read_all(), 184405737464SWang Nan * record__mmap_read_all() didn't collect data from 184505737464SWang Nan * overwritable ring buffer. Read again. 184605737464SWang Nan */ 184705737464SWang Nan if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) 184805737464SWang Nan continue; 18493c1cb7e3SWang Nan trigger_ready(&switch_output_trigger); 18503c1cb7e3SWang Nan 185105737464SWang Nan /* 185205737464SWang Nan * Reenable events in overwrite ring buffer after 185305737464SWang Nan * record__mmap_read_all(): we should have collected 185405737464SWang Nan * data from it. 185505737464SWang Nan */ 185605737464SWang Nan perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); 185705737464SWang Nan 18583c1cb7e3SWang Nan if (!quiet) 18593c1cb7e3SWang Nan fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 18603c1cb7e3SWang Nan waking); 18613c1cb7e3SWang Nan waking = 0; 18623c1cb7e3SWang Nan fd = record__switch_output(rec, false); 18633c1cb7e3SWang Nan if (fd < 0) { 18643c1cb7e3SWang Nan pr_err("Failed to switch to new file\n"); 18653c1cb7e3SWang Nan trigger_error(&switch_output_trigger); 18663c1cb7e3SWang Nan err = fd; 18673c1cb7e3SWang Nan goto out_child; 18683c1cb7e3SWang Nan } 1869bfacbe3bSJiri Olsa 1870bfacbe3bSJiri Olsa /* re-arm the alarm */ 1871bfacbe3bSJiri Olsa if (rec->switch_output.time) 1872bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 18733c1cb7e3SWang Nan } 18743c1cb7e3SWang Nan 1875d20deb64SArnaldo Carvalho de Melo if (hits == rec->samples) { 18766dcf45efSArnaldo Carvalho de Melo if (done || draining) 1877649c48a9SPeter Zijlstra break; 187880ab2987SJiri Olsa err = evlist__poll(rec->evlist, -1); 1879a515114fSJiri Olsa /* 1880a515114fSJiri Olsa * Propagate error, only if there's any. Ignore positive 1881a515114fSJiri Olsa * number of returned events and interrupt error. 1882a515114fSJiri Olsa */ 1883a515114fSJiri Olsa if (err > 0 || (err < 0 && errno == EINTR)) 188445604710SNamhyung Kim err = 0; 18858b412664SPeter Zijlstra waking++; 18866dcf45efSArnaldo Carvalho de Melo 1887f4009e7bSJiri Olsa if (evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0) 18886dcf45efSArnaldo Carvalho de Melo draining = true; 18898b412664SPeter Zijlstra } 18908b412664SPeter Zijlstra 1891acce0223SAlexey Budankov if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) { 1892acce0223SAlexey Budankov switch (cmd) { 1893acce0223SAlexey Budankov case EVLIST_CTL_CMD_ENABLE: 1894acce0223SAlexey Budankov pr_info(EVLIST_ENABLED_MSG); 1895acce0223SAlexey Budankov break; 1896acce0223SAlexey Budankov case EVLIST_CTL_CMD_DISABLE: 1897acce0223SAlexey Budankov pr_info(EVLIST_DISABLED_MSG); 1898acce0223SAlexey Budankov break; 1899acce0223SAlexey Budankov case EVLIST_CTL_CMD_ACK: 1900acce0223SAlexey Budankov case EVLIST_CTL_CMD_UNSUPPORTED: 1901acce0223SAlexey Budankov default: 1902acce0223SAlexey Budankov break; 1903acce0223SAlexey Budankov } 1904acce0223SAlexey Budankov } 1905acce0223SAlexey Budankov 1906774cb499SJiri Olsa /* 1907774cb499SJiri Olsa * When perf is starting the traced process, at the end events 1908774cb499SJiri Olsa * die with the process and we wait for that. Thus no need to 1909774cb499SJiri Olsa * disable events in this case. 1910774cb499SJiri Olsa */ 1911602ad878SArnaldo Carvalho de Melo if (done && !disabled && !target__none(&opts->target)) { 19125f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 1913e74676deSJiri Olsa evlist__disable(rec->evlist); 19142711926aSJiri Olsa disabled = true; 19152711926aSJiri Olsa } 19168b412664SPeter Zijlstra } 1917ce7b0e42SAlexander Shishkin 19185f9cf599SWang Nan trigger_off(&auxtrace_snapshot_trigger); 19193c1cb7e3SWang Nan trigger_off(&switch_output_trigger); 19208b412664SPeter Zijlstra 1921ce7b0e42SAlexander Shishkin if (opts->auxtrace_snapshot_on_exit) 1922ce7b0e42SAlexander Shishkin record__auxtrace_snapshot_exit(rec); 1923ce7b0e42SAlexander Shishkin 1924f33cbe72SArnaldo Carvalho de Melo if (forks && workload_exec_errno) { 192535550da3SMasami Hiramatsu char msg[STRERR_BUFSIZE]; 1926c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 1927f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 1928f33cbe72SArnaldo Carvalho de Melo err = -1; 192945604710SNamhyung Kim goto out_child; 1930f33cbe72SArnaldo Carvalho de Melo } 1931f33cbe72SArnaldo Carvalho de Melo 1932e3d59112SNamhyung Kim if (!quiet) 19338b412664SPeter Zijlstra fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 193486470930SIngo Molnar 19354ea648aeSWang Nan if (target__none(&rec->opts.target)) 19364ea648aeSWang Nan record__synthesize_workload(rec, true); 19374ea648aeSWang Nan 193845604710SNamhyung Kim out_child: 19391d078ccbSAlexey Budankov evlist__finalize_ctlfd(rec->evlist); 1940470530bbSAlexey Budankov record__mmap_read_all(rec, true); 1941d3d1af6fSAlexey Budankov record__aio_mmap_read_sync(rec); 1942d3d1af6fSAlexey Budankov 1943d3c8c08eSAlexey Budankov if (rec->session->bytes_transferred && rec->session->bytes_compressed) { 1944d3c8c08eSAlexey Budankov ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed; 1945d3c8c08eSAlexey Budankov session->header.env.comp_ratio = ratio + 0.5; 1946d3c8c08eSAlexey Budankov } 1947d3c8c08eSAlexey Budankov 194845604710SNamhyung Kim if (forks) { 194945604710SNamhyung Kim int exit_status; 195045604710SNamhyung Kim 195145604710SNamhyung Kim if (!child_finished) 195245604710SNamhyung Kim kill(rec->evlist->workload.pid, SIGTERM); 195345604710SNamhyung Kim 195445604710SNamhyung Kim wait(&exit_status); 195545604710SNamhyung Kim 195645604710SNamhyung Kim if (err < 0) 195745604710SNamhyung Kim status = err; 195845604710SNamhyung Kim else if (WIFEXITED(exit_status)) 195945604710SNamhyung Kim status = WEXITSTATUS(exit_status); 196045604710SNamhyung Kim else if (WIFSIGNALED(exit_status)) 196145604710SNamhyung Kim signr = WTERMSIG(exit_status); 196245604710SNamhyung Kim } else 196345604710SNamhyung Kim status = err; 196445604710SNamhyung Kim 19654ea648aeSWang Nan record__synthesize(rec, true); 1966e3d59112SNamhyung Kim /* this will be recalculated during process_buildids() */ 1967e3d59112SNamhyung Kim rec->samples = 0; 1968e3d59112SNamhyung Kim 1969ecfd7a9cSWang Nan if (!err) { 1970ecfd7a9cSWang Nan if (!rec->timestamp_filename) { 1971e1ab48baSWang Nan record__finish_output(rec); 1972ecfd7a9cSWang Nan } else { 1973ecfd7a9cSWang Nan fd = record__switch_output(rec, true); 1974ecfd7a9cSWang Nan if (fd < 0) { 1975ecfd7a9cSWang Nan status = fd; 1976ecfd7a9cSWang Nan goto out_delete_session; 1977ecfd7a9cSWang Nan } 1978ecfd7a9cSWang Nan } 1979ecfd7a9cSWang Nan } 198039d17dacSArnaldo Carvalho de Melo 1981a074865eSWang Nan perf_hooks__invoke_record_end(); 1982a074865eSWang Nan 1983e3d59112SNamhyung Kim if (!err && !quiet) { 1984e3d59112SNamhyung Kim char samples[128]; 1985ecfd7a9cSWang Nan const char *postfix = rec->timestamp_filename ? 1986ecfd7a9cSWang Nan ".<timestamp>" : ""; 1987e3d59112SNamhyung Kim 1988ef149c25SAdrian Hunter if (rec->samples && !rec->opts.full_auxtrace) 1989e3d59112SNamhyung Kim scnprintf(samples, sizeof(samples), 1990e3d59112SNamhyung Kim " (%" PRIu64 " samples)", rec->samples); 1991e3d59112SNamhyung Kim else 1992e3d59112SNamhyung Kim samples[0] = '\0'; 1993e3d59112SNamhyung Kim 1994d3c8c08eSAlexey Budankov fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s", 19958ceb41d7SJiri Olsa perf_data__size(data) / 1024.0 / 1024.0, 19962d4f2799SJiri Olsa data->path, postfix, samples); 1997d3c8c08eSAlexey Budankov if (ratio) { 1998d3c8c08eSAlexey Budankov fprintf(stderr, ", compressed (original %.3f MB, ratio is %.3f)", 1999d3c8c08eSAlexey Budankov rec->session->bytes_transferred / 1024.0 / 1024.0, 2000d3c8c08eSAlexey Budankov ratio); 2001d3c8c08eSAlexey Budankov } 2002d3c8c08eSAlexey Budankov fprintf(stderr, " ]\n"); 2003e3d59112SNamhyung Kim } 2004e3d59112SNamhyung Kim 200539d17dacSArnaldo Carvalho de Melo out_delete_session: 2006da231338SAnand K Mistry #ifdef HAVE_EVENTFD_SUPPORT 2007da231338SAnand K Mistry if (done_fd >= 0) 2008da231338SAnand K Mistry close(done_fd); 2009da231338SAnand K Mistry #endif 20105d7f4116SAlexey Budankov zstd_fini(&session->zstd_data); 201139d17dacSArnaldo Carvalho de Melo perf_session__delete(session); 2012657ee553SSong Liu 2013657ee553SSong Liu if (!opts->no_bpf_event) 2014bc477d79SArnaldo Carvalho de Melo perf_evlist__stop_sb_thread(rec->sb_evlist); 201545604710SNamhyung Kim return status; 201686470930SIngo Molnar } 201786470930SIngo Molnar 20180883e820SArnaldo Carvalho de Melo static void callchain_debug(struct callchain_param *callchain) 201909b0fd45SJiri Olsa { 2020aad2b21cSKan Liang static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 2021a601fdffSJiri Olsa 20220883e820SArnaldo Carvalho de Melo pr_debug("callchain: type %s\n", str[callchain->record_mode]); 202326d33022SJiri Olsa 20240883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 202509b0fd45SJiri Olsa pr_debug("callchain: stack dump size %d\n", 20260883e820SArnaldo Carvalho de Melo callchain->dump_size); 20270883e820SArnaldo Carvalho de Melo } 20280883e820SArnaldo Carvalho de Melo 20290883e820SArnaldo Carvalho de Melo int record_opts__parse_callchain(struct record_opts *record, 20300883e820SArnaldo Carvalho de Melo struct callchain_param *callchain, 20310883e820SArnaldo Carvalho de Melo const char *arg, bool unset) 20320883e820SArnaldo Carvalho de Melo { 20330883e820SArnaldo Carvalho de Melo int ret; 20340883e820SArnaldo Carvalho de Melo callchain->enabled = !unset; 20350883e820SArnaldo Carvalho de Melo 20360883e820SArnaldo Carvalho de Melo /* --no-call-graph */ 20370883e820SArnaldo Carvalho de Melo if (unset) { 20380883e820SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_NONE; 20390883e820SArnaldo Carvalho de Melo pr_debug("callchain: disabled\n"); 20400883e820SArnaldo Carvalho de Melo return 0; 20410883e820SArnaldo Carvalho de Melo } 20420883e820SArnaldo Carvalho de Melo 20430883e820SArnaldo Carvalho de Melo ret = parse_callchain_record_opt(arg, callchain); 20440883e820SArnaldo Carvalho de Melo if (!ret) { 20450883e820SArnaldo Carvalho de Melo /* Enable data address sampling for DWARF unwind. */ 20460883e820SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_DWARF) 20470883e820SArnaldo Carvalho de Melo record->sample_address = true; 20480883e820SArnaldo Carvalho de Melo callchain_debug(callchain); 20490883e820SArnaldo Carvalho de Melo } 20500883e820SArnaldo Carvalho de Melo 20510883e820SArnaldo Carvalho de Melo return ret; 205209b0fd45SJiri Olsa } 205309b0fd45SJiri Olsa 2054c421e80bSKan Liang int record_parse_callchain_opt(const struct option *opt, 205509b0fd45SJiri Olsa const char *arg, 205609b0fd45SJiri Olsa int unset) 205709b0fd45SJiri Olsa { 20580883e820SArnaldo Carvalho de Melo return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset); 205926d33022SJiri Olsa } 206026d33022SJiri Olsa 2061c421e80bSKan Liang int record_callchain_opt(const struct option *opt, 206209b0fd45SJiri Olsa const char *arg __maybe_unused, 206309b0fd45SJiri Olsa int unset __maybe_unused) 206409b0fd45SJiri Olsa { 20652ddd5c04SArnaldo Carvalho de Melo struct callchain_param *callchain = opt->value; 2066c421e80bSKan Liang 20672ddd5c04SArnaldo Carvalho de Melo callchain->enabled = true; 206809b0fd45SJiri Olsa 20692ddd5c04SArnaldo Carvalho de Melo if (callchain->record_mode == CALLCHAIN_NONE) 20702ddd5c04SArnaldo Carvalho de Melo callchain->record_mode = CALLCHAIN_FP; 2071eb853e80SJiri Olsa 20722ddd5c04SArnaldo Carvalho de Melo callchain_debug(callchain); 207309b0fd45SJiri Olsa return 0; 207409b0fd45SJiri Olsa } 207509b0fd45SJiri Olsa 2076eb853e80SJiri Olsa static int perf_record_config(const char *var, const char *value, void *cb) 2077eb853e80SJiri Olsa { 20787a29c087SNamhyung Kim struct record *rec = cb; 20797a29c087SNamhyung Kim 20807a29c087SNamhyung Kim if (!strcmp(var, "record.build-id")) { 20817a29c087SNamhyung Kim if (!strcmp(value, "cache")) 20827a29c087SNamhyung Kim rec->no_buildid_cache = false; 20837a29c087SNamhyung Kim else if (!strcmp(value, "no-cache")) 20847a29c087SNamhyung Kim rec->no_buildid_cache = true; 20857a29c087SNamhyung Kim else if (!strcmp(value, "skip")) 20867a29c087SNamhyung Kim rec->no_buildid = true; 20877a29c087SNamhyung Kim else 20887a29c087SNamhyung Kim return -1; 20897a29c087SNamhyung Kim return 0; 20907a29c087SNamhyung Kim } 2091cff17205SYisheng Xie if (!strcmp(var, "record.call-graph")) { 2092cff17205SYisheng Xie var = "call-graph.record-mode"; 2093eb853e80SJiri Olsa return perf_default_config(var, value, cb); 2094eb853e80SJiri Olsa } 209593f20c0fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 209693f20c0fSAlexey Budankov if (!strcmp(var, "record.aio")) { 209793f20c0fSAlexey Budankov rec->opts.nr_cblocks = strtol(value, NULL, 0); 209893f20c0fSAlexey Budankov if (!rec->opts.nr_cblocks) 209993f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_default; 210093f20c0fSAlexey Budankov } 210193f20c0fSAlexey Budankov #endif 2102eb853e80SJiri Olsa 2103cff17205SYisheng Xie return 0; 2104cff17205SYisheng Xie } 2105cff17205SYisheng Xie 2106814c8c38SPeter Zijlstra 2107f4fe11b7SAlexey Budankov static int record__parse_affinity(const struct option *opt, const char *str, int unset) 2108f4fe11b7SAlexey Budankov { 2109f4fe11b7SAlexey Budankov struct record_opts *opts = (struct record_opts *)opt->value; 2110f4fe11b7SAlexey Budankov 2111f4fe11b7SAlexey Budankov if (unset || !str) 2112f4fe11b7SAlexey Budankov return 0; 2113f4fe11b7SAlexey Budankov 2114f4fe11b7SAlexey Budankov if (!strcasecmp(str, "node")) 2115f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_NODE; 2116f4fe11b7SAlexey Budankov else if (!strcasecmp(str, "cpu")) 2117f4fe11b7SAlexey Budankov opts->affinity = PERF_AFFINITY_CPU; 2118f4fe11b7SAlexey Budankov 2119f4fe11b7SAlexey Budankov return 0; 2120f4fe11b7SAlexey Budankov } 2121f4fe11b7SAlexey Budankov 21226d575816SJiwei Sun static int parse_output_max_size(const struct option *opt, 21236d575816SJiwei Sun const char *str, int unset) 21246d575816SJiwei Sun { 21256d575816SJiwei Sun unsigned long *s = (unsigned long *)opt->value; 21266d575816SJiwei Sun static struct parse_tag tags_size[] = { 21276d575816SJiwei Sun { .tag = 'B', .mult = 1 }, 21286d575816SJiwei Sun { .tag = 'K', .mult = 1 << 10 }, 21296d575816SJiwei Sun { .tag = 'M', .mult = 1 << 20 }, 21306d575816SJiwei Sun { .tag = 'G', .mult = 1 << 30 }, 21316d575816SJiwei Sun { .tag = 0 }, 21326d575816SJiwei Sun }; 21336d575816SJiwei Sun unsigned long val; 21346d575816SJiwei Sun 21356d575816SJiwei Sun if (unset) { 21366d575816SJiwei Sun *s = 0; 21376d575816SJiwei Sun return 0; 21386d575816SJiwei Sun } 21396d575816SJiwei Sun 21406d575816SJiwei Sun val = parse_tag_value(str, tags_size); 21416d575816SJiwei Sun if (val != (unsigned long) -1) { 21426d575816SJiwei Sun *s = val; 21436d575816SJiwei Sun return 0; 21446d575816SJiwei Sun } 21456d575816SJiwei Sun 21466d575816SJiwei Sun return -1; 21476d575816SJiwei Sun } 21486d575816SJiwei Sun 2149e9db1310SAdrian Hunter static int record__parse_mmap_pages(const struct option *opt, 2150e9db1310SAdrian Hunter const char *str, 2151e9db1310SAdrian Hunter int unset __maybe_unused) 2152e9db1310SAdrian Hunter { 2153e9db1310SAdrian Hunter struct record_opts *opts = opt->value; 2154e9db1310SAdrian Hunter char *s, *p; 2155e9db1310SAdrian Hunter unsigned int mmap_pages; 2156e9db1310SAdrian Hunter int ret; 2157e9db1310SAdrian Hunter 2158e9db1310SAdrian Hunter if (!str) 2159e9db1310SAdrian Hunter return -EINVAL; 2160e9db1310SAdrian Hunter 2161e9db1310SAdrian Hunter s = strdup(str); 2162e9db1310SAdrian Hunter if (!s) 2163e9db1310SAdrian Hunter return -ENOMEM; 2164e9db1310SAdrian Hunter 2165e9db1310SAdrian Hunter p = strchr(s, ','); 2166e9db1310SAdrian Hunter if (p) 2167e9db1310SAdrian Hunter *p = '\0'; 2168e9db1310SAdrian Hunter 2169e9db1310SAdrian Hunter if (*s) { 2170e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, s); 2171e9db1310SAdrian Hunter if (ret) 2172e9db1310SAdrian Hunter goto out_free; 2173e9db1310SAdrian Hunter opts->mmap_pages = mmap_pages; 2174e9db1310SAdrian Hunter } 2175e9db1310SAdrian Hunter 2176e9db1310SAdrian Hunter if (!p) { 2177e9db1310SAdrian Hunter ret = 0; 2178e9db1310SAdrian Hunter goto out_free; 2179e9db1310SAdrian Hunter } 2180e9db1310SAdrian Hunter 2181e9db1310SAdrian Hunter ret = __perf_evlist__parse_mmap_pages(&mmap_pages, p + 1); 2182e9db1310SAdrian Hunter if (ret) 2183e9db1310SAdrian Hunter goto out_free; 2184e9db1310SAdrian Hunter 2185e9db1310SAdrian Hunter opts->auxtrace_mmap_pages = mmap_pages; 2186e9db1310SAdrian Hunter 2187e9db1310SAdrian Hunter out_free: 2188e9db1310SAdrian Hunter free(s); 2189e9db1310SAdrian Hunter return ret; 2190e9db1310SAdrian Hunter } 2191e9db1310SAdrian Hunter 21921d078ccbSAlexey Budankov static int parse_control_option(const struct option *opt, 21931d078ccbSAlexey Budankov const char *str, 21941d078ccbSAlexey Budankov int unset __maybe_unused) 21951d078ccbSAlexey Budankov { 21961d078ccbSAlexey Budankov char *comma = NULL, *endptr = NULL; 21971d078ccbSAlexey Budankov struct record_opts *config = (struct record_opts *)opt->value; 21981d078ccbSAlexey Budankov 21991d078ccbSAlexey Budankov if (strncmp(str, "fd:", 3)) 22001d078ccbSAlexey Budankov return -EINVAL; 22011d078ccbSAlexey Budankov 22021d078ccbSAlexey Budankov config->ctl_fd = strtoul(&str[3], &endptr, 0); 22031d078ccbSAlexey Budankov if (endptr == &str[3]) 22041d078ccbSAlexey Budankov return -EINVAL; 22051d078ccbSAlexey Budankov 22061d078ccbSAlexey Budankov comma = strchr(str, ','); 22071d078ccbSAlexey Budankov if (comma) { 22081d078ccbSAlexey Budankov if (endptr != comma) 22091d078ccbSAlexey Budankov return -EINVAL; 22101d078ccbSAlexey Budankov 22111d078ccbSAlexey Budankov config->ctl_fd_ack = strtoul(comma + 1, &endptr, 0); 22121d078ccbSAlexey Budankov if (endptr == comma + 1 || *endptr != '\0') 22131d078ccbSAlexey Budankov return -EINVAL; 22141d078ccbSAlexey Budankov } 22151d078ccbSAlexey Budankov 22161d078ccbSAlexey Budankov return 0; 22171d078ccbSAlexey Budankov } 22181d078ccbSAlexey Budankov 22190c582449SJiri Olsa static void switch_output_size_warn(struct record *rec) 22200c582449SJiri Olsa { 22219521b5f2SJiri Olsa u64 wakeup_size = evlist__mmap_size(rec->opts.mmap_pages); 22220c582449SJiri Olsa struct switch_output *s = &rec->switch_output; 22230c582449SJiri Olsa 22240c582449SJiri Olsa wakeup_size /= 2; 22250c582449SJiri Olsa 22260c582449SJiri Olsa if (s->size < wakeup_size) { 22270c582449SJiri Olsa char buf[100]; 22280c582449SJiri Olsa 22290c582449SJiri Olsa unit_number__scnprintf(buf, sizeof(buf), wakeup_size); 22300c582449SJiri Olsa pr_warning("WARNING: switch-output data size lower than " 22310c582449SJiri Olsa "wakeup kernel buffer size (%s) " 22320c582449SJiri Olsa "expect bigger perf.data sizes\n", buf); 22330c582449SJiri Olsa } 22340c582449SJiri Olsa } 22350c582449SJiri Olsa 2236cb4e1ebbSJiri Olsa static int switch_output_setup(struct record *rec) 2237cb4e1ebbSJiri Olsa { 2238cb4e1ebbSJiri Olsa struct switch_output *s = &rec->switch_output; 2239dc0c6127SJiri Olsa static struct parse_tag tags_size[] = { 2240dc0c6127SJiri Olsa { .tag = 'B', .mult = 1 }, 2241dc0c6127SJiri Olsa { .tag = 'K', .mult = 1 << 10 }, 2242dc0c6127SJiri Olsa { .tag = 'M', .mult = 1 << 20 }, 2243dc0c6127SJiri Olsa { .tag = 'G', .mult = 1 << 30 }, 2244dc0c6127SJiri Olsa { .tag = 0 }, 2245dc0c6127SJiri Olsa }; 2246bfacbe3bSJiri Olsa static struct parse_tag tags_time[] = { 2247bfacbe3bSJiri Olsa { .tag = 's', .mult = 1 }, 2248bfacbe3bSJiri Olsa { .tag = 'm', .mult = 60 }, 2249bfacbe3bSJiri Olsa { .tag = 'h', .mult = 60*60 }, 2250bfacbe3bSJiri Olsa { .tag = 'd', .mult = 60*60*24 }, 2251bfacbe3bSJiri Olsa { .tag = 0 }, 2252bfacbe3bSJiri Olsa }; 2253dc0c6127SJiri Olsa unsigned long val; 2254cb4e1ebbSJiri Olsa 2255899e5ffbSArnaldo Carvalho de Melo /* 2256899e5ffbSArnaldo Carvalho de Melo * If we're using --switch-output-events, then we imply its 2257899e5ffbSArnaldo Carvalho de Melo * --switch-output=signal, as we'll send a SIGUSR2 from the side band 2258899e5ffbSArnaldo Carvalho de Melo * thread to its parent. 2259899e5ffbSArnaldo Carvalho de Melo */ 2260899e5ffbSArnaldo Carvalho de Melo if (rec->switch_output_event_set) 2261899e5ffbSArnaldo Carvalho de Melo goto do_signal; 2262899e5ffbSArnaldo Carvalho de Melo 2263cb4e1ebbSJiri Olsa if (!s->set) 2264cb4e1ebbSJiri Olsa return 0; 2265cb4e1ebbSJiri Olsa 2266cb4e1ebbSJiri Olsa if (!strcmp(s->str, "signal")) { 2267899e5ffbSArnaldo Carvalho de Melo do_signal: 2268cb4e1ebbSJiri Olsa s->signal = true; 2269cb4e1ebbSJiri Olsa pr_debug("switch-output with SIGUSR2 signal\n"); 2270dc0c6127SJiri Olsa goto enabled; 2271dc0c6127SJiri Olsa } 2272dc0c6127SJiri Olsa 2273dc0c6127SJiri Olsa val = parse_tag_value(s->str, tags_size); 2274dc0c6127SJiri Olsa if (val != (unsigned long) -1) { 2275dc0c6127SJiri Olsa s->size = val; 2276dc0c6127SJiri Olsa pr_debug("switch-output with %s size threshold\n", s->str); 2277dc0c6127SJiri Olsa goto enabled; 2278cb4e1ebbSJiri Olsa } 2279cb4e1ebbSJiri Olsa 2280bfacbe3bSJiri Olsa val = parse_tag_value(s->str, tags_time); 2281bfacbe3bSJiri Olsa if (val != (unsigned long) -1) { 2282bfacbe3bSJiri Olsa s->time = val; 2283bfacbe3bSJiri Olsa pr_debug("switch-output with %s time threshold (%lu seconds)\n", 2284bfacbe3bSJiri Olsa s->str, s->time); 2285bfacbe3bSJiri Olsa goto enabled; 2286bfacbe3bSJiri Olsa } 2287bfacbe3bSJiri Olsa 2288cb4e1ebbSJiri Olsa return -1; 2289dc0c6127SJiri Olsa 2290dc0c6127SJiri Olsa enabled: 2291dc0c6127SJiri Olsa rec->timestamp_filename = true; 2292dc0c6127SJiri Olsa s->enabled = true; 22930c582449SJiri Olsa 22940c582449SJiri Olsa if (s->size && !rec->opts.no_buffering) 22950c582449SJiri Olsa switch_output_size_warn(rec); 22960c582449SJiri Olsa 2297dc0c6127SJiri Olsa return 0; 2298cb4e1ebbSJiri Olsa } 2299cb4e1ebbSJiri Olsa 2300e5b2c207SNamhyung Kim static const char * const __record_usage[] = { 230186470930SIngo Molnar "perf record [<options>] [<command>]", 230286470930SIngo Molnar "perf record [<options>] -- <command> [<options>]", 230386470930SIngo Molnar NULL 230486470930SIngo Molnar }; 2305e5b2c207SNamhyung Kim const char * const *record_usage = __record_usage; 230686470930SIngo Molnar 23076e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap(struct perf_tool *tool, union perf_event *event, 23086e0a9b3dSArnaldo Carvalho de Melo struct perf_sample *sample, struct machine *machine) 23096e0a9b3dSArnaldo Carvalho de Melo { 23106e0a9b3dSArnaldo Carvalho de Melo /* 23116e0a9b3dSArnaldo Carvalho de Melo * We already have the kernel maps, put in place via perf_session__create_kernel_maps() 23126e0a9b3dSArnaldo Carvalho de Melo * no need to add them twice. 23136e0a9b3dSArnaldo Carvalho de Melo */ 23146e0a9b3dSArnaldo Carvalho de Melo if (!(event->header.misc & PERF_RECORD_MISC_USER)) 23156e0a9b3dSArnaldo Carvalho de Melo return 0; 23166e0a9b3dSArnaldo Carvalho de Melo return perf_event__process_mmap(tool, event, sample, machine); 23176e0a9b3dSArnaldo Carvalho de Melo } 23186e0a9b3dSArnaldo Carvalho de Melo 23196e0a9b3dSArnaldo Carvalho de Melo static int build_id__process_mmap2(struct perf_tool *tool, union perf_event *event, 23206e0a9b3dSArnaldo Carvalho de Melo struct perf_sample *sample, struct machine *machine) 23216e0a9b3dSArnaldo Carvalho de Melo { 23226e0a9b3dSArnaldo Carvalho de Melo /* 23236e0a9b3dSArnaldo Carvalho de Melo * We already have the kernel maps, put in place via perf_session__create_kernel_maps() 23246e0a9b3dSArnaldo Carvalho de Melo * no need to add them twice. 23256e0a9b3dSArnaldo Carvalho de Melo */ 23266e0a9b3dSArnaldo Carvalho de Melo if (!(event->header.misc & PERF_RECORD_MISC_USER)) 23276e0a9b3dSArnaldo Carvalho de Melo return 0; 23286e0a9b3dSArnaldo Carvalho de Melo 23296e0a9b3dSArnaldo Carvalho de Melo return perf_event__process_mmap2(tool, event, sample, machine); 23306e0a9b3dSArnaldo Carvalho de Melo } 23316e0a9b3dSArnaldo Carvalho de Melo 2332d20deb64SArnaldo Carvalho de Melo /* 23338c6f45a7SArnaldo Carvalho de Melo * XXX Ideally would be local to cmd_record() and passed to a record__new 23348c6f45a7SArnaldo Carvalho de Melo * because we need to have access to it in record__exit, that is called 2335d20deb64SArnaldo Carvalho de Melo * after cmd_record() exits, but since record_options need to be accessible to 2336d20deb64SArnaldo Carvalho de Melo * builtin-script, leave it here. 2337d20deb64SArnaldo Carvalho de Melo * 2338d20deb64SArnaldo Carvalho de Melo * At least we don't ouch it in all the other functions here directly. 2339d20deb64SArnaldo Carvalho de Melo * 2340d20deb64SArnaldo Carvalho de Melo * Just say no to tons of global variables, sigh. 2341d20deb64SArnaldo Carvalho de Melo */ 23428c6f45a7SArnaldo Carvalho de Melo static struct record record = { 2343d20deb64SArnaldo Carvalho de Melo .opts = { 23448affc2b8SAndi Kleen .sample_time = true, 2345d20deb64SArnaldo Carvalho de Melo .mmap_pages = UINT_MAX, 2346d20deb64SArnaldo Carvalho de Melo .user_freq = UINT_MAX, 2347d20deb64SArnaldo Carvalho de Melo .user_interval = ULLONG_MAX, 2348447a6013SArnaldo Carvalho de Melo .freq = 4000, 2349d1cb9fceSNamhyung Kim .target = { 2350d1cb9fceSNamhyung Kim .uses_mmap = true, 23513aa5939dSAdrian Hunter .default_per_cpu = true, 2352d1cb9fceSNamhyung Kim }, 2353470530bbSAlexey Budankov .mmap_flush = MMAP_FLUSH_DEFAULT, 2354d99c22eaSStephane Eranian .nr_threads_synthesize = 1, 23551d078ccbSAlexey Budankov .ctl_fd = -1, 23561d078ccbSAlexey Budankov .ctl_fd_ack = -1, 2357d20deb64SArnaldo Carvalho de Melo }, 2358e3d59112SNamhyung Kim .tool = { 2359e3d59112SNamhyung Kim .sample = process_sample_event, 2360e3d59112SNamhyung Kim .fork = perf_event__process_fork, 2361cca8482cSAdrian Hunter .exit = perf_event__process_exit, 2362e3d59112SNamhyung Kim .comm = perf_event__process_comm, 2363f3b3614aSHari Bathini .namespaces = perf_event__process_namespaces, 23646e0a9b3dSArnaldo Carvalho de Melo .mmap = build_id__process_mmap, 23656e0a9b3dSArnaldo Carvalho de Melo .mmap2 = build_id__process_mmap2, 2366cca8482cSAdrian Hunter .ordered_events = true, 2367e3d59112SNamhyung Kim }, 2368d20deb64SArnaldo Carvalho de Melo }; 23697865e817SFrederic Weisbecker 237076a26549SNamhyung Kim const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 237176a26549SNamhyung Kim "\n\t\t\t\tDefault: fp"; 237261eaa3beSArnaldo Carvalho de Melo 23730aab2136SWang Nan static bool dry_run; 23740aab2136SWang Nan 2375d20deb64SArnaldo Carvalho de Melo /* 2376d20deb64SArnaldo Carvalho de Melo * XXX Will stay a global variable till we fix builtin-script.c to stop messing 2377d20deb64SArnaldo Carvalho de Melo * with it and switch to use the library functions in perf_evlist that came 2378b4006796SArnaldo Carvalho de Melo * from builtin-record.c, i.e. use record_opts, 2379d20deb64SArnaldo Carvalho de Melo * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 2380d20deb64SArnaldo Carvalho de Melo * using pipes, etc. 2381d20deb64SArnaldo Carvalho de Melo */ 2382efd21307SJiri Olsa static struct option __record_options[] = { 2383d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('e', "event", &record.evlist, "event", 238486470930SIngo Molnar "event selector. use 'perf list' to list available events", 2385f120f9d5SJiri Olsa parse_events_option), 2386d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK(0, "filter", &record.evlist, "filter", 2387c171b552SLi Zefan "event filter", parse_filter), 23884ba1faa1SWang Nan OPT_CALLBACK_NOOPT(0, "exclude-perf", &record.evlist, 23894ba1faa1SWang Nan NULL, "don't record events from perf itself", 23904ba1faa1SWang Nan exclude_perf), 2391bea03405SNamhyung Kim OPT_STRING('p', "pid", &record.opts.target.pid, "pid", 2392d6d901c2SZhang, Yanmin "record events on existing process id"), 2393bea03405SNamhyung Kim OPT_STRING('t', "tid", &record.opts.target.tid, "tid", 2394d6d901c2SZhang, Yanmin "record events on existing thread id"), 2395d20deb64SArnaldo Carvalho de Melo OPT_INTEGER('r', "realtime", &record.realtime_prio, 239686470930SIngo Molnar "collect data with this RT SCHED_FIFO priority"), 2397509051eaSArnaldo Carvalho de Melo OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering, 2398acac03faSKirill Smelkov "collect data without buffering"), 2399d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 2400daac07b2SFrederic Weisbecker "collect raw sample records from all opened counters"), 2401bea03405SNamhyung Kim OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, 240286470930SIngo Molnar "system-wide collection from all CPUs"), 2403bea03405SNamhyung Kim OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 2404c45c6ea2SStephane Eranian "list of cpus to monitor"), 2405d20deb64SArnaldo Carvalho de Melo OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 24062d4f2799SJiri Olsa OPT_STRING('o', "output", &record.data.path, "file", 240786470930SIngo Molnar "output file name"), 240869e7e5b0SAdrian Hunter OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 240969e7e5b0SAdrian Hunter &record.opts.no_inherit_set, 24102e6cdf99SStephane Eranian "child tasks do not inherit counters"), 24114ea648aeSWang Nan OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 24124ea648aeSWang Nan "synthesize non-sample events at the end of output"), 2413626a6b78SWang Nan OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 241471184c6aSSong Liu OPT_BOOLEAN(0, "no-bpf-event", &record.opts.no_bpf_event, "record bpf events"), 2415b09c2364SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq, 2416b09c2364SArnaldo Carvalho de Melo "Fail if the specified frequency can't be used"), 241767230479SArnaldo Carvalho de Melo OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'", 241867230479SArnaldo Carvalho de Melo "profile at this frequency", 241967230479SArnaldo Carvalho de Melo record__parse_freq), 2420e9db1310SAdrian Hunter OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 2421e9db1310SAdrian Hunter "number of mmap data pages and AUX area tracing mmap pages", 2422e9db1310SAdrian Hunter record__parse_mmap_pages), 2423470530bbSAlexey Budankov OPT_CALLBACK(0, "mmap-flush", &record.opts, "number", 2424470530bbSAlexey Budankov "Minimal number of bytes that is extracted from mmap data pages (default: 1)", 2425470530bbSAlexey Budankov record__mmap_flush_parse), 2426d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN(0, "group", &record.opts.group, 242743bece79SLin Ming "put the counters into a counter group"), 24282ddd5c04SArnaldo Carvalho de Melo OPT_CALLBACK_NOOPT('g', NULL, &callchain_param, 242909b0fd45SJiri Olsa NULL, "enables call-graph recording" , 243009b0fd45SJiri Olsa &record_callchain_opt), 243109b0fd45SJiri Olsa OPT_CALLBACK(0, "call-graph", &record.opts, 243276a26549SNamhyung Kim "record_mode[,record_size]", record_callchain_help, 243309b0fd45SJiri Olsa &record_parse_callchain_opt), 2434c0555642SIan Munsie OPT_INCR('v', "verbose", &verbose, 24353da297a6SIngo Molnar "be more verbose (show counter open errors, etc)"), 2436b44308f5SArnaldo Carvalho de Melo OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 2437d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 2438649c48a9SPeter Zijlstra "per thread counts"), 243956100321SPeter Zijlstra OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 24403b0a5daaSKan Liang OPT_BOOLEAN(0, "phys-data", &record.opts.sample_phys_addr, 24413b0a5daaSKan Liang "Record the sample physical addresses"), 2442b6f35ed7SJiri Olsa OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), 24433abebc55SAdrian Hunter OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 24443abebc55SAdrian Hunter &record.opts.sample_time_set, 24453abebc55SAdrian Hunter "Record the sample timestamps"), 2446f290aa1fSJiri Olsa OPT_BOOLEAN_SET('P', "period", &record.opts.period, &record.opts.period_set, 2447f290aa1fSJiri Olsa "Record the sample period"), 2448d20deb64SArnaldo Carvalho de Melo OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, 2449649c48a9SPeter Zijlstra "don't sample"), 2450d2db9a98SWang Nan OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, 2451d2db9a98SWang Nan &record.no_buildid_cache_set, 2452a1ac1d3cSStephane Eranian "do not update the buildid cache"), 2453d2db9a98SWang Nan OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, 2454d2db9a98SWang Nan &record.no_buildid_set, 2455baa2f6ceSArnaldo Carvalho de Melo "do not collect buildids in perf.data"), 2456d20deb64SArnaldo Carvalho de Melo OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 2457023695d9SStephane Eranian "monitor event in cgroup name only", 2458023695d9SStephane Eranian parse_cgroups), 245968cd3b45SAlexey Budankov OPT_INTEGER('D', "delay", &record.opts.initial_delay, 246068cd3b45SAlexey Budankov "ms to wait before starting measurement after program start (-1: start with events disabled)"), 2461eeb399b5SAdrian Hunter OPT_BOOLEAN(0, "kcore", &record.opts.kcore, "copy /proc/kcore"), 2462bea03405SNamhyung Kim OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 2463bea03405SNamhyung Kim "user to profile"), 2464a5aabdacSStephane Eranian 2465a5aabdacSStephane Eranian OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 2466a5aabdacSStephane Eranian "branch any", "sample any taken branches", 2467a5aabdacSStephane Eranian parse_branch_stack), 2468a5aabdacSStephane Eranian 2469a5aabdacSStephane Eranian OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, 2470a5aabdacSStephane Eranian "branch filter mask", "branch stack filter modes", 2471bdfebd84SRoberto Agostino Vitillo parse_branch_stack), 247205484298SAndi Kleen OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 247305484298SAndi Kleen "sample by weight (on special events only)"), 2474475eeab9SAndi Kleen OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 2475475eeab9SAndi Kleen "sample transaction flags (special events only)"), 24763aa5939dSAdrian Hunter OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 24773aa5939dSAdrian Hunter "use per-thread mmaps"), 2478bcc84ec6SStephane Eranian OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 2479bcc84ec6SStephane Eranian "sample selected machine registers on interrupt," 2480aeea9062SKan Liang " use '-I?' to list register names", parse_intr_regs), 248184c41742SAndi Kleen OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 248284c41742SAndi Kleen "sample selected machine registers on interrupt," 2483aeea9062SKan Liang " use '--user-regs=?' to list register names", parse_user_regs), 248485c273d2SAndi Kleen OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 248585c273d2SAndi Kleen "Record running/enabled time of read (:S) events"), 2486814c8c38SPeter Zijlstra OPT_CALLBACK('k', "clockid", &record.opts, 2487814c8c38SPeter Zijlstra "clockid", "clockid to use for events, see clock_gettime()", 2488814c8c38SPeter Zijlstra parse_clockid), 24892dd6d8a1SAdrian Hunter OPT_STRING_OPTARG('S', "snapshot", &record.opts.auxtrace_snapshot_opts, 24902dd6d8a1SAdrian Hunter "opts", "AUX area tracing Snapshot Mode", ""), 2491c0a6de06SAdrian Hunter OPT_STRING_OPTARG(0, "aux-sample", &record.opts.auxtrace_sample_opts, 2492c0a6de06SAdrian Hunter "opts", "sample AUX area", ""), 24933fcb10e4SMark Drayton OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout, 24949d9cad76SKan Liang "per thread proc mmap processing timeout in ms"), 2495f3b3614aSHari Bathini OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces, 2496f3b3614aSHari Bathini "Record namespaces events"), 24978fb4b679SNamhyung Kim OPT_BOOLEAN(0, "all-cgroups", &record.opts.record_cgroup, 24988fb4b679SNamhyung Kim "Record cgroup events"), 249916b4b4e1SAdrian Hunter OPT_BOOLEAN_SET(0, "switch-events", &record.opts.record_switch_events, 250016b4b4e1SAdrian Hunter &record.opts.record_switch_events_set, 2501b757bb09SAdrian Hunter "Record context switch events"), 250285723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel, 250385723885SJiri Olsa "Configure all used events to run in kernel space.", 250485723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 250585723885SJiri Olsa OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user, 250685723885SJiri Olsa "Configure all used events to run in user space.", 250785723885SJiri Olsa PARSE_OPT_EXCLUSIVE), 250853651b28Syuzhoujian OPT_BOOLEAN(0, "kernel-callchains", &record.opts.kernel_callchains, 250953651b28Syuzhoujian "collect kernel callchains"), 251053651b28Syuzhoujian OPT_BOOLEAN(0, "user-callchains", &record.opts.user_callchains, 251153651b28Syuzhoujian "collect user callchains"), 251271dc2326SWang Nan OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", 251371dc2326SWang Nan "clang binary to use for compiling BPF scriptlets"), 251471dc2326SWang Nan OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", 251571dc2326SWang Nan "options passed to clang when compiling BPF scriptlets"), 25167efe0e03SHe Kuang OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name, 25177efe0e03SHe Kuang "file", "vmlinux pathname"), 25186156681bSNamhyung Kim OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 25196156681bSNamhyung Kim "Record build-id of all DSOs regardless of hits"), 2520ecfd7a9cSWang Nan OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename, 2521ecfd7a9cSWang Nan "append timestamp to output filename"), 252268588bafSJin Yao OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary, 252368588bafSJin Yao "Record timestamp boundary (time of first/last samples)"), 2524cb4e1ebbSJiri Olsa OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str, 2525c38dab7dSAndi Kleen &record.switch_output.set, "signal or size[BKMG] or time[smhd]", 2526c38dab7dSAndi Kleen "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold", 2527dc0c6127SJiri Olsa "signal"), 2528899e5ffbSArnaldo Carvalho de Melo OPT_CALLBACK_SET(0, "switch-output-event", &record.sb_evlist, &record.switch_output_event_set, "switch output event", 2529899e5ffbSArnaldo Carvalho de Melo "switch output event selector. use 'perf list' to list available events", 2530899e5ffbSArnaldo Carvalho de Melo parse_events_option_new_evlist), 253103724b2eSAndi Kleen OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, 253203724b2eSAndi Kleen "Limit number of switch output generated files"), 25330aab2136SWang Nan OPT_BOOLEAN(0, "dry-run", &dry_run, 25340aab2136SWang Nan "Parse options then exit"), 2535d3d1af6fSAlexey Budankov #ifdef HAVE_AIO_SUPPORT 253693f20c0fSAlexey Budankov OPT_CALLBACK_OPTARG(0, "aio", &record.opts, 253793f20c0fSAlexey Budankov &nr_cblocks_default, "n", "Use <n> control blocks in asynchronous trace writing mode (default: 1, max: 4)", 2538d3d1af6fSAlexey Budankov record__aio_parse), 2539d3d1af6fSAlexey Budankov #endif 2540f4fe11b7SAlexey Budankov OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", 2541f4fe11b7SAlexey Budankov "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", 2542f4fe11b7SAlexey Budankov record__parse_affinity), 2543504c1ad1SAlexey Budankov #ifdef HAVE_ZSTD_SUPPORT 2544504c1ad1SAlexey Budankov OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default, 2545504c1ad1SAlexey Budankov "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)", 2546504c1ad1SAlexey Budankov record__parse_comp_level), 2547504c1ad1SAlexey Budankov #endif 25486d575816SJiwei Sun OPT_CALLBACK(0, "max-size", &record.output_max_size, 25496d575816SJiwei Sun "size", "Limit the maximum size of the output file", parse_output_max_size), 2550d99c22eaSStephane Eranian OPT_UINTEGER(0, "num-thread-synthesize", 2551d99c22eaSStephane Eranian &record.opts.nr_threads_synthesize, 2552d99c22eaSStephane Eranian "number of threads to run for event synthesis"), 255370943490SStephane Eranian #ifdef HAVE_LIBPFM 255470943490SStephane Eranian OPT_CALLBACK(0, "pfm-events", &record.evlist, "event", 255570943490SStephane Eranian "libpfm4 event selector. use 'perf list' to list available events", 255670943490SStephane Eranian parse_libpfm_events_option), 255770943490SStephane Eranian #endif 25581d078ccbSAlexey Budankov OPT_CALLBACK(0, "control", &record.opts, "fd:ctl-fd[,ack-fd]", 25591d078ccbSAlexey Budankov "Listen on ctl-fd descriptor for command to control measurement ('enable': enable events, 'disable': disable events).\n" 25601d078ccbSAlexey Budankov "\t\t\t Optionally send control command completion ('ack\\n') to ack-fd descriptor.", 25611d078ccbSAlexey Budankov parse_control_option), 256286470930SIngo Molnar OPT_END() 256386470930SIngo Molnar }; 256486470930SIngo Molnar 2565e5b2c207SNamhyung Kim struct option *record_options = __record_options; 2566e5b2c207SNamhyung Kim 2567b0ad8ea6SArnaldo Carvalho de Melo int cmd_record(int argc, const char **argv) 256886470930SIngo Molnar { 2569ef149c25SAdrian Hunter int err; 25708c6f45a7SArnaldo Carvalho de Melo struct record *rec = &record; 257116ad2ffbSNamhyung Kim char errbuf[BUFSIZ]; 257286470930SIngo Molnar 257367230479SArnaldo Carvalho de Melo setlocale(LC_ALL, ""); 257467230479SArnaldo Carvalho de Melo 257548e1cab1SWang Nan #ifndef HAVE_LIBBPF_SUPPORT 257648e1cab1SWang Nan # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 257748e1cab1SWang Nan set_nobuild('\0', "clang-path", true); 257848e1cab1SWang Nan set_nobuild('\0', "clang-opt", true); 257948e1cab1SWang Nan # undef set_nobuild 258048e1cab1SWang Nan #endif 258148e1cab1SWang Nan 25827efe0e03SHe Kuang #ifndef HAVE_BPF_PROLOGUE 25837efe0e03SHe Kuang # if !defined (HAVE_DWARF_SUPPORT) 25847efe0e03SHe Kuang # define REASON "NO_DWARF=1" 25857efe0e03SHe Kuang # elif !defined (HAVE_LIBBPF_SUPPORT) 25867efe0e03SHe Kuang # define REASON "NO_LIBBPF=1" 25877efe0e03SHe Kuang # else 25887efe0e03SHe Kuang # define REASON "this architecture doesn't support BPF prologue" 25897efe0e03SHe Kuang # endif 25907efe0e03SHe Kuang # define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, REASON, c) 25917efe0e03SHe Kuang set_nobuild('\0', "vmlinux", true); 25927efe0e03SHe Kuang # undef set_nobuild 25937efe0e03SHe Kuang # undef REASON 25947efe0e03SHe Kuang #endif 25957efe0e03SHe Kuang 25969d2ed645SAlexey Budankov rec->opts.affinity = PERF_AFFINITY_SYS; 25979d2ed645SAlexey Budankov 25980f98b11cSJiri Olsa rec->evlist = evlist__new(); 25993e2be2daSArnaldo Carvalho de Melo if (rec->evlist == NULL) 2600361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 2601361c99a6SArnaldo Carvalho de Melo 2602ecc4c561SArnaldo Carvalho de Melo err = perf_config(perf_record_config, rec); 2603ecc4c561SArnaldo Carvalho de Melo if (err) 2604ecc4c561SArnaldo Carvalho de Melo return err; 2605eb853e80SJiri Olsa 2606bca647aaSTom Zanussi argc = parse_options(argc, argv, record_options, record_usage, 2607a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 260868ba3235SNamhyung Kim if (quiet) 260968ba3235SNamhyung Kim perf_quiet_option(); 2610483635a9SJiri Olsa 2611483635a9SJiri Olsa /* Make system wide (-a) the default target. */ 2612602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&rec->opts.target)) 2613483635a9SJiri Olsa rec->opts.target.system_wide = true; 261486470930SIngo Molnar 2615bea03405SNamhyung Kim if (nr_cgroups && !rec->opts.target.system_wide) { 2616c7118369SNamhyung Kim usage_with_options_msg(record_usage, record_options, 2617c7118369SNamhyung Kim "cgroup monitoring only available in system-wide mode"); 2618c7118369SNamhyung Kim 2619023695d9SStephane Eranian } 2620504c1ad1SAlexey Budankov 2621eeb399b5SAdrian Hunter if (rec->opts.kcore) 2622eeb399b5SAdrian Hunter rec->data.is_dir = true; 2623eeb399b5SAdrian Hunter 2624504c1ad1SAlexey Budankov if (rec->opts.comp_level != 0) { 2625504c1ad1SAlexey Budankov pr_debug("Compression enabled, disabling build id collection at the end of the session.\n"); 2626504c1ad1SAlexey Budankov rec->no_buildid = true; 2627504c1ad1SAlexey Budankov } 2628504c1ad1SAlexey Budankov 2629b757bb09SAdrian Hunter if (rec->opts.record_switch_events && 2630b757bb09SAdrian Hunter !perf_can_record_switch_events()) { 2631c7118369SNamhyung Kim ui__error("kernel does not support recording context switch events\n"); 2632c7118369SNamhyung Kim parse_options_usage(record_usage, record_options, "switch-events", 0); 2633c7118369SNamhyung Kim return -EINVAL; 2634b757bb09SAdrian Hunter } 2635023695d9SStephane Eranian 2636cb4e1ebbSJiri Olsa if (switch_output_setup(rec)) { 2637cb4e1ebbSJiri Olsa parse_options_usage(record_usage, record_options, "switch-output", 0); 2638cb4e1ebbSJiri Olsa return -EINVAL; 2639cb4e1ebbSJiri Olsa } 2640cb4e1ebbSJiri Olsa 2641bfacbe3bSJiri Olsa if (rec->switch_output.time) { 2642bfacbe3bSJiri Olsa signal(SIGALRM, alarm_sig_handler); 2643bfacbe3bSJiri Olsa alarm(rec->switch_output.time); 2644bfacbe3bSJiri Olsa } 2645bfacbe3bSJiri Olsa 264603724b2eSAndi Kleen if (rec->switch_output.num_files) { 264703724b2eSAndi Kleen rec->switch_output.filenames = calloc(sizeof(char *), 264803724b2eSAndi Kleen rec->switch_output.num_files); 264903724b2eSAndi Kleen if (!rec->switch_output.filenames) 265003724b2eSAndi Kleen return -EINVAL; 265103724b2eSAndi Kleen } 265203724b2eSAndi Kleen 26531b36c03eSAdrian Hunter /* 26541b36c03eSAdrian Hunter * Allow aliases to facilitate the lookup of symbols for address 26551b36c03eSAdrian Hunter * filters. Refer to auxtrace_parse_filters(). 26561b36c03eSAdrian Hunter */ 26571b36c03eSAdrian Hunter symbol_conf.allow_aliases = true; 26581b36c03eSAdrian Hunter 26591b36c03eSAdrian Hunter symbol__init(NULL); 26601b36c03eSAdrian Hunter 26618384a260SAlexey Budankov if (rec->opts.affinity != PERF_AFFINITY_SYS) { 26628384a260SAlexey Budankov rec->affinity_mask.nbits = cpu__max_cpu(); 26638384a260SAlexey Budankov rec->affinity_mask.bits = bitmap_alloc(rec->affinity_mask.nbits); 26648384a260SAlexey Budankov if (!rec->affinity_mask.bits) { 26658384a260SAlexey Budankov pr_err("Failed to allocate thread mask for %zd cpus\n", rec->affinity_mask.nbits); 26668384a260SAlexey Budankov return -ENOMEM; 26678384a260SAlexey Budankov } 26688384a260SAlexey Budankov pr_debug2("thread mask[%zd]: empty\n", rec->affinity_mask.nbits); 26698384a260SAlexey Budankov } 26708384a260SAlexey Budankov 26714b5ea3bdSAdrian Hunter err = record__auxtrace_init(rec); 26721b36c03eSAdrian Hunter if (err) 26731b36c03eSAdrian Hunter goto out; 26741b36c03eSAdrian Hunter 26750aab2136SWang Nan if (dry_run) 26765c01ad60SAdrian Hunter goto out; 26770aab2136SWang Nan 2678d7888573SWang Nan err = bpf__setup_stdout(rec->evlist); 2679d7888573SWang Nan if (err) { 2680d7888573SWang Nan bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 2681d7888573SWang Nan pr_err("ERROR: Setup BPF stdout failed: %s\n", 2682d7888573SWang Nan errbuf); 26835c01ad60SAdrian Hunter goto out; 2684d7888573SWang Nan } 2685d7888573SWang Nan 2686ef149c25SAdrian Hunter err = -ENOMEM; 2687ef149c25SAdrian Hunter 26880c1d46a8SWang Nan if (rec->no_buildid_cache || rec->no_buildid) { 2689a1ac1d3cSStephane Eranian disable_buildid_cache(); 2690dc0c6127SJiri Olsa } else if (rec->switch_output.enabled) { 26910c1d46a8SWang Nan /* 26920c1d46a8SWang Nan * In 'perf record --switch-output', disable buildid 26930c1d46a8SWang Nan * generation by default to reduce data file switching 26940c1d46a8SWang Nan * overhead. Still generate buildid if they are required 26950c1d46a8SWang Nan * explicitly using 26960c1d46a8SWang Nan * 269760437ac0SJiri Olsa * perf record --switch-output --no-no-buildid \ 26980c1d46a8SWang Nan * --no-no-buildid-cache 26990c1d46a8SWang Nan * 27000c1d46a8SWang Nan * Following code equals to: 27010c1d46a8SWang Nan * 27020c1d46a8SWang Nan * if ((rec->no_buildid || !rec->no_buildid_set) && 27030c1d46a8SWang Nan * (rec->no_buildid_cache || !rec->no_buildid_cache_set)) 27040c1d46a8SWang Nan * disable_buildid_cache(); 27050c1d46a8SWang Nan */ 27060c1d46a8SWang Nan bool disable = true; 27070c1d46a8SWang Nan 27080c1d46a8SWang Nan if (rec->no_buildid_set && !rec->no_buildid) 27090c1d46a8SWang Nan disable = false; 27100c1d46a8SWang Nan if (rec->no_buildid_cache_set && !rec->no_buildid_cache) 27110c1d46a8SWang Nan disable = false; 27120c1d46a8SWang Nan if (disable) { 27130c1d46a8SWang Nan rec->no_buildid = true; 27140c1d46a8SWang Nan rec->no_buildid_cache = true; 27150c1d46a8SWang Nan disable_buildid_cache(); 27160c1d46a8SWang Nan } 27170c1d46a8SWang Nan } 2718655000e7SArnaldo Carvalho de Melo 27194ea648aeSWang Nan if (record.opts.overwrite) 27204ea648aeSWang Nan record.opts.tail_synthesize = true; 27214ea648aeSWang Nan 27226484d2f9SJiri Olsa if (rec->evlist->core.nr_entries == 0 && 2723e251abeeSArnaldo Carvalho de Melo __evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { 272469aad6f1SArnaldo Carvalho de Melo pr_err("Not enough memory for event selector list\n"); 2725394c01edSAdrian Hunter goto out; 2726bbd36e5eSPeter Zijlstra } 272786470930SIngo Molnar 272869e7e5b0SAdrian Hunter if (rec->opts.target.tid && !rec->opts.no_inherit_set) 272969e7e5b0SAdrian Hunter rec->opts.no_inherit = true; 273069e7e5b0SAdrian Hunter 2731602ad878SArnaldo Carvalho de Melo err = target__validate(&rec->opts.target); 273216ad2ffbSNamhyung Kim if (err) { 2733602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 2734c3dec27bSJiri Olsa ui__warning("%s\n", errbuf); 273516ad2ffbSNamhyung Kim } 27364bd0f2d2SNamhyung Kim 2737602ad878SArnaldo Carvalho de Melo err = target__parse_uid(&rec->opts.target); 273816ad2ffbSNamhyung Kim if (err) { 273916ad2ffbSNamhyung Kim int saved_errno = errno; 274016ad2ffbSNamhyung Kim 2741602ad878SArnaldo Carvalho de Melo target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 27423780f488SNamhyung Kim ui__error("%s", errbuf); 274316ad2ffbSNamhyung Kim 274416ad2ffbSNamhyung Kim err = -saved_errno; 2745394c01edSAdrian Hunter goto out; 274616ad2ffbSNamhyung Kim } 27470d37aa34SArnaldo Carvalho de Melo 2748ca800068SMengting Zhang /* Enable ignoring missing threads when -u/-p option is defined. */ 2749ca800068SMengting Zhang rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; 275023dc4f15SJiri Olsa 275116ad2ffbSNamhyung Kim err = -ENOMEM; 27523e2be2daSArnaldo Carvalho de Melo if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0) 2753dd7927f4SArnaldo Carvalho de Melo usage_with_options(record_usage, record_options); 275469aad6f1SArnaldo Carvalho de Melo 2755ef149c25SAdrian Hunter err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 2756ef149c25SAdrian Hunter if (err) 2757394c01edSAdrian Hunter goto out; 2758ef149c25SAdrian Hunter 27596156681bSNamhyung Kim /* 27606156681bSNamhyung Kim * We take all buildids when the file contains 27616156681bSNamhyung Kim * AUX area tracing data because we do not decode the 27626156681bSNamhyung Kim * trace because it would take too long. 27636156681bSNamhyung Kim */ 27646156681bSNamhyung Kim if (rec->opts.full_auxtrace) 27656156681bSNamhyung Kim rec->buildid_all = true; 27666156681bSNamhyung Kim 2767246eba8eSAdrian Hunter if (rec->opts.text_poke) { 2768246eba8eSAdrian Hunter err = record__config_text_poke(rec->evlist); 2769246eba8eSAdrian Hunter if (err) { 2770246eba8eSAdrian Hunter pr_err("record__config_text_poke failed, error %d\n", err); 2771246eba8eSAdrian Hunter goto out; 2772246eba8eSAdrian Hunter } 2773246eba8eSAdrian Hunter } 2774246eba8eSAdrian Hunter 2775b4006796SArnaldo Carvalho de Melo if (record_opts__config(&rec->opts)) { 277639d17dacSArnaldo Carvalho de Melo err = -EINVAL; 2777394c01edSAdrian Hunter goto out; 27787e4ff9e3SMike Galbraith } 27797e4ff9e3SMike Galbraith 278093f20c0fSAlexey Budankov if (rec->opts.nr_cblocks > nr_cblocks_max) 278193f20c0fSAlexey Budankov rec->opts.nr_cblocks = nr_cblocks_max; 27825d7f4116SAlexey Budankov pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks); 2783d3d1af6fSAlexey Budankov 27849d2ed645SAlexey Budankov pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); 2785470530bbSAlexey Budankov pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); 27869d2ed645SAlexey Budankov 278751255a8aSAlexey Budankov if (rec->opts.comp_level > comp_level_max) 278851255a8aSAlexey Budankov rec->opts.comp_level = comp_level_max; 278951255a8aSAlexey Budankov pr_debug("comp level: %d\n", rec->opts.comp_level); 279051255a8aSAlexey Budankov 2791d20deb64SArnaldo Carvalho de Melo err = __cmd_record(&record, argc, argv); 2792394c01edSAdrian Hunter out: 27938384a260SAlexey Budankov bitmap_free(rec->affinity_mask.bits); 2794c12995a5SJiri Olsa evlist__delete(rec->evlist); 2795d65a458bSArnaldo Carvalho de Melo symbol__exit(); 2796ef149c25SAdrian Hunter auxtrace_record__free(rec->itr); 279739d17dacSArnaldo Carvalho de Melo return err; 279886470930SIngo Molnar } 27992dd6d8a1SAdrian Hunter 28002dd6d8a1SAdrian Hunter static void snapshot_sig_handler(int sig __maybe_unused) 28012dd6d8a1SAdrian Hunter { 2802dc0c6127SJiri Olsa struct record *rec = &record; 2803dc0c6127SJiri Olsa 28045f9cf599SWang Nan if (trigger_is_ready(&auxtrace_snapshot_trigger)) { 28055f9cf599SWang Nan trigger_hit(&auxtrace_snapshot_trigger); 28062dd6d8a1SAdrian Hunter auxtrace_record__snapshot_started = 1; 28075f9cf599SWang Nan if (auxtrace_record__snapshot_start(record.itr)) 28085f9cf599SWang Nan trigger_error(&auxtrace_snapshot_trigger); 28095f9cf599SWang Nan } 28103c1cb7e3SWang Nan 2811dc0c6127SJiri Olsa if (switch_output_signal(rec)) 28123c1cb7e3SWang Nan trigger_hit(&switch_output_trigger); 28132dd6d8a1SAdrian Hunter } 2814bfacbe3bSJiri Olsa 2815bfacbe3bSJiri Olsa static void alarm_sig_handler(int sig __maybe_unused) 2816bfacbe3bSJiri Olsa { 2817bfacbe3bSJiri Olsa struct record *rec = &record; 2818bfacbe3bSJiri Olsa 2819bfacbe3bSJiri Olsa if (switch_output_time(rec)) 2820bfacbe3bSJiri Olsa trigger_hit(&switch_output_trigger); 2821bfacbe3bSJiri Olsa } 2822