162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <errno.h> 362306a36Sopenharmony_ci#include <signal.h> 462306a36Sopenharmony_ci#include <inttypes.h> 562306a36Sopenharmony_ci#include <linux/err.h> 662306a36Sopenharmony_ci#include <linux/kernel.h> 762306a36Sopenharmony_ci#include <linux/zalloc.h> 862306a36Sopenharmony_ci#include <api/fs/fs.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <byteswap.h> 1162306a36Sopenharmony_ci#include <unistd.h> 1262306a36Sopenharmony_ci#include <sys/types.h> 1362306a36Sopenharmony_ci#include <sys/mman.h> 1462306a36Sopenharmony_ci#include <perf/cpumap.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "map_symbol.h" 1762306a36Sopenharmony_ci#include "branch.h" 1862306a36Sopenharmony_ci#include "debug.h" 1962306a36Sopenharmony_ci#include "env.h" 2062306a36Sopenharmony_ci#include "evlist.h" 2162306a36Sopenharmony_ci#include "evsel.h" 2262306a36Sopenharmony_ci#include "memswap.h" 2362306a36Sopenharmony_ci#include "map.h" 2462306a36Sopenharmony_ci#include "symbol.h" 2562306a36Sopenharmony_ci#include "session.h" 2662306a36Sopenharmony_ci#include "tool.h" 2762306a36Sopenharmony_ci#include "perf_regs.h" 2862306a36Sopenharmony_ci#include "asm/bug.h" 2962306a36Sopenharmony_ci#include "auxtrace.h" 3062306a36Sopenharmony_ci#include "thread.h" 3162306a36Sopenharmony_ci#include "thread-stack.h" 3262306a36Sopenharmony_ci#include "sample-raw.h" 3362306a36Sopenharmony_ci#include "stat.h" 3462306a36Sopenharmony_ci#include "tsc.h" 3562306a36Sopenharmony_ci#include "ui/progress.h" 3662306a36Sopenharmony_ci#include "util.h" 3762306a36Sopenharmony_ci#include "arch/common.h" 3862306a36Sopenharmony_ci#include "units.h" 3962306a36Sopenharmony_ci#include <internal/lib.h> 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#ifdef HAVE_ZSTD_SUPPORT 4262306a36Sopenharmony_cistatic int perf_session__process_compressed_event(struct perf_session *session, 4362306a36Sopenharmony_ci union perf_event *event, u64 file_offset, 4462306a36Sopenharmony_ci const char *file_path) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci void *src; 4762306a36Sopenharmony_ci size_t decomp_size, src_size; 4862306a36Sopenharmony_ci u64 decomp_last_rem = 0; 4962306a36Sopenharmony_ci size_t mmap_len, decomp_len = session->header.env.comp_mmap_len; 5062306a36Sopenharmony_ci struct decomp *decomp, *decomp_last = session->active_decomp->decomp_last; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci if (decomp_last) { 5362306a36Sopenharmony_ci decomp_last_rem = decomp_last->size - decomp_last->head; 5462306a36Sopenharmony_ci decomp_len += decomp_last_rem; 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci mmap_len = sizeof(struct decomp) + decomp_len; 5862306a36Sopenharmony_ci decomp = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE, 5962306a36Sopenharmony_ci MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 6062306a36Sopenharmony_ci if (decomp == MAP_FAILED) { 6162306a36Sopenharmony_ci pr_err("Couldn't allocate memory for decompression\n"); 6262306a36Sopenharmony_ci return -1; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci decomp->file_pos = file_offset; 6662306a36Sopenharmony_ci decomp->file_path = file_path; 6762306a36Sopenharmony_ci decomp->mmap_len = mmap_len; 6862306a36Sopenharmony_ci decomp->head = 0; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (decomp_last_rem) { 7162306a36Sopenharmony_ci memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem); 7262306a36Sopenharmony_ci decomp->size = decomp_last_rem; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci src = (void *)event + sizeof(struct perf_record_compressed); 7662306a36Sopenharmony_ci src_size = event->pack.header.size - sizeof(struct perf_record_compressed); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci decomp_size = zstd_decompress_stream(session->active_decomp->zstd_decomp, src, src_size, 7962306a36Sopenharmony_ci &(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem); 8062306a36Sopenharmony_ci if (!decomp_size) { 8162306a36Sopenharmony_ci munmap(decomp, mmap_len); 8262306a36Sopenharmony_ci pr_err("Couldn't decompress data\n"); 8362306a36Sopenharmony_ci return -1; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci decomp->size += decomp_size; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (session->active_decomp->decomp == NULL) 8962306a36Sopenharmony_ci session->active_decomp->decomp = decomp; 9062306a36Sopenharmony_ci else 9162306a36Sopenharmony_ci session->active_decomp->decomp_last->next = decomp; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci session->active_decomp->decomp_last = decomp; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci pr_debug("decomp (B): %zd to %zd\n", src_size, decomp_size); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci return 0; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci#else /* !HAVE_ZSTD_SUPPORT */ 10062306a36Sopenharmony_ci#define perf_session__process_compressed_event perf_session__process_compressed_event_stub 10162306a36Sopenharmony_ci#endif 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic int perf_session__deliver_event(struct perf_session *session, 10462306a36Sopenharmony_ci union perf_event *event, 10562306a36Sopenharmony_ci struct perf_tool *tool, 10662306a36Sopenharmony_ci u64 file_offset, 10762306a36Sopenharmony_ci const char *file_path); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int perf_session__open(struct perf_session *session, int repipe_fd) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci struct perf_data *data = session->data; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if (perf_session__read_header(session, repipe_fd) < 0) { 11462306a36Sopenharmony_ci pr_err("incompatible file format (rerun with -v to learn more)\n"); 11562306a36Sopenharmony_ci return -1; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if (perf_data__is_pipe(data)) 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (perf_header__has_feat(&session->header, HEADER_STAT)) 12262306a36Sopenharmony_ci return 0; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (!evlist__valid_sample_type(session->evlist)) { 12562306a36Sopenharmony_ci pr_err("non matching sample_type\n"); 12662306a36Sopenharmony_ci return -1; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (!evlist__valid_sample_id_all(session->evlist)) { 13062306a36Sopenharmony_ci pr_err("non matching sample_id_all\n"); 13162306a36Sopenharmony_ci return -1; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (!evlist__valid_read_format(session->evlist)) { 13562306a36Sopenharmony_ci pr_err("non matching read_format\n"); 13662306a36Sopenharmony_ci return -1; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return 0; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_civoid perf_session__set_id_hdr_size(struct perf_session *session) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci u16 id_hdr_size = evlist__id_hdr_size(session->evlist); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci machines__set_id_hdr_size(&session->machines, id_hdr_size); 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciint perf_session__create_kernel_maps(struct perf_session *session) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci int ret = machine__create_kernel_maps(&session->machines.host); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (ret >= 0) 15462306a36Sopenharmony_ci ret = machines__create_guest_kernel_maps(&session->machines); 15562306a36Sopenharmony_ci return ret; 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic void perf_session__destroy_kernel_maps(struct perf_session *session) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci machines__destroy_kernel_maps(&session->machines); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic bool perf_session__has_comm_exec(struct perf_session *session) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct evsel *evsel; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci evlist__for_each_entry(session->evlist, evsel) { 16862306a36Sopenharmony_ci if (evsel->core.attr.comm_exec) 16962306a36Sopenharmony_ci return true; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci return false; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic void perf_session__set_comm_exec(struct perf_session *session) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci bool comm_exec = perf_session__has_comm_exec(session); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci machines__set_comm_exec(&session->machines, comm_exec); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int ordered_events__deliver_event(struct ordered_events *oe, 18362306a36Sopenharmony_ci struct ordered_event *event) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct perf_session *session = container_of(oe, struct perf_session, 18662306a36Sopenharmony_ci ordered_events); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return perf_session__deliver_event(session, event->event, 18962306a36Sopenharmony_ci session->tool, event->file_offset, 19062306a36Sopenharmony_ci event->file_path); 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistruct perf_session *__perf_session__new(struct perf_data *data, 19462306a36Sopenharmony_ci bool repipe, int repipe_fd, 19562306a36Sopenharmony_ci struct perf_tool *tool) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci int ret = -ENOMEM; 19862306a36Sopenharmony_ci struct perf_session *session = zalloc(sizeof(*session)); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci if (!session) 20162306a36Sopenharmony_ci goto out; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci session->repipe = repipe; 20462306a36Sopenharmony_ci session->tool = tool; 20562306a36Sopenharmony_ci session->decomp_data.zstd_decomp = &session->zstd_data; 20662306a36Sopenharmony_ci session->active_decomp = &session->decomp_data; 20762306a36Sopenharmony_ci INIT_LIST_HEAD(&session->auxtrace_index); 20862306a36Sopenharmony_ci machines__init(&session->machines); 20962306a36Sopenharmony_ci ordered_events__init(&session->ordered_events, 21062306a36Sopenharmony_ci ordered_events__deliver_event, NULL); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci perf_env__init(&session->header.env); 21362306a36Sopenharmony_ci if (data) { 21462306a36Sopenharmony_ci ret = perf_data__open(data); 21562306a36Sopenharmony_ci if (ret < 0) 21662306a36Sopenharmony_ci goto out_delete; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci session->data = data; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci if (perf_data__is_read(data)) { 22162306a36Sopenharmony_ci ret = perf_session__open(session, repipe_fd); 22262306a36Sopenharmony_ci if (ret < 0) 22362306a36Sopenharmony_ci goto out_delete; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* 22662306a36Sopenharmony_ci * set session attributes that are present in perf.data 22762306a36Sopenharmony_ci * but not in pipe-mode. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ci if (!data->is_pipe) { 23062306a36Sopenharmony_ci perf_session__set_id_hdr_size(session); 23162306a36Sopenharmony_ci perf_session__set_comm_exec(session); 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci evlist__init_trace_event_sample_raw(session->evlist); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* Open the directory data. */ 23762306a36Sopenharmony_ci if (data->is_dir) { 23862306a36Sopenharmony_ci ret = perf_data__open_dir(data); 23962306a36Sopenharmony_ci if (ret) 24062306a36Sopenharmony_ci goto out_delete; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (!symbol_conf.kallsyms_name && 24462306a36Sopenharmony_ci !symbol_conf.vmlinux_name) 24562306a36Sopenharmony_ci symbol_conf.kallsyms_name = perf_data__kallsyms_name(data); 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci } else { 24862306a36Sopenharmony_ci session->machines.host.env = &perf_env; 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci session->machines.host.single_address_space = 25262306a36Sopenharmony_ci perf_env__single_address_space(session->machines.host.env); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (!data || perf_data__is_write(data)) { 25562306a36Sopenharmony_ci /* 25662306a36Sopenharmony_ci * In O_RDONLY mode this will be performed when reading the 25762306a36Sopenharmony_ci * kernel MMAP event, in perf_event__process_mmap(). 25862306a36Sopenharmony_ci */ 25962306a36Sopenharmony_ci if (perf_session__create_kernel_maps(session) < 0) 26062306a36Sopenharmony_ci pr_warning("Cannot read kernel map\n"); 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* 26462306a36Sopenharmony_ci * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is 26562306a36Sopenharmony_ci * processed, so evlist__sample_id_all is not meaningful here. 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_ci if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps && 26862306a36Sopenharmony_ci tool->ordered_events && !evlist__sample_id_all(session->evlist)) { 26962306a36Sopenharmony_ci dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 27062306a36Sopenharmony_ci tool->ordered_events = false; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci return session; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci out_delete: 27662306a36Sopenharmony_ci perf_session__delete(session); 27762306a36Sopenharmony_ci out: 27862306a36Sopenharmony_ci return ERR_PTR(ret); 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic void perf_decomp__release_events(struct decomp *next) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci struct decomp *decomp; 28462306a36Sopenharmony_ci size_t mmap_len; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci do { 28762306a36Sopenharmony_ci decomp = next; 28862306a36Sopenharmony_ci if (decomp == NULL) 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci next = decomp->next; 29162306a36Sopenharmony_ci mmap_len = decomp->mmap_len; 29262306a36Sopenharmony_ci munmap(decomp, mmap_len); 29362306a36Sopenharmony_ci } while (1); 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_civoid perf_session__delete(struct perf_session *session) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci if (session == NULL) 29962306a36Sopenharmony_ci return; 30062306a36Sopenharmony_ci auxtrace__free(session); 30162306a36Sopenharmony_ci auxtrace_index__free(&session->auxtrace_index); 30262306a36Sopenharmony_ci perf_session__destroy_kernel_maps(session); 30362306a36Sopenharmony_ci perf_decomp__release_events(session->decomp_data.decomp); 30462306a36Sopenharmony_ci perf_env__exit(&session->header.env); 30562306a36Sopenharmony_ci machines__exit(&session->machines); 30662306a36Sopenharmony_ci if (session->data) { 30762306a36Sopenharmony_ci if (perf_data__is_read(session->data)) 30862306a36Sopenharmony_ci evlist__delete(session->evlist); 30962306a36Sopenharmony_ci perf_data__close(session->data); 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci#ifdef HAVE_LIBTRACEEVENT 31262306a36Sopenharmony_ci trace_event__cleanup(&session->tevent); 31362306a36Sopenharmony_ci#endif 31462306a36Sopenharmony_ci free(session); 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic int process_event_synth_tracing_data_stub(struct perf_session *session 31862306a36Sopenharmony_ci __maybe_unused, 31962306a36Sopenharmony_ci union perf_event *event 32062306a36Sopenharmony_ci __maybe_unused) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 32362306a36Sopenharmony_ci return 0; 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused, 32762306a36Sopenharmony_ci union perf_event *event __maybe_unused, 32862306a36Sopenharmony_ci struct evlist **pevlist 32962306a36Sopenharmony_ci __maybe_unused) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 33262306a36Sopenharmony_ci return 0; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic int process_event_synth_event_update_stub(struct perf_tool *tool __maybe_unused, 33662306a36Sopenharmony_ci union perf_event *event __maybe_unused, 33762306a36Sopenharmony_ci struct evlist **pevlist 33862306a36Sopenharmony_ci __maybe_unused) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci if (dump_trace) 34162306a36Sopenharmony_ci perf_event__fprintf_event_update(event, stdout); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 34462306a36Sopenharmony_ci return 0; 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_cistatic int process_event_sample_stub(struct perf_tool *tool __maybe_unused, 34862306a36Sopenharmony_ci union perf_event *event __maybe_unused, 34962306a36Sopenharmony_ci struct perf_sample *sample __maybe_unused, 35062306a36Sopenharmony_ci struct evsel *evsel __maybe_unused, 35162306a36Sopenharmony_ci struct machine *machine __maybe_unused) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 35462306a36Sopenharmony_ci return 0; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic int process_event_stub(struct perf_tool *tool __maybe_unused, 35862306a36Sopenharmony_ci union perf_event *event __maybe_unused, 35962306a36Sopenharmony_ci struct perf_sample *sample __maybe_unused, 36062306a36Sopenharmony_ci struct machine *machine __maybe_unused) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 36362306a36Sopenharmony_ci return 0; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic int process_finished_round_stub(struct perf_tool *tool __maybe_unused, 36762306a36Sopenharmony_ci union perf_event *event __maybe_unused, 36862306a36Sopenharmony_ci struct ordered_events *oe __maybe_unused) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 37162306a36Sopenharmony_ci return 0; 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic int skipn(int fd, off_t n) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci char buf[4096]; 37762306a36Sopenharmony_ci ssize_t ret; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci while (n > 0) { 38062306a36Sopenharmony_ci ret = read(fd, buf, min(n, (off_t)sizeof(buf))); 38162306a36Sopenharmony_ci if (ret <= 0) 38262306a36Sopenharmony_ci return ret; 38362306a36Sopenharmony_ci n -= ret; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci return 0; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused, 39062306a36Sopenharmony_ci union perf_event *event) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 39362306a36Sopenharmony_ci if (perf_data__is_pipe(session->data)) 39462306a36Sopenharmony_ci skipn(perf_data__fd(session->data), event->auxtrace.size); 39562306a36Sopenharmony_ci return event->auxtrace.size; 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic int process_event_op2_stub(struct perf_session *session __maybe_unused, 39962306a36Sopenharmony_ci union perf_event *event __maybe_unused) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 40262306a36Sopenharmony_ci return 0; 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic 40762306a36Sopenharmony_ciint process_event_thread_map_stub(struct perf_session *session __maybe_unused, 40862306a36Sopenharmony_ci union perf_event *event __maybe_unused) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci if (dump_trace) 41162306a36Sopenharmony_ci perf_event__fprintf_thread_map(event, stdout); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 41462306a36Sopenharmony_ci return 0; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic 41862306a36Sopenharmony_ciint process_event_cpu_map_stub(struct perf_session *session __maybe_unused, 41962306a36Sopenharmony_ci union perf_event *event __maybe_unused) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci if (dump_trace) 42262306a36Sopenharmony_ci perf_event__fprintf_cpu_map(event, stdout); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 42562306a36Sopenharmony_ci return 0; 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic 42962306a36Sopenharmony_ciint process_event_stat_config_stub(struct perf_session *session __maybe_unused, 43062306a36Sopenharmony_ci union perf_event *event __maybe_unused) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci if (dump_trace) 43362306a36Sopenharmony_ci perf_event__fprintf_stat_config(event, stdout); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 43662306a36Sopenharmony_ci return 0; 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic int process_stat_stub(struct perf_session *perf_session __maybe_unused, 44062306a36Sopenharmony_ci union perf_event *event) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci if (dump_trace) 44362306a36Sopenharmony_ci perf_event__fprintf_stat(event, stdout); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 44662306a36Sopenharmony_ci return 0; 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic int process_stat_round_stub(struct perf_session *perf_session __maybe_unused, 45062306a36Sopenharmony_ci union perf_event *event) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci if (dump_trace) 45362306a36Sopenharmony_ci perf_event__fprintf_stat_round(event, stdout); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 45662306a36Sopenharmony_ci return 0; 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int process_event_time_conv_stub(struct perf_session *perf_session __maybe_unused, 46062306a36Sopenharmony_ci union perf_event *event) 46162306a36Sopenharmony_ci{ 46262306a36Sopenharmony_ci if (dump_trace) 46362306a36Sopenharmony_ci perf_event__fprintf_time_conv(event, stdout); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic int perf_session__process_compressed_event_stub(struct perf_session *session __maybe_unused, 47062306a36Sopenharmony_ci union perf_event *event __maybe_unused, 47162306a36Sopenharmony_ci u64 file_offset __maybe_unused, 47262306a36Sopenharmony_ci const char *file_path __maybe_unused) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci dump_printf(": unhandled!\n"); 47562306a36Sopenharmony_ci return 0; 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_civoid perf_tool__fill_defaults(struct perf_tool *tool) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci if (tool->sample == NULL) 48162306a36Sopenharmony_ci tool->sample = process_event_sample_stub; 48262306a36Sopenharmony_ci if (tool->mmap == NULL) 48362306a36Sopenharmony_ci tool->mmap = process_event_stub; 48462306a36Sopenharmony_ci if (tool->mmap2 == NULL) 48562306a36Sopenharmony_ci tool->mmap2 = process_event_stub; 48662306a36Sopenharmony_ci if (tool->comm == NULL) 48762306a36Sopenharmony_ci tool->comm = process_event_stub; 48862306a36Sopenharmony_ci if (tool->namespaces == NULL) 48962306a36Sopenharmony_ci tool->namespaces = process_event_stub; 49062306a36Sopenharmony_ci if (tool->cgroup == NULL) 49162306a36Sopenharmony_ci tool->cgroup = process_event_stub; 49262306a36Sopenharmony_ci if (tool->fork == NULL) 49362306a36Sopenharmony_ci tool->fork = process_event_stub; 49462306a36Sopenharmony_ci if (tool->exit == NULL) 49562306a36Sopenharmony_ci tool->exit = process_event_stub; 49662306a36Sopenharmony_ci if (tool->lost == NULL) 49762306a36Sopenharmony_ci tool->lost = perf_event__process_lost; 49862306a36Sopenharmony_ci if (tool->lost_samples == NULL) 49962306a36Sopenharmony_ci tool->lost_samples = perf_event__process_lost_samples; 50062306a36Sopenharmony_ci if (tool->aux == NULL) 50162306a36Sopenharmony_ci tool->aux = perf_event__process_aux; 50262306a36Sopenharmony_ci if (tool->itrace_start == NULL) 50362306a36Sopenharmony_ci tool->itrace_start = perf_event__process_itrace_start; 50462306a36Sopenharmony_ci if (tool->context_switch == NULL) 50562306a36Sopenharmony_ci tool->context_switch = perf_event__process_switch; 50662306a36Sopenharmony_ci if (tool->ksymbol == NULL) 50762306a36Sopenharmony_ci tool->ksymbol = perf_event__process_ksymbol; 50862306a36Sopenharmony_ci if (tool->bpf == NULL) 50962306a36Sopenharmony_ci tool->bpf = perf_event__process_bpf; 51062306a36Sopenharmony_ci if (tool->text_poke == NULL) 51162306a36Sopenharmony_ci tool->text_poke = perf_event__process_text_poke; 51262306a36Sopenharmony_ci if (tool->aux_output_hw_id == NULL) 51362306a36Sopenharmony_ci tool->aux_output_hw_id = perf_event__process_aux_output_hw_id; 51462306a36Sopenharmony_ci if (tool->read == NULL) 51562306a36Sopenharmony_ci tool->read = process_event_sample_stub; 51662306a36Sopenharmony_ci if (tool->throttle == NULL) 51762306a36Sopenharmony_ci tool->throttle = process_event_stub; 51862306a36Sopenharmony_ci if (tool->unthrottle == NULL) 51962306a36Sopenharmony_ci tool->unthrottle = process_event_stub; 52062306a36Sopenharmony_ci if (tool->attr == NULL) 52162306a36Sopenharmony_ci tool->attr = process_event_synth_attr_stub; 52262306a36Sopenharmony_ci if (tool->event_update == NULL) 52362306a36Sopenharmony_ci tool->event_update = process_event_synth_event_update_stub; 52462306a36Sopenharmony_ci if (tool->tracing_data == NULL) 52562306a36Sopenharmony_ci tool->tracing_data = process_event_synth_tracing_data_stub; 52662306a36Sopenharmony_ci if (tool->build_id == NULL) 52762306a36Sopenharmony_ci tool->build_id = process_event_op2_stub; 52862306a36Sopenharmony_ci if (tool->finished_round == NULL) { 52962306a36Sopenharmony_ci if (tool->ordered_events) 53062306a36Sopenharmony_ci tool->finished_round = perf_event__process_finished_round; 53162306a36Sopenharmony_ci else 53262306a36Sopenharmony_ci tool->finished_round = process_finished_round_stub; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci if (tool->id_index == NULL) 53562306a36Sopenharmony_ci tool->id_index = process_event_op2_stub; 53662306a36Sopenharmony_ci if (tool->auxtrace_info == NULL) 53762306a36Sopenharmony_ci tool->auxtrace_info = process_event_op2_stub; 53862306a36Sopenharmony_ci if (tool->auxtrace == NULL) 53962306a36Sopenharmony_ci tool->auxtrace = process_event_auxtrace_stub; 54062306a36Sopenharmony_ci if (tool->auxtrace_error == NULL) 54162306a36Sopenharmony_ci tool->auxtrace_error = process_event_op2_stub; 54262306a36Sopenharmony_ci if (tool->thread_map == NULL) 54362306a36Sopenharmony_ci tool->thread_map = process_event_thread_map_stub; 54462306a36Sopenharmony_ci if (tool->cpu_map == NULL) 54562306a36Sopenharmony_ci tool->cpu_map = process_event_cpu_map_stub; 54662306a36Sopenharmony_ci if (tool->stat_config == NULL) 54762306a36Sopenharmony_ci tool->stat_config = process_event_stat_config_stub; 54862306a36Sopenharmony_ci if (tool->stat == NULL) 54962306a36Sopenharmony_ci tool->stat = process_stat_stub; 55062306a36Sopenharmony_ci if (tool->stat_round == NULL) 55162306a36Sopenharmony_ci tool->stat_round = process_stat_round_stub; 55262306a36Sopenharmony_ci if (tool->time_conv == NULL) 55362306a36Sopenharmony_ci tool->time_conv = process_event_time_conv_stub; 55462306a36Sopenharmony_ci if (tool->feature == NULL) 55562306a36Sopenharmony_ci tool->feature = process_event_op2_stub; 55662306a36Sopenharmony_ci if (tool->compressed == NULL) 55762306a36Sopenharmony_ci tool->compressed = perf_session__process_compressed_event; 55862306a36Sopenharmony_ci if (tool->finished_init == NULL) 55962306a36Sopenharmony_ci tool->finished_init = process_event_op2_stub; 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic void swap_sample_id_all(union perf_event *event, void *data) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci void *end = (void *) event + event->header.size; 56562306a36Sopenharmony_ci int size = end - data; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci BUG_ON(size % sizeof(u64)); 56862306a36Sopenharmony_ci mem_bswap_64(data, size); 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic void perf_event__all64_swap(union perf_event *event, 57262306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci struct perf_event_header *hdr = &event->header; 57562306a36Sopenharmony_ci mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic void perf_event__comm_swap(union perf_event *event, bool sample_id_all) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci event->comm.pid = bswap_32(event->comm.pid); 58162306a36Sopenharmony_ci event->comm.tid = bswap_32(event->comm.tid); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (sample_id_all) { 58462306a36Sopenharmony_ci void *data = &event->comm.comm; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); 58762306a36Sopenharmony_ci swap_sample_id_all(event, data); 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic void perf_event__mmap_swap(union perf_event *event, 59262306a36Sopenharmony_ci bool sample_id_all) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci event->mmap.pid = bswap_32(event->mmap.pid); 59562306a36Sopenharmony_ci event->mmap.tid = bswap_32(event->mmap.tid); 59662306a36Sopenharmony_ci event->mmap.start = bswap_64(event->mmap.start); 59762306a36Sopenharmony_ci event->mmap.len = bswap_64(event->mmap.len); 59862306a36Sopenharmony_ci event->mmap.pgoff = bswap_64(event->mmap.pgoff); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (sample_id_all) { 60162306a36Sopenharmony_ci void *data = &event->mmap.filename; 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); 60462306a36Sopenharmony_ci swap_sample_id_all(event, data); 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic void perf_event__mmap2_swap(union perf_event *event, 60962306a36Sopenharmony_ci bool sample_id_all) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci event->mmap2.pid = bswap_32(event->mmap2.pid); 61262306a36Sopenharmony_ci event->mmap2.tid = bswap_32(event->mmap2.tid); 61362306a36Sopenharmony_ci event->mmap2.start = bswap_64(event->mmap2.start); 61462306a36Sopenharmony_ci event->mmap2.len = bswap_64(event->mmap2.len); 61562306a36Sopenharmony_ci event->mmap2.pgoff = bswap_64(event->mmap2.pgoff); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (!(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) { 61862306a36Sopenharmony_ci event->mmap2.maj = bswap_32(event->mmap2.maj); 61962306a36Sopenharmony_ci event->mmap2.min = bswap_32(event->mmap2.min); 62062306a36Sopenharmony_ci event->mmap2.ino = bswap_64(event->mmap2.ino); 62162306a36Sopenharmony_ci event->mmap2.ino_generation = bswap_64(event->mmap2.ino_generation); 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci if (sample_id_all) { 62562306a36Sopenharmony_ci void *data = &event->mmap2.filename; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); 62862306a36Sopenharmony_ci swap_sample_id_all(event, data); 62962306a36Sopenharmony_ci } 63062306a36Sopenharmony_ci} 63162306a36Sopenharmony_cistatic void perf_event__task_swap(union perf_event *event, bool sample_id_all) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci event->fork.pid = bswap_32(event->fork.pid); 63462306a36Sopenharmony_ci event->fork.tid = bswap_32(event->fork.tid); 63562306a36Sopenharmony_ci event->fork.ppid = bswap_32(event->fork.ppid); 63662306a36Sopenharmony_ci event->fork.ptid = bswap_32(event->fork.ptid); 63762306a36Sopenharmony_ci event->fork.time = bswap_64(event->fork.time); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci if (sample_id_all) 64062306a36Sopenharmony_ci swap_sample_id_all(event, &event->fork + 1); 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic void perf_event__read_swap(union perf_event *event, bool sample_id_all) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci event->read.pid = bswap_32(event->read.pid); 64662306a36Sopenharmony_ci event->read.tid = bswap_32(event->read.tid); 64762306a36Sopenharmony_ci event->read.value = bswap_64(event->read.value); 64862306a36Sopenharmony_ci event->read.time_enabled = bswap_64(event->read.time_enabled); 64962306a36Sopenharmony_ci event->read.time_running = bswap_64(event->read.time_running); 65062306a36Sopenharmony_ci event->read.id = bswap_64(event->read.id); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (sample_id_all) 65362306a36Sopenharmony_ci swap_sample_id_all(event, &event->read + 1); 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic void perf_event__aux_swap(union perf_event *event, bool sample_id_all) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci event->aux.aux_offset = bswap_64(event->aux.aux_offset); 65962306a36Sopenharmony_ci event->aux.aux_size = bswap_64(event->aux.aux_size); 66062306a36Sopenharmony_ci event->aux.flags = bswap_64(event->aux.flags); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci if (sample_id_all) 66362306a36Sopenharmony_ci swap_sample_id_all(event, &event->aux + 1); 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_cistatic void perf_event__itrace_start_swap(union perf_event *event, 66762306a36Sopenharmony_ci bool sample_id_all) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci event->itrace_start.pid = bswap_32(event->itrace_start.pid); 67062306a36Sopenharmony_ci event->itrace_start.tid = bswap_32(event->itrace_start.tid); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (sample_id_all) 67362306a36Sopenharmony_ci swap_sample_id_all(event, &event->itrace_start + 1); 67462306a36Sopenharmony_ci} 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_cistatic void perf_event__switch_swap(union perf_event *event, bool sample_id_all) 67762306a36Sopenharmony_ci{ 67862306a36Sopenharmony_ci if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) { 67962306a36Sopenharmony_ci event->context_switch.next_prev_pid = 68062306a36Sopenharmony_ci bswap_32(event->context_switch.next_prev_pid); 68162306a36Sopenharmony_ci event->context_switch.next_prev_tid = 68262306a36Sopenharmony_ci bswap_32(event->context_switch.next_prev_tid); 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci if (sample_id_all) 68662306a36Sopenharmony_ci swap_sample_id_all(event, &event->context_switch + 1); 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic void perf_event__text_poke_swap(union perf_event *event, bool sample_id_all) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci event->text_poke.addr = bswap_64(event->text_poke.addr); 69262306a36Sopenharmony_ci event->text_poke.old_len = bswap_16(event->text_poke.old_len); 69362306a36Sopenharmony_ci event->text_poke.new_len = bswap_16(event->text_poke.new_len); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci if (sample_id_all) { 69662306a36Sopenharmony_ci size_t len = sizeof(event->text_poke.old_len) + 69762306a36Sopenharmony_ci sizeof(event->text_poke.new_len) + 69862306a36Sopenharmony_ci event->text_poke.old_len + 69962306a36Sopenharmony_ci event->text_poke.new_len; 70062306a36Sopenharmony_ci void *data = &event->text_poke.old_len; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci data += PERF_ALIGN(len, sizeof(u64)); 70362306a36Sopenharmony_ci swap_sample_id_all(event, data); 70462306a36Sopenharmony_ci } 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic void perf_event__throttle_swap(union perf_event *event, 70862306a36Sopenharmony_ci bool sample_id_all) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci event->throttle.time = bswap_64(event->throttle.time); 71162306a36Sopenharmony_ci event->throttle.id = bswap_64(event->throttle.id); 71262306a36Sopenharmony_ci event->throttle.stream_id = bswap_64(event->throttle.stream_id); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (sample_id_all) 71562306a36Sopenharmony_ci swap_sample_id_all(event, &event->throttle + 1); 71662306a36Sopenharmony_ci} 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_cistatic void perf_event__namespaces_swap(union perf_event *event, 71962306a36Sopenharmony_ci bool sample_id_all) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci u64 i; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci event->namespaces.pid = bswap_32(event->namespaces.pid); 72462306a36Sopenharmony_ci event->namespaces.tid = bswap_32(event->namespaces.tid); 72562306a36Sopenharmony_ci event->namespaces.nr_namespaces = bswap_64(event->namespaces.nr_namespaces); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci for (i = 0; i < event->namespaces.nr_namespaces; i++) { 72862306a36Sopenharmony_ci struct perf_ns_link_info *ns = &event->namespaces.link_info[i]; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci ns->dev = bswap_64(ns->dev); 73162306a36Sopenharmony_ci ns->ino = bswap_64(ns->ino); 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci if (sample_id_all) 73562306a36Sopenharmony_ci swap_sample_id_all(event, &event->namespaces.link_info[i]); 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic void perf_event__cgroup_swap(union perf_event *event, bool sample_id_all) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci event->cgroup.id = bswap_64(event->cgroup.id); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (sample_id_all) { 74362306a36Sopenharmony_ci void *data = &event->cgroup.path; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); 74662306a36Sopenharmony_ci swap_sample_id_all(event, data); 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci} 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_cistatic u8 revbyte(u8 b) 75162306a36Sopenharmony_ci{ 75262306a36Sopenharmony_ci int rev = (b >> 4) | ((b & 0xf) << 4); 75362306a36Sopenharmony_ci rev = ((rev & 0xcc) >> 2) | ((rev & 0x33) << 2); 75462306a36Sopenharmony_ci rev = ((rev & 0xaa) >> 1) | ((rev & 0x55) << 1); 75562306a36Sopenharmony_ci return (u8) rev; 75662306a36Sopenharmony_ci} 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci/* 75962306a36Sopenharmony_ci * XXX this is hack in attempt to carry flags bitfield 76062306a36Sopenharmony_ci * through endian village. ABI says: 76162306a36Sopenharmony_ci * 76262306a36Sopenharmony_ci * Bit-fields are allocated from right to left (least to most significant) 76362306a36Sopenharmony_ci * on little-endian implementations and from left to right (most to least 76462306a36Sopenharmony_ci * significant) on big-endian implementations. 76562306a36Sopenharmony_ci * 76662306a36Sopenharmony_ci * The above seems to be byte specific, so we need to reverse each 76762306a36Sopenharmony_ci * byte of the bitfield. 'Internet' also says this might be implementation 76862306a36Sopenharmony_ci * specific and we probably need proper fix and carry perf_event_attr 76962306a36Sopenharmony_ci * bitfield flags in separate data file FEAT_ section. Thought this seems 77062306a36Sopenharmony_ci * to work for now. 77162306a36Sopenharmony_ci */ 77262306a36Sopenharmony_cistatic void swap_bitfield(u8 *p, unsigned len) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci unsigned i; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci for (i = 0; i < len; i++) { 77762306a36Sopenharmony_ci *p = revbyte(*p); 77862306a36Sopenharmony_ci p++; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci} 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci/* exported for swapping attributes in file header */ 78362306a36Sopenharmony_civoid perf_event__attr_swap(struct perf_event_attr *attr) 78462306a36Sopenharmony_ci{ 78562306a36Sopenharmony_ci attr->type = bswap_32(attr->type); 78662306a36Sopenharmony_ci attr->size = bswap_32(attr->size); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci#define bswap_safe(f, n) \ 78962306a36Sopenharmony_ci (attr->size > (offsetof(struct perf_event_attr, f) + \ 79062306a36Sopenharmony_ci sizeof(attr->f) * (n))) 79162306a36Sopenharmony_ci#define bswap_field(f, sz) \ 79262306a36Sopenharmony_cido { \ 79362306a36Sopenharmony_ci if (bswap_safe(f, 0)) \ 79462306a36Sopenharmony_ci attr->f = bswap_##sz(attr->f); \ 79562306a36Sopenharmony_ci} while(0) 79662306a36Sopenharmony_ci#define bswap_field_16(f) bswap_field(f, 16) 79762306a36Sopenharmony_ci#define bswap_field_32(f) bswap_field(f, 32) 79862306a36Sopenharmony_ci#define bswap_field_64(f) bswap_field(f, 64) 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci bswap_field_64(config); 80162306a36Sopenharmony_ci bswap_field_64(sample_period); 80262306a36Sopenharmony_ci bswap_field_64(sample_type); 80362306a36Sopenharmony_ci bswap_field_64(read_format); 80462306a36Sopenharmony_ci bswap_field_32(wakeup_events); 80562306a36Sopenharmony_ci bswap_field_32(bp_type); 80662306a36Sopenharmony_ci bswap_field_64(bp_addr); 80762306a36Sopenharmony_ci bswap_field_64(bp_len); 80862306a36Sopenharmony_ci bswap_field_64(branch_sample_type); 80962306a36Sopenharmony_ci bswap_field_64(sample_regs_user); 81062306a36Sopenharmony_ci bswap_field_32(sample_stack_user); 81162306a36Sopenharmony_ci bswap_field_32(aux_watermark); 81262306a36Sopenharmony_ci bswap_field_16(sample_max_stack); 81362306a36Sopenharmony_ci bswap_field_32(aux_sample_size); 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci /* 81662306a36Sopenharmony_ci * After read_format are bitfields. Check read_format because 81762306a36Sopenharmony_ci * we are unable to use offsetof on bitfield. 81862306a36Sopenharmony_ci */ 81962306a36Sopenharmony_ci if (bswap_safe(read_format, 1)) 82062306a36Sopenharmony_ci swap_bitfield((u8 *) (&attr->read_format + 1), 82162306a36Sopenharmony_ci sizeof(u64)); 82262306a36Sopenharmony_ci#undef bswap_field_64 82362306a36Sopenharmony_ci#undef bswap_field_32 82462306a36Sopenharmony_ci#undef bswap_field 82562306a36Sopenharmony_ci#undef bswap_safe 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_cistatic void perf_event__hdr_attr_swap(union perf_event *event, 82962306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci size_t size; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci perf_event__attr_swap(&event->attr.attr); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci size = event->header.size; 83662306a36Sopenharmony_ci size -= perf_record_header_attr_id(event) - (void *)event; 83762306a36Sopenharmony_ci mem_bswap_64(perf_record_header_attr_id(event), size); 83862306a36Sopenharmony_ci} 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_cistatic void perf_event__event_update_swap(union perf_event *event, 84162306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 84262306a36Sopenharmony_ci{ 84362306a36Sopenharmony_ci event->event_update.type = bswap_64(event->event_update.type); 84462306a36Sopenharmony_ci event->event_update.id = bswap_64(event->event_update.id); 84562306a36Sopenharmony_ci} 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_cistatic void perf_event__event_type_swap(union perf_event *event, 84862306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 84962306a36Sopenharmony_ci{ 85062306a36Sopenharmony_ci event->event_type.event_type.event_id = 85162306a36Sopenharmony_ci bswap_64(event->event_type.event_type.event_id); 85262306a36Sopenharmony_ci} 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_cistatic void perf_event__tracing_data_swap(union perf_event *event, 85562306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 85662306a36Sopenharmony_ci{ 85762306a36Sopenharmony_ci event->tracing_data.size = bswap_32(event->tracing_data.size); 85862306a36Sopenharmony_ci} 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_cistatic void perf_event__auxtrace_info_swap(union perf_event *event, 86162306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci size_t size; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci event->auxtrace_info.type = bswap_32(event->auxtrace_info.type); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci size = event->header.size; 86862306a36Sopenharmony_ci size -= (void *)&event->auxtrace_info.priv - (void *)event; 86962306a36Sopenharmony_ci mem_bswap_64(event->auxtrace_info.priv, size); 87062306a36Sopenharmony_ci} 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic void perf_event__auxtrace_swap(union perf_event *event, 87362306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci event->auxtrace.size = bswap_64(event->auxtrace.size); 87662306a36Sopenharmony_ci event->auxtrace.offset = bswap_64(event->auxtrace.offset); 87762306a36Sopenharmony_ci event->auxtrace.reference = bswap_64(event->auxtrace.reference); 87862306a36Sopenharmony_ci event->auxtrace.idx = bswap_32(event->auxtrace.idx); 87962306a36Sopenharmony_ci event->auxtrace.tid = bswap_32(event->auxtrace.tid); 88062306a36Sopenharmony_ci event->auxtrace.cpu = bswap_32(event->auxtrace.cpu); 88162306a36Sopenharmony_ci} 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cistatic void perf_event__auxtrace_error_swap(union perf_event *event, 88462306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 88562306a36Sopenharmony_ci{ 88662306a36Sopenharmony_ci event->auxtrace_error.type = bswap_32(event->auxtrace_error.type); 88762306a36Sopenharmony_ci event->auxtrace_error.code = bswap_32(event->auxtrace_error.code); 88862306a36Sopenharmony_ci event->auxtrace_error.cpu = bswap_32(event->auxtrace_error.cpu); 88962306a36Sopenharmony_ci event->auxtrace_error.pid = bswap_32(event->auxtrace_error.pid); 89062306a36Sopenharmony_ci event->auxtrace_error.tid = bswap_32(event->auxtrace_error.tid); 89162306a36Sopenharmony_ci event->auxtrace_error.fmt = bswap_32(event->auxtrace_error.fmt); 89262306a36Sopenharmony_ci event->auxtrace_error.ip = bswap_64(event->auxtrace_error.ip); 89362306a36Sopenharmony_ci if (event->auxtrace_error.fmt) 89462306a36Sopenharmony_ci event->auxtrace_error.time = bswap_64(event->auxtrace_error.time); 89562306a36Sopenharmony_ci if (event->auxtrace_error.fmt >= 2) { 89662306a36Sopenharmony_ci event->auxtrace_error.machine_pid = bswap_32(event->auxtrace_error.machine_pid); 89762306a36Sopenharmony_ci event->auxtrace_error.vcpu = bswap_32(event->auxtrace_error.vcpu); 89862306a36Sopenharmony_ci } 89962306a36Sopenharmony_ci} 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_cistatic void perf_event__thread_map_swap(union perf_event *event, 90262306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 90362306a36Sopenharmony_ci{ 90462306a36Sopenharmony_ci unsigned i; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci event->thread_map.nr = bswap_64(event->thread_map.nr); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci for (i = 0; i < event->thread_map.nr; i++) 90962306a36Sopenharmony_ci event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid); 91062306a36Sopenharmony_ci} 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_cistatic void perf_event__cpu_map_swap(union perf_event *event, 91362306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 91462306a36Sopenharmony_ci{ 91562306a36Sopenharmony_ci struct perf_record_cpu_map_data *data = &event->cpu_map.data; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci data->type = bswap_16(data->type); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci switch (data->type) { 92062306a36Sopenharmony_ci case PERF_CPU_MAP__CPUS: 92162306a36Sopenharmony_ci data->cpus_data.nr = bswap_16(data->cpus_data.nr); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci for (unsigned i = 0; i < data->cpus_data.nr; i++) 92462306a36Sopenharmony_ci data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]); 92562306a36Sopenharmony_ci break; 92662306a36Sopenharmony_ci case PERF_CPU_MAP__MASK: 92762306a36Sopenharmony_ci data->mask32_data.long_size = bswap_16(data->mask32_data.long_size); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci switch (data->mask32_data.long_size) { 93062306a36Sopenharmony_ci case 4: 93162306a36Sopenharmony_ci data->mask32_data.nr = bswap_16(data->mask32_data.nr); 93262306a36Sopenharmony_ci for (unsigned i = 0; i < data->mask32_data.nr; i++) 93362306a36Sopenharmony_ci data->mask32_data.mask[i] = bswap_32(data->mask32_data.mask[i]); 93462306a36Sopenharmony_ci break; 93562306a36Sopenharmony_ci case 8: 93662306a36Sopenharmony_ci data->mask64_data.nr = bswap_16(data->mask64_data.nr); 93762306a36Sopenharmony_ci for (unsigned i = 0; i < data->mask64_data.nr; i++) 93862306a36Sopenharmony_ci data->mask64_data.mask[i] = bswap_64(data->mask64_data.mask[i]); 93962306a36Sopenharmony_ci break; 94062306a36Sopenharmony_ci default: 94162306a36Sopenharmony_ci pr_err("cpu_map swap: unsupported long size\n"); 94262306a36Sopenharmony_ci } 94362306a36Sopenharmony_ci break; 94462306a36Sopenharmony_ci case PERF_CPU_MAP__RANGE_CPUS: 94562306a36Sopenharmony_ci data->range_cpu_data.start_cpu = bswap_16(data->range_cpu_data.start_cpu); 94662306a36Sopenharmony_ci data->range_cpu_data.end_cpu = bswap_16(data->range_cpu_data.end_cpu); 94762306a36Sopenharmony_ci break; 94862306a36Sopenharmony_ci default: 94962306a36Sopenharmony_ci break; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_cistatic void perf_event__stat_config_swap(union perf_event *event, 95462306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 95562306a36Sopenharmony_ci{ 95662306a36Sopenharmony_ci u64 size; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci size = bswap_64(event->stat_config.nr) * sizeof(event->stat_config.data[0]); 95962306a36Sopenharmony_ci size += 1; /* nr item itself */ 96062306a36Sopenharmony_ci mem_bswap_64(&event->stat_config.nr, size); 96162306a36Sopenharmony_ci} 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_cistatic void perf_event__stat_swap(union perf_event *event, 96462306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci event->stat.id = bswap_64(event->stat.id); 96762306a36Sopenharmony_ci event->stat.thread = bswap_32(event->stat.thread); 96862306a36Sopenharmony_ci event->stat.cpu = bswap_32(event->stat.cpu); 96962306a36Sopenharmony_ci event->stat.val = bswap_64(event->stat.val); 97062306a36Sopenharmony_ci event->stat.ena = bswap_64(event->stat.ena); 97162306a36Sopenharmony_ci event->stat.run = bswap_64(event->stat.run); 97262306a36Sopenharmony_ci} 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_cistatic void perf_event__stat_round_swap(union perf_event *event, 97562306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci event->stat_round.type = bswap_64(event->stat_round.type); 97862306a36Sopenharmony_ci event->stat_round.time = bswap_64(event->stat_round.time); 97962306a36Sopenharmony_ci} 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cistatic void perf_event__time_conv_swap(union perf_event *event, 98262306a36Sopenharmony_ci bool sample_id_all __maybe_unused) 98362306a36Sopenharmony_ci{ 98462306a36Sopenharmony_ci event->time_conv.time_shift = bswap_64(event->time_conv.time_shift); 98562306a36Sopenharmony_ci event->time_conv.time_mult = bswap_64(event->time_conv.time_mult); 98662306a36Sopenharmony_ci event->time_conv.time_zero = bswap_64(event->time_conv.time_zero); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci if (event_contains(event->time_conv, time_cycles)) { 98962306a36Sopenharmony_ci event->time_conv.time_cycles = bswap_64(event->time_conv.time_cycles); 99062306a36Sopenharmony_ci event->time_conv.time_mask = bswap_64(event->time_conv.time_mask); 99162306a36Sopenharmony_ci } 99262306a36Sopenharmony_ci} 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_citypedef void (*perf_event__swap_op)(union perf_event *event, 99562306a36Sopenharmony_ci bool sample_id_all); 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_cistatic perf_event__swap_op perf_event__swap_ops[] = { 99862306a36Sopenharmony_ci [PERF_RECORD_MMAP] = perf_event__mmap_swap, 99962306a36Sopenharmony_ci [PERF_RECORD_MMAP2] = perf_event__mmap2_swap, 100062306a36Sopenharmony_ci [PERF_RECORD_COMM] = perf_event__comm_swap, 100162306a36Sopenharmony_ci [PERF_RECORD_FORK] = perf_event__task_swap, 100262306a36Sopenharmony_ci [PERF_RECORD_EXIT] = perf_event__task_swap, 100362306a36Sopenharmony_ci [PERF_RECORD_LOST] = perf_event__all64_swap, 100462306a36Sopenharmony_ci [PERF_RECORD_READ] = perf_event__read_swap, 100562306a36Sopenharmony_ci [PERF_RECORD_THROTTLE] = perf_event__throttle_swap, 100662306a36Sopenharmony_ci [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap, 100762306a36Sopenharmony_ci [PERF_RECORD_SAMPLE] = perf_event__all64_swap, 100862306a36Sopenharmony_ci [PERF_RECORD_AUX] = perf_event__aux_swap, 100962306a36Sopenharmony_ci [PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap, 101062306a36Sopenharmony_ci [PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap, 101162306a36Sopenharmony_ci [PERF_RECORD_SWITCH] = perf_event__switch_swap, 101262306a36Sopenharmony_ci [PERF_RECORD_SWITCH_CPU_WIDE] = perf_event__switch_swap, 101362306a36Sopenharmony_ci [PERF_RECORD_NAMESPACES] = perf_event__namespaces_swap, 101462306a36Sopenharmony_ci [PERF_RECORD_CGROUP] = perf_event__cgroup_swap, 101562306a36Sopenharmony_ci [PERF_RECORD_TEXT_POKE] = perf_event__text_poke_swap, 101662306a36Sopenharmony_ci [PERF_RECORD_AUX_OUTPUT_HW_ID] = perf_event__all64_swap, 101762306a36Sopenharmony_ci [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, 101862306a36Sopenharmony_ci [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 101962306a36Sopenharmony_ci [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 102062306a36Sopenharmony_ci [PERF_RECORD_HEADER_BUILD_ID] = NULL, 102162306a36Sopenharmony_ci [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, 102262306a36Sopenharmony_ci [PERF_RECORD_AUXTRACE_INFO] = perf_event__auxtrace_info_swap, 102362306a36Sopenharmony_ci [PERF_RECORD_AUXTRACE] = perf_event__auxtrace_swap, 102462306a36Sopenharmony_ci [PERF_RECORD_AUXTRACE_ERROR] = perf_event__auxtrace_error_swap, 102562306a36Sopenharmony_ci [PERF_RECORD_THREAD_MAP] = perf_event__thread_map_swap, 102662306a36Sopenharmony_ci [PERF_RECORD_CPU_MAP] = perf_event__cpu_map_swap, 102762306a36Sopenharmony_ci [PERF_RECORD_STAT_CONFIG] = perf_event__stat_config_swap, 102862306a36Sopenharmony_ci [PERF_RECORD_STAT] = perf_event__stat_swap, 102962306a36Sopenharmony_ci [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, 103062306a36Sopenharmony_ci [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, 103162306a36Sopenharmony_ci [PERF_RECORD_TIME_CONV] = perf_event__time_conv_swap, 103262306a36Sopenharmony_ci [PERF_RECORD_HEADER_MAX] = NULL, 103362306a36Sopenharmony_ci}; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci/* 103662306a36Sopenharmony_ci * When perf record finishes a pass on every buffers, it records this pseudo 103762306a36Sopenharmony_ci * event. 103862306a36Sopenharmony_ci * We record the max timestamp t found in the pass n. 103962306a36Sopenharmony_ci * Assuming these timestamps are monotonic across cpus, we know that if 104062306a36Sopenharmony_ci * a buffer still has events with timestamps below t, they will be all 104162306a36Sopenharmony_ci * available and then read in the pass n + 1. 104262306a36Sopenharmony_ci * Hence when we start to read the pass n + 2, we can safely flush every 104362306a36Sopenharmony_ci * events with timestamps below t. 104462306a36Sopenharmony_ci * 104562306a36Sopenharmony_ci * ============ PASS n ================= 104662306a36Sopenharmony_ci * CPU 0 | CPU 1 104762306a36Sopenharmony_ci * | 104862306a36Sopenharmony_ci * cnt1 timestamps | cnt2 timestamps 104962306a36Sopenharmony_ci * 1 | 2 105062306a36Sopenharmony_ci * 2 | 3 105162306a36Sopenharmony_ci * - | 4 <--- max recorded 105262306a36Sopenharmony_ci * 105362306a36Sopenharmony_ci * ============ PASS n + 1 ============== 105462306a36Sopenharmony_ci * CPU 0 | CPU 1 105562306a36Sopenharmony_ci * | 105662306a36Sopenharmony_ci * cnt1 timestamps | cnt2 timestamps 105762306a36Sopenharmony_ci * 3 | 5 105862306a36Sopenharmony_ci * 4 | 6 105962306a36Sopenharmony_ci * 5 | 7 <---- max recorded 106062306a36Sopenharmony_ci * 106162306a36Sopenharmony_ci * Flush every events below timestamp 4 106262306a36Sopenharmony_ci * 106362306a36Sopenharmony_ci * ============ PASS n + 2 ============== 106462306a36Sopenharmony_ci * CPU 0 | CPU 1 106562306a36Sopenharmony_ci * | 106662306a36Sopenharmony_ci * cnt1 timestamps | cnt2 timestamps 106762306a36Sopenharmony_ci * 6 | 8 106862306a36Sopenharmony_ci * 7 | 9 106962306a36Sopenharmony_ci * - | 10 107062306a36Sopenharmony_ci * 107162306a36Sopenharmony_ci * Flush every events below timestamp 7 107262306a36Sopenharmony_ci * etc... 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_ciint perf_event__process_finished_round(struct perf_tool *tool __maybe_unused, 107562306a36Sopenharmony_ci union perf_event *event __maybe_unused, 107662306a36Sopenharmony_ci struct ordered_events *oe) 107762306a36Sopenharmony_ci{ 107862306a36Sopenharmony_ci if (dump_trace) 107962306a36Sopenharmony_ci fprintf(stdout, "\n"); 108062306a36Sopenharmony_ci return ordered_events__flush(oe, OE_FLUSH__ROUND); 108162306a36Sopenharmony_ci} 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ciint perf_session__queue_event(struct perf_session *s, union perf_event *event, 108462306a36Sopenharmony_ci u64 timestamp, u64 file_offset, const char *file_path) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci return ordered_events__queue(&s->ordered_events, event, timestamp, file_offset, file_path); 108762306a36Sopenharmony_ci} 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_cistatic void callchain__lbr_callstack_printf(struct perf_sample *sample) 109062306a36Sopenharmony_ci{ 109162306a36Sopenharmony_ci struct ip_callchain *callchain = sample->callchain; 109262306a36Sopenharmony_ci struct branch_stack *lbr_stack = sample->branch_stack; 109362306a36Sopenharmony_ci struct branch_entry *entries = perf_sample__branch_entries(sample); 109462306a36Sopenharmony_ci u64 kernel_callchain_nr = callchain->nr; 109562306a36Sopenharmony_ci unsigned int i; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci for (i = 0; i < kernel_callchain_nr; i++) { 109862306a36Sopenharmony_ci if (callchain->ips[i] == PERF_CONTEXT_USER) 109962306a36Sopenharmony_ci break; 110062306a36Sopenharmony_ci } 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci if ((i != kernel_callchain_nr) && lbr_stack->nr) { 110362306a36Sopenharmony_ci u64 total_nr; 110462306a36Sopenharmony_ci /* 110562306a36Sopenharmony_ci * LBR callstack can only get user call chain, 110662306a36Sopenharmony_ci * i is kernel call chain number, 110762306a36Sopenharmony_ci * 1 is PERF_CONTEXT_USER. 110862306a36Sopenharmony_ci * 110962306a36Sopenharmony_ci * The user call chain is stored in LBR registers. 111062306a36Sopenharmony_ci * LBR are pair registers. The caller is stored 111162306a36Sopenharmony_ci * in "from" register, while the callee is stored 111262306a36Sopenharmony_ci * in "to" register. 111362306a36Sopenharmony_ci * For example, there is a call stack 111462306a36Sopenharmony_ci * "A"->"B"->"C"->"D". 111562306a36Sopenharmony_ci * The LBR registers will be recorded like 111662306a36Sopenharmony_ci * "C"->"D", "B"->"C", "A"->"B". 111762306a36Sopenharmony_ci * So only the first "to" register and all "from" 111862306a36Sopenharmony_ci * registers are needed to construct the whole stack. 111962306a36Sopenharmony_ci */ 112062306a36Sopenharmony_ci total_nr = i + 1 + lbr_stack->nr + 1; 112162306a36Sopenharmony_ci kernel_callchain_nr = i + 1; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci printf("... LBR call chain: nr:%" PRIu64 "\n", total_nr); 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci for (i = 0; i < kernel_callchain_nr; i++) 112662306a36Sopenharmony_ci printf("..... %2d: %016" PRIx64 "\n", 112762306a36Sopenharmony_ci i, callchain->ips[i]); 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci printf("..... %2d: %016" PRIx64 "\n", 113062306a36Sopenharmony_ci (int)(kernel_callchain_nr), entries[0].to); 113162306a36Sopenharmony_ci for (i = 0; i < lbr_stack->nr; i++) 113262306a36Sopenharmony_ci printf("..... %2d: %016" PRIx64 "\n", 113362306a36Sopenharmony_ci (int)(i + kernel_callchain_nr + 1), entries[i].from); 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci} 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_cistatic void callchain__printf(struct evsel *evsel, 113862306a36Sopenharmony_ci struct perf_sample *sample) 113962306a36Sopenharmony_ci{ 114062306a36Sopenharmony_ci unsigned int i; 114162306a36Sopenharmony_ci struct ip_callchain *callchain = sample->callchain; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci if (evsel__has_branch_callstack(evsel)) 114462306a36Sopenharmony_ci callchain__lbr_callstack_printf(sample); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr); 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci for (i = 0; i < callchain->nr; i++) 114962306a36Sopenharmony_ci printf("..... %2d: %016" PRIx64 "\n", 115062306a36Sopenharmony_ci i, callchain->ips[i]); 115162306a36Sopenharmony_ci} 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_cistatic void branch_stack__printf(struct perf_sample *sample, bool callstack) 115462306a36Sopenharmony_ci{ 115562306a36Sopenharmony_ci struct branch_entry *entries = perf_sample__branch_entries(sample); 115662306a36Sopenharmony_ci uint64_t i; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci if (!callstack) { 115962306a36Sopenharmony_ci printf("%s: nr:%" PRIu64 "\n", "... branch stack", sample->branch_stack->nr); 116062306a36Sopenharmony_ci } else { 116162306a36Sopenharmony_ci /* the reason of adding 1 to nr is because after expanding 116262306a36Sopenharmony_ci * branch stack it generates nr + 1 callstack records. e.g., 116362306a36Sopenharmony_ci * B()->C() 116462306a36Sopenharmony_ci * A()->B() 116562306a36Sopenharmony_ci * the final callstack should be: 116662306a36Sopenharmony_ci * C() 116762306a36Sopenharmony_ci * B() 116862306a36Sopenharmony_ci * A() 116962306a36Sopenharmony_ci */ 117062306a36Sopenharmony_ci printf("%s: nr:%" PRIu64 "\n", "... branch callstack", sample->branch_stack->nr+1); 117162306a36Sopenharmony_ci } 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci for (i = 0; i < sample->branch_stack->nr; i++) { 117462306a36Sopenharmony_ci struct branch_entry *e = &entries[i]; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci if (!callstack) { 117762306a36Sopenharmony_ci printf("..... %2"PRIu64": %016" PRIx64 " -> %016" PRIx64 " %hu cycles %s%s%s%s %x %s %s\n", 117862306a36Sopenharmony_ci i, e->from, e->to, 117962306a36Sopenharmony_ci (unsigned short)e->flags.cycles, 118062306a36Sopenharmony_ci e->flags.mispred ? "M" : " ", 118162306a36Sopenharmony_ci e->flags.predicted ? "P" : " ", 118262306a36Sopenharmony_ci e->flags.abort ? "A" : " ", 118362306a36Sopenharmony_ci e->flags.in_tx ? "T" : " ", 118462306a36Sopenharmony_ci (unsigned)e->flags.reserved, 118562306a36Sopenharmony_ci get_branch_type(e), 118662306a36Sopenharmony_ci e->flags.spec ? branch_spec_desc(e->flags.spec) : ""); 118762306a36Sopenharmony_ci } else { 118862306a36Sopenharmony_ci if (i == 0) { 118962306a36Sopenharmony_ci printf("..... %2"PRIu64": %016" PRIx64 "\n" 119062306a36Sopenharmony_ci "..... %2"PRIu64": %016" PRIx64 "\n", 119162306a36Sopenharmony_ci i, e->to, i+1, e->from); 119262306a36Sopenharmony_ci } else { 119362306a36Sopenharmony_ci printf("..... %2"PRIu64": %016" PRIx64 "\n", i+1, e->from); 119462306a36Sopenharmony_ci } 119562306a36Sopenharmony_ci } 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci} 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_cistatic void regs_dump__printf(u64 mask, u64 *regs, const char *arch) 120062306a36Sopenharmony_ci{ 120162306a36Sopenharmony_ci unsigned rid, i = 0; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) { 120462306a36Sopenharmony_ci u64 val = regs[i++]; 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci printf(".... %-5s 0x%016" PRIx64 "\n", 120762306a36Sopenharmony_ci perf_reg_name(rid, arch), val); 120862306a36Sopenharmony_ci } 120962306a36Sopenharmony_ci} 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_cistatic const char *regs_abi[] = { 121262306a36Sopenharmony_ci [PERF_SAMPLE_REGS_ABI_NONE] = "none", 121362306a36Sopenharmony_ci [PERF_SAMPLE_REGS_ABI_32] = "32-bit", 121462306a36Sopenharmony_ci [PERF_SAMPLE_REGS_ABI_64] = "64-bit", 121562306a36Sopenharmony_ci}; 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cistatic inline const char *regs_dump_abi(struct regs_dump *d) 121862306a36Sopenharmony_ci{ 121962306a36Sopenharmony_ci if (d->abi > PERF_SAMPLE_REGS_ABI_64) 122062306a36Sopenharmony_ci return "unknown"; 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci return regs_abi[d->abi]; 122362306a36Sopenharmony_ci} 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_cistatic void regs__printf(const char *type, struct regs_dump *regs, const char *arch) 122662306a36Sopenharmony_ci{ 122762306a36Sopenharmony_ci u64 mask = regs->mask; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n", 123062306a36Sopenharmony_ci type, 123162306a36Sopenharmony_ci mask, 123262306a36Sopenharmony_ci regs_dump_abi(regs)); 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci regs_dump__printf(mask, regs->regs, arch); 123562306a36Sopenharmony_ci} 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_cistatic void regs_user__printf(struct perf_sample *sample, const char *arch) 123862306a36Sopenharmony_ci{ 123962306a36Sopenharmony_ci struct regs_dump *user_regs = &sample->user_regs; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci if (user_regs->regs) 124262306a36Sopenharmony_ci regs__printf("user", user_regs, arch); 124362306a36Sopenharmony_ci} 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_cistatic void regs_intr__printf(struct perf_sample *sample, const char *arch) 124662306a36Sopenharmony_ci{ 124762306a36Sopenharmony_ci struct regs_dump *intr_regs = &sample->intr_regs; 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci if (intr_regs->regs) 125062306a36Sopenharmony_ci regs__printf("intr", intr_regs, arch); 125162306a36Sopenharmony_ci} 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_cistatic void stack_user__printf(struct stack_dump *dump) 125462306a36Sopenharmony_ci{ 125562306a36Sopenharmony_ci printf("... ustack: size %" PRIu64 ", offset 0x%x\n", 125662306a36Sopenharmony_ci dump->size, dump->offset); 125762306a36Sopenharmony_ci} 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_cistatic void evlist__print_tstamp(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) 126062306a36Sopenharmony_ci{ 126162306a36Sopenharmony_ci u64 sample_type = __evlist__combined_sample_type(evlist); 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci if (event->header.type != PERF_RECORD_SAMPLE && 126462306a36Sopenharmony_ci !evlist__sample_id_all(evlist)) { 126562306a36Sopenharmony_ci fputs("-1 -1 ", stdout); 126662306a36Sopenharmony_ci return; 126762306a36Sopenharmony_ci } 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci if ((sample_type & PERF_SAMPLE_CPU)) 127062306a36Sopenharmony_ci printf("%u ", sample->cpu); 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_TIME) 127362306a36Sopenharmony_ci printf("%" PRIu64 " ", sample->time); 127462306a36Sopenharmony_ci} 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_cistatic void sample_read__printf(struct perf_sample *sample, u64 read_format) 127762306a36Sopenharmony_ci{ 127862306a36Sopenharmony_ci printf("... sample_read:\n"); 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 128162306a36Sopenharmony_ci printf("...... time enabled %016" PRIx64 "\n", 128262306a36Sopenharmony_ci sample->read.time_enabled); 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 128562306a36Sopenharmony_ci printf("...... time running %016" PRIx64 "\n", 128662306a36Sopenharmony_ci sample->read.time_running); 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci if (read_format & PERF_FORMAT_GROUP) { 128962306a36Sopenharmony_ci struct sample_read_value *value = sample->read.group.values; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci printf(".... group nr %" PRIu64 "\n", sample->read.group.nr); 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci sample_read_group__for_each(value, sample->read.group.nr, read_format) { 129462306a36Sopenharmony_ci printf("..... id %016" PRIx64 129562306a36Sopenharmony_ci ", value %016" PRIx64, 129662306a36Sopenharmony_ci value->id, value->value); 129762306a36Sopenharmony_ci if (read_format & PERF_FORMAT_LOST) 129862306a36Sopenharmony_ci printf(", lost %" PRIu64, value->lost); 129962306a36Sopenharmony_ci printf("\n"); 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci } else { 130262306a36Sopenharmony_ci printf("..... id %016" PRIx64 ", value %016" PRIx64, 130362306a36Sopenharmony_ci sample->read.one.id, sample->read.one.value); 130462306a36Sopenharmony_ci if (read_format & PERF_FORMAT_LOST) 130562306a36Sopenharmony_ci printf(", lost %" PRIu64, sample->read.one.lost); 130662306a36Sopenharmony_ci printf("\n"); 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci} 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_cistatic void dump_event(struct evlist *evlist, union perf_event *event, 131162306a36Sopenharmony_ci u64 file_offset, struct perf_sample *sample, 131262306a36Sopenharmony_ci const char *file_path) 131362306a36Sopenharmony_ci{ 131462306a36Sopenharmony_ci if (!dump_trace) 131562306a36Sopenharmony_ci return; 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci printf("\n%#" PRIx64 "@%s [%#x]: event: %d\n", 131862306a36Sopenharmony_ci file_offset, file_path, event->header.size, event->header.type); 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci trace_event(event); 132162306a36Sopenharmony_ci if (event->header.type == PERF_RECORD_SAMPLE && evlist->trace_event_sample_raw) 132262306a36Sopenharmony_ci evlist->trace_event_sample_raw(evlist, event, sample); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci if (sample) 132562306a36Sopenharmony_ci evlist__print_tstamp(evlist, event, sample); 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset, 132862306a36Sopenharmony_ci event->header.size, perf_event__name(event->header.type)); 132962306a36Sopenharmony_ci} 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_cichar *get_page_size_name(u64 size, char *str) 133262306a36Sopenharmony_ci{ 133362306a36Sopenharmony_ci if (!size || !unit_number__scnprintf(str, PAGE_SIZE_NAME_LEN, size)) 133462306a36Sopenharmony_ci snprintf(str, PAGE_SIZE_NAME_LEN, "%s", "N/A"); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci return str; 133762306a36Sopenharmony_ci} 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_cistatic void dump_sample(struct evsel *evsel, union perf_event *event, 134062306a36Sopenharmony_ci struct perf_sample *sample, const char *arch) 134162306a36Sopenharmony_ci{ 134262306a36Sopenharmony_ci u64 sample_type; 134362306a36Sopenharmony_ci char str[PAGE_SIZE_NAME_LEN]; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci if (!dump_trace) 134662306a36Sopenharmony_ci return; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci printf("(IP, 0x%x): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n", 134962306a36Sopenharmony_ci event->header.misc, sample->pid, sample->tid, sample->ip, 135062306a36Sopenharmony_ci sample->period, sample->addr); 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci sample_type = evsel->core.attr.sample_type; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci if (evsel__has_callchain(evsel)) 135562306a36Sopenharmony_ci callchain__printf(evsel, sample); 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci if (evsel__has_br_stack(evsel)) 135862306a36Sopenharmony_ci branch_stack__printf(sample, evsel__has_branch_callstack(evsel)); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_REGS_USER) 136162306a36Sopenharmony_ci regs_user__printf(sample, arch); 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_REGS_INTR) 136462306a36Sopenharmony_ci regs_intr__printf(sample, arch); 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_STACK_USER) 136762306a36Sopenharmony_ci stack_user__printf(&sample->user_stack); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_WEIGHT_TYPE) { 137062306a36Sopenharmony_ci printf("... weight: %" PRIu64 "", sample->weight); 137162306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_WEIGHT_STRUCT) { 137262306a36Sopenharmony_ci printf(",0x%"PRIx16"", sample->ins_lat); 137362306a36Sopenharmony_ci printf(",0x%"PRIx16"", sample->p_stage_cyc); 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci printf("\n"); 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_DATA_SRC) 137962306a36Sopenharmony_ci printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_PHYS_ADDR) 138262306a36Sopenharmony_ci printf(" .. phys_addr: 0x%"PRIx64"\n", sample->phys_addr); 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_DATA_PAGE_SIZE) 138562306a36Sopenharmony_ci printf(" .. data page size: %s\n", get_page_size_name(sample->data_page_size, str)); 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_CODE_PAGE_SIZE) 138862306a36Sopenharmony_ci printf(" .. code page size: %s\n", get_page_size_name(sample->code_page_size, str)); 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_TRANSACTION) 139162306a36Sopenharmony_ci printf("... transaction: %" PRIx64 "\n", sample->transaction); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci if (sample_type & PERF_SAMPLE_READ) 139462306a36Sopenharmony_ci sample_read__printf(sample, evsel->core.attr.read_format); 139562306a36Sopenharmony_ci} 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_cistatic void dump_read(struct evsel *evsel, union perf_event *event) 139862306a36Sopenharmony_ci{ 139962306a36Sopenharmony_ci struct perf_record_read *read_event = &event->read; 140062306a36Sopenharmony_ci u64 read_format; 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci if (!dump_trace) 140362306a36Sopenharmony_ci return; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci printf(": %d %d %s %" PRI_lu64 "\n", event->read.pid, event->read.tid, 140662306a36Sopenharmony_ci evsel__name(evsel), event->read.value); 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci if (!evsel) 140962306a36Sopenharmony_ci return; 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci read_format = evsel->core.attr.read_format; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) 141462306a36Sopenharmony_ci printf("... time enabled : %" PRI_lu64 "\n", read_event->time_enabled); 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 141762306a36Sopenharmony_ci printf("... time running : %" PRI_lu64 "\n", read_event->time_running); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (read_format & PERF_FORMAT_ID) 142062306a36Sopenharmony_ci printf("... id : %" PRI_lu64 "\n", read_event->id); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci if (read_format & PERF_FORMAT_LOST) 142362306a36Sopenharmony_ci printf("... lost : %" PRI_lu64 "\n", read_event->lost); 142462306a36Sopenharmony_ci} 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_cistatic struct machine *machines__find_for_cpumode(struct machines *machines, 142762306a36Sopenharmony_ci union perf_event *event, 142862306a36Sopenharmony_ci struct perf_sample *sample) 142962306a36Sopenharmony_ci{ 143062306a36Sopenharmony_ci if (perf_guest && 143162306a36Sopenharmony_ci ((sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || 143262306a36Sopenharmony_ci (sample->cpumode == PERF_RECORD_MISC_GUEST_USER))) { 143362306a36Sopenharmony_ci u32 pid; 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci if (sample->machine_pid) 143662306a36Sopenharmony_ci pid = sample->machine_pid; 143762306a36Sopenharmony_ci else if (event->header.type == PERF_RECORD_MMAP 143862306a36Sopenharmony_ci || event->header.type == PERF_RECORD_MMAP2) 143962306a36Sopenharmony_ci pid = event->mmap.pid; 144062306a36Sopenharmony_ci else 144162306a36Sopenharmony_ci pid = sample->pid; 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci /* 144462306a36Sopenharmony_ci * Guest code machine is created as needed and does not use 144562306a36Sopenharmony_ci * DEFAULT_GUEST_KERNEL_ID. 144662306a36Sopenharmony_ci */ 144762306a36Sopenharmony_ci if (symbol_conf.guest_code) 144862306a36Sopenharmony_ci return machines__findnew(machines, pid); 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci return machines__find_guest(machines, pid); 145162306a36Sopenharmony_ci } 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci return &machines->host; 145462306a36Sopenharmony_ci} 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_cistatic int deliver_sample_value(struct evlist *evlist, 145762306a36Sopenharmony_ci struct perf_tool *tool, 145862306a36Sopenharmony_ci union perf_event *event, 145962306a36Sopenharmony_ci struct perf_sample *sample, 146062306a36Sopenharmony_ci struct sample_read_value *v, 146162306a36Sopenharmony_ci struct machine *machine) 146262306a36Sopenharmony_ci{ 146362306a36Sopenharmony_ci struct perf_sample_id *sid = evlist__id2sid(evlist, v->id); 146462306a36Sopenharmony_ci struct evsel *evsel; 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci if (sid) { 146762306a36Sopenharmony_ci sample->id = v->id; 146862306a36Sopenharmony_ci sample->period = v->value - sid->period; 146962306a36Sopenharmony_ci sid->period = v->value; 147062306a36Sopenharmony_ci } 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci if (!sid || sid->evsel == NULL) { 147362306a36Sopenharmony_ci ++evlist->stats.nr_unknown_id; 147462306a36Sopenharmony_ci return 0; 147562306a36Sopenharmony_ci } 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci /* 147862306a36Sopenharmony_ci * There's no reason to deliver sample 147962306a36Sopenharmony_ci * for zero period, bail out. 148062306a36Sopenharmony_ci */ 148162306a36Sopenharmony_ci if (!sample->period) 148262306a36Sopenharmony_ci return 0; 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci evsel = container_of(sid->evsel, struct evsel, core); 148562306a36Sopenharmony_ci return tool->sample(tool, event, sample, evsel, machine); 148662306a36Sopenharmony_ci} 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_cistatic int deliver_sample_group(struct evlist *evlist, 148962306a36Sopenharmony_ci struct perf_tool *tool, 149062306a36Sopenharmony_ci union perf_event *event, 149162306a36Sopenharmony_ci struct perf_sample *sample, 149262306a36Sopenharmony_ci struct machine *machine, 149362306a36Sopenharmony_ci u64 read_format) 149462306a36Sopenharmony_ci{ 149562306a36Sopenharmony_ci int ret = -EINVAL; 149662306a36Sopenharmony_ci struct sample_read_value *v = sample->read.group.values; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci sample_read_group__for_each(v, sample->read.group.nr, read_format) { 149962306a36Sopenharmony_ci ret = deliver_sample_value(evlist, tool, event, sample, v, 150062306a36Sopenharmony_ci machine); 150162306a36Sopenharmony_ci if (ret) 150262306a36Sopenharmony_ci break; 150362306a36Sopenharmony_ci } 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci return ret; 150662306a36Sopenharmony_ci} 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_cistatic int evlist__deliver_sample(struct evlist *evlist, struct perf_tool *tool, 150962306a36Sopenharmony_ci union perf_event *event, struct perf_sample *sample, 151062306a36Sopenharmony_ci struct evsel *evsel, struct machine *machine) 151162306a36Sopenharmony_ci{ 151262306a36Sopenharmony_ci /* We know evsel != NULL. */ 151362306a36Sopenharmony_ci u64 sample_type = evsel->core.attr.sample_type; 151462306a36Sopenharmony_ci u64 read_format = evsel->core.attr.read_format; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci /* Standard sample delivery. */ 151762306a36Sopenharmony_ci if (!(sample_type & PERF_SAMPLE_READ)) 151862306a36Sopenharmony_ci return tool->sample(tool, event, sample, evsel, machine); 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci /* For PERF_SAMPLE_READ we have either single or group mode. */ 152162306a36Sopenharmony_ci if (read_format & PERF_FORMAT_GROUP) 152262306a36Sopenharmony_ci return deliver_sample_group(evlist, tool, event, sample, 152362306a36Sopenharmony_ci machine, read_format); 152462306a36Sopenharmony_ci else 152562306a36Sopenharmony_ci return deliver_sample_value(evlist, tool, event, sample, 152662306a36Sopenharmony_ci &sample->read.one, machine); 152762306a36Sopenharmony_ci} 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_cistatic int machines__deliver_event(struct machines *machines, 153062306a36Sopenharmony_ci struct evlist *evlist, 153162306a36Sopenharmony_ci union perf_event *event, 153262306a36Sopenharmony_ci struct perf_sample *sample, 153362306a36Sopenharmony_ci struct perf_tool *tool, u64 file_offset, 153462306a36Sopenharmony_ci const char *file_path) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci struct evsel *evsel; 153762306a36Sopenharmony_ci struct machine *machine; 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci dump_event(evlist, event, file_offset, sample, file_path); 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci evsel = evlist__id2evsel(evlist, sample->id); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci machine = machines__find_for_cpumode(machines, event, sample); 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci switch (event->header.type) { 154662306a36Sopenharmony_ci case PERF_RECORD_SAMPLE: 154762306a36Sopenharmony_ci if (evsel == NULL) { 154862306a36Sopenharmony_ci ++evlist->stats.nr_unknown_id; 154962306a36Sopenharmony_ci return 0; 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci if (machine == NULL) { 155262306a36Sopenharmony_ci ++evlist->stats.nr_unprocessable_samples; 155362306a36Sopenharmony_ci dump_sample(evsel, event, sample, perf_env__arch(NULL)); 155462306a36Sopenharmony_ci return 0; 155562306a36Sopenharmony_ci } 155662306a36Sopenharmony_ci dump_sample(evsel, event, sample, perf_env__arch(machine->env)); 155762306a36Sopenharmony_ci return evlist__deliver_sample(evlist, tool, event, sample, evsel, machine); 155862306a36Sopenharmony_ci case PERF_RECORD_MMAP: 155962306a36Sopenharmony_ci return tool->mmap(tool, event, sample, machine); 156062306a36Sopenharmony_ci case PERF_RECORD_MMAP2: 156162306a36Sopenharmony_ci if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT) 156262306a36Sopenharmony_ci ++evlist->stats.nr_proc_map_timeout; 156362306a36Sopenharmony_ci return tool->mmap2(tool, event, sample, machine); 156462306a36Sopenharmony_ci case PERF_RECORD_COMM: 156562306a36Sopenharmony_ci return tool->comm(tool, event, sample, machine); 156662306a36Sopenharmony_ci case PERF_RECORD_NAMESPACES: 156762306a36Sopenharmony_ci return tool->namespaces(tool, event, sample, machine); 156862306a36Sopenharmony_ci case PERF_RECORD_CGROUP: 156962306a36Sopenharmony_ci return tool->cgroup(tool, event, sample, machine); 157062306a36Sopenharmony_ci case PERF_RECORD_FORK: 157162306a36Sopenharmony_ci return tool->fork(tool, event, sample, machine); 157262306a36Sopenharmony_ci case PERF_RECORD_EXIT: 157362306a36Sopenharmony_ci return tool->exit(tool, event, sample, machine); 157462306a36Sopenharmony_ci case PERF_RECORD_LOST: 157562306a36Sopenharmony_ci if (tool->lost == perf_event__process_lost) 157662306a36Sopenharmony_ci evlist->stats.total_lost += event->lost.lost; 157762306a36Sopenharmony_ci return tool->lost(tool, event, sample, machine); 157862306a36Sopenharmony_ci case PERF_RECORD_LOST_SAMPLES: 157962306a36Sopenharmony_ci if (tool->lost_samples == perf_event__process_lost_samples && 158062306a36Sopenharmony_ci !(event->header.misc & PERF_RECORD_MISC_LOST_SAMPLES_BPF)) 158162306a36Sopenharmony_ci evlist->stats.total_lost_samples += event->lost_samples.lost; 158262306a36Sopenharmony_ci return tool->lost_samples(tool, event, sample, machine); 158362306a36Sopenharmony_ci case PERF_RECORD_READ: 158462306a36Sopenharmony_ci dump_read(evsel, event); 158562306a36Sopenharmony_ci return tool->read(tool, event, sample, evsel, machine); 158662306a36Sopenharmony_ci case PERF_RECORD_THROTTLE: 158762306a36Sopenharmony_ci return tool->throttle(tool, event, sample, machine); 158862306a36Sopenharmony_ci case PERF_RECORD_UNTHROTTLE: 158962306a36Sopenharmony_ci return tool->unthrottle(tool, event, sample, machine); 159062306a36Sopenharmony_ci case PERF_RECORD_AUX: 159162306a36Sopenharmony_ci if (tool->aux == perf_event__process_aux) { 159262306a36Sopenharmony_ci if (event->aux.flags & PERF_AUX_FLAG_TRUNCATED) 159362306a36Sopenharmony_ci evlist->stats.total_aux_lost += 1; 159462306a36Sopenharmony_ci if (event->aux.flags & PERF_AUX_FLAG_PARTIAL) 159562306a36Sopenharmony_ci evlist->stats.total_aux_partial += 1; 159662306a36Sopenharmony_ci if (event->aux.flags & PERF_AUX_FLAG_COLLISION) 159762306a36Sopenharmony_ci evlist->stats.total_aux_collision += 1; 159862306a36Sopenharmony_ci } 159962306a36Sopenharmony_ci return tool->aux(tool, event, sample, machine); 160062306a36Sopenharmony_ci case PERF_RECORD_ITRACE_START: 160162306a36Sopenharmony_ci return tool->itrace_start(tool, event, sample, machine); 160262306a36Sopenharmony_ci case PERF_RECORD_SWITCH: 160362306a36Sopenharmony_ci case PERF_RECORD_SWITCH_CPU_WIDE: 160462306a36Sopenharmony_ci return tool->context_switch(tool, event, sample, machine); 160562306a36Sopenharmony_ci case PERF_RECORD_KSYMBOL: 160662306a36Sopenharmony_ci return tool->ksymbol(tool, event, sample, machine); 160762306a36Sopenharmony_ci case PERF_RECORD_BPF_EVENT: 160862306a36Sopenharmony_ci return tool->bpf(tool, event, sample, machine); 160962306a36Sopenharmony_ci case PERF_RECORD_TEXT_POKE: 161062306a36Sopenharmony_ci return tool->text_poke(tool, event, sample, machine); 161162306a36Sopenharmony_ci case PERF_RECORD_AUX_OUTPUT_HW_ID: 161262306a36Sopenharmony_ci return tool->aux_output_hw_id(tool, event, sample, machine); 161362306a36Sopenharmony_ci default: 161462306a36Sopenharmony_ci ++evlist->stats.nr_unknown_events; 161562306a36Sopenharmony_ci return -1; 161662306a36Sopenharmony_ci } 161762306a36Sopenharmony_ci} 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_cistatic int perf_session__deliver_event(struct perf_session *session, 162062306a36Sopenharmony_ci union perf_event *event, 162162306a36Sopenharmony_ci struct perf_tool *tool, 162262306a36Sopenharmony_ci u64 file_offset, 162362306a36Sopenharmony_ci const char *file_path) 162462306a36Sopenharmony_ci{ 162562306a36Sopenharmony_ci struct perf_sample sample; 162662306a36Sopenharmony_ci int ret = evlist__parse_sample(session->evlist, event, &sample); 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci if (ret) { 162962306a36Sopenharmony_ci pr_err("Can't parse sample, err = %d\n", ret); 163062306a36Sopenharmony_ci return ret; 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci ret = auxtrace__process_event(session, event, &sample, tool); 163462306a36Sopenharmony_ci if (ret < 0) 163562306a36Sopenharmony_ci return ret; 163662306a36Sopenharmony_ci if (ret > 0) 163762306a36Sopenharmony_ci return 0; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci ret = machines__deliver_event(&session->machines, session->evlist, 164062306a36Sopenharmony_ci event, &sample, tool, file_offset, file_path); 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci if (dump_trace && sample.aux_sample.size) 164362306a36Sopenharmony_ci auxtrace__dump_auxtrace_sample(session, &sample); 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci return ret; 164662306a36Sopenharmony_ci} 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_cistatic s64 perf_session__process_user_event(struct perf_session *session, 164962306a36Sopenharmony_ci union perf_event *event, 165062306a36Sopenharmony_ci u64 file_offset, 165162306a36Sopenharmony_ci const char *file_path) 165262306a36Sopenharmony_ci{ 165362306a36Sopenharmony_ci struct ordered_events *oe = &session->ordered_events; 165462306a36Sopenharmony_ci struct perf_tool *tool = session->tool; 165562306a36Sopenharmony_ci struct perf_sample sample = { .time = 0, }; 165662306a36Sopenharmony_ci int fd = perf_data__fd(session->data); 165762306a36Sopenharmony_ci int err; 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci if (event->header.type != PERF_RECORD_COMPRESSED || 166062306a36Sopenharmony_ci tool->compressed == perf_session__process_compressed_event_stub) 166162306a36Sopenharmony_ci dump_event(session->evlist, event, file_offset, &sample, file_path); 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci /* These events are processed right away */ 166462306a36Sopenharmony_ci switch (event->header.type) { 166562306a36Sopenharmony_ci case PERF_RECORD_HEADER_ATTR: 166662306a36Sopenharmony_ci err = tool->attr(tool, event, &session->evlist); 166762306a36Sopenharmony_ci if (err == 0) { 166862306a36Sopenharmony_ci perf_session__set_id_hdr_size(session); 166962306a36Sopenharmony_ci perf_session__set_comm_exec(session); 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci return err; 167262306a36Sopenharmony_ci case PERF_RECORD_EVENT_UPDATE: 167362306a36Sopenharmony_ci return tool->event_update(tool, event, &session->evlist); 167462306a36Sopenharmony_ci case PERF_RECORD_HEADER_EVENT_TYPE: 167562306a36Sopenharmony_ci /* 167662306a36Sopenharmony_ci * Deprecated, but we need to handle it for sake 167762306a36Sopenharmony_ci * of old data files create in pipe mode. 167862306a36Sopenharmony_ci */ 167962306a36Sopenharmony_ci return 0; 168062306a36Sopenharmony_ci case PERF_RECORD_HEADER_TRACING_DATA: 168162306a36Sopenharmony_ci /* 168262306a36Sopenharmony_ci * Setup for reading amidst mmap, but only when we 168362306a36Sopenharmony_ci * are in 'file' mode. The 'pipe' fd is in proper 168462306a36Sopenharmony_ci * place already. 168562306a36Sopenharmony_ci */ 168662306a36Sopenharmony_ci if (!perf_data__is_pipe(session->data)) 168762306a36Sopenharmony_ci lseek(fd, file_offset, SEEK_SET); 168862306a36Sopenharmony_ci return tool->tracing_data(session, event); 168962306a36Sopenharmony_ci case PERF_RECORD_HEADER_BUILD_ID: 169062306a36Sopenharmony_ci return tool->build_id(session, event); 169162306a36Sopenharmony_ci case PERF_RECORD_FINISHED_ROUND: 169262306a36Sopenharmony_ci return tool->finished_round(tool, event, oe); 169362306a36Sopenharmony_ci case PERF_RECORD_ID_INDEX: 169462306a36Sopenharmony_ci return tool->id_index(session, event); 169562306a36Sopenharmony_ci case PERF_RECORD_AUXTRACE_INFO: 169662306a36Sopenharmony_ci return tool->auxtrace_info(session, event); 169762306a36Sopenharmony_ci case PERF_RECORD_AUXTRACE: 169862306a36Sopenharmony_ci /* 169962306a36Sopenharmony_ci * Setup for reading amidst mmap, but only when we 170062306a36Sopenharmony_ci * are in 'file' mode. The 'pipe' fd is in proper 170162306a36Sopenharmony_ci * place already. 170262306a36Sopenharmony_ci */ 170362306a36Sopenharmony_ci if (!perf_data__is_pipe(session->data)) 170462306a36Sopenharmony_ci lseek(fd, file_offset + event->header.size, SEEK_SET); 170562306a36Sopenharmony_ci return tool->auxtrace(session, event); 170662306a36Sopenharmony_ci case PERF_RECORD_AUXTRACE_ERROR: 170762306a36Sopenharmony_ci perf_session__auxtrace_error_inc(session, event); 170862306a36Sopenharmony_ci return tool->auxtrace_error(session, event); 170962306a36Sopenharmony_ci case PERF_RECORD_THREAD_MAP: 171062306a36Sopenharmony_ci return tool->thread_map(session, event); 171162306a36Sopenharmony_ci case PERF_RECORD_CPU_MAP: 171262306a36Sopenharmony_ci return tool->cpu_map(session, event); 171362306a36Sopenharmony_ci case PERF_RECORD_STAT_CONFIG: 171462306a36Sopenharmony_ci return tool->stat_config(session, event); 171562306a36Sopenharmony_ci case PERF_RECORD_STAT: 171662306a36Sopenharmony_ci return tool->stat(session, event); 171762306a36Sopenharmony_ci case PERF_RECORD_STAT_ROUND: 171862306a36Sopenharmony_ci return tool->stat_round(session, event); 171962306a36Sopenharmony_ci case PERF_RECORD_TIME_CONV: 172062306a36Sopenharmony_ci session->time_conv = event->time_conv; 172162306a36Sopenharmony_ci return tool->time_conv(session, event); 172262306a36Sopenharmony_ci case PERF_RECORD_HEADER_FEATURE: 172362306a36Sopenharmony_ci return tool->feature(session, event); 172462306a36Sopenharmony_ci case PERF_RECORD_COMPRESSED: 172562306a36Sopenharmony_ci err = tool->compressed(session, event, file_offset, file_path); 172662306a36Sopenharmony_ci if (err) 172762306a36Sopenharmony_ci dump_event(session->evlist, event, file_offset, &sample, file_path); 172862306a36Sopenharmony_ci return err; 172962306a36Sopenharmony_ci case PERF_RECORD_FINISHED_INIT: 173062306a36Sopenharmony_ci return tool->finished_init(session, event); 173162306a36Sopenharmony_ci default: 173262306a36Sopenharmony_ci return -EINVAL; 173362306a36Sopenharmony_ci } 173462306a36Sopenharmony_ci} 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ciint perf_session__deliver_synth_event(struct perf_session *session, 173762306a36Sopenharmony_ci union perf_event *event, 173862306a36Sopenharmony_ci struct perf_sample *sample) 173962306a36Sopenharmony_ci{ 174062306a36Sopenharmony_ci struct evlist *evlist = session->evlist; 174162306a36Sopenharmony_ci struct perf_tool *tool = session->tool; 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci events_stats__inc(&evlist->stats, event->header.type); 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci if (event->header.type >= PERF_RECORD_USER_TYPE_START) 174662306a36Sopenharmony_ci return perf_session__process_user_event(session, event, 0, NULL); 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0, NULL); 174962306a36Sopenharmony_ci} 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_cistatic void event_swap(union perf_event *event, bool sample_id_all) 175262306a36Sopenharmony_ci{ 175362306a36Sopenharmony_ci perf_event__swap_op swap; 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci swap = perf_event__swap_ops[event->header.type]; 175662306a36Sopenharmony_ci if (swap) 175762306a36Sopenharmony_ci swap(event, sample_id_all); 175862306a36Sopenharmony_ci} 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ciint perf_session__peek_event(struct perf_session *session, off_t file_offset, 176162306a36Sopenharmony_ci void *buf, size_t buf_sz, 176262306a36Sopenharmony_ci union perf_event **event_ptr, 176362306a36Sopenharmony_ci struct perf_sample *sample) 176462306a36Sopenharmony_ci{ 176562306a36Sopenharmony_ci union perf_event *event; 176662306a36Sopenharmony_ci size_t hdr_sz, rest; 176762306a36Sopenharmony_ci int fd; 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci if (session->one_mmap && !session->header.needs_swap) { 177062306a36Sopenharmony_ci event = file_offset - session->one_mmap_offset + 177162306a36Sopenharmony_ci session->one_mmap_addr; 177262306a36Sopenharmony_ci goto out_parse_sample; 177362306a36Sopenharmony_ci } 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci if (perf_data__is_pipe(session->data)) 177662306a36Sopenharmony_ci return -1; 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci fd = perf_data__fd(session->data); 177962306a36Sopenharmony_ci hdr_sz = sizeof(struct perf_event_header); 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci if (buf_sz < hdr_sz) 178262306a36Sopenharmony_ci return -1; 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || 178562306a36Sopenharmony_ci readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz) 178662306a36Sopenharmony_ci return -1; 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci event = (union perf_event *)buf; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci if (session->header.needs_swap) 179162306a36Sopenharmony_ci perf_event_header__bswap(&event->header); 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci if (event->header.size < hdr_sz || event->header.size > buf_sz) 179462306a36Sopenharmony_ci return -1; 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci buf += hdr_sz; 179762306a36Sopenharmony_ci rest = event->header.size - hdr_sz; 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci if (readn(fd, buf, rest) != (ssize_t)rest) 180062306a36Sopenharmony_ci return -1; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci if (session->header.needs_swap) 180362306a36Sopenharmony_ci event_swap(event, evlist__sample_id_all(session->evlist)); 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ciout_parse_sample: 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci if (sample && event->header.type < PERF_RECORD_USER_TYPE_START && 180862306a36Sopenharmony_ci evlist__parse_sample(session->evlist, event, sample)) 180962306a36Sopenharmony_ci return -1; 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci *event_ptr = event; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci return 0; 181462306a36Sopenharmony_ci} 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ciint perf_session__peek_events(struct perf_session *session, u64 offset, 181762306a36Sopenharmony_ci u64 size, peek_events_cb_t cb, void *data) 181862306a36Sopenharmony_ci{ 181962306a36Sopenharmony_ci u64 max_offset = offset + size; 182062306a36Sopenharmony_ci char buf[PERF_SAMPLE_MAX_SIZE]; 182162306a36Sopenharmony_ci union perf_event *event; 182262306a36Sopenharmony_ci int err; 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci do { 182562306a36Sopenharmony_ci err = perf_session__peek_event(session, offset, buf, 182662306a36Sopenharmony_ci PERF_SAMPLE_MAX_SIZE, &event, 182762306a36Sopenharmony_ci NULL); 182862306a36Sopenharmony_ci if (err) 182962306a36Sopenharmony_ci return err; 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci err = cb(session, event, offset, data); 183262306a36Sopenharmony_ci if (err) 183362306a36Sopenharmony_ci return err; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci offset += event->header.size; 183662306a36Sopenharmony_ci if (event->header.type == PERF_RECORD_AUXTRACE) 183762306a36Sopenharmony_ci offset += event->auxtrace.size; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci } while (offset < max_offset); 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci return err; 184262306a36Sopenharmony_ci} 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_cistatic s64 perf_session__process_event(struct perf_session *session, 184562306a36Sopenharmony_ci union perf_event *event, u64 file_offset, 184662306a36Sopenharmony_ci const char *file_path) 184762306a36Sopenharmony_ci{ 184862306a36Sopenharmony_ci struct evlist *evlist = session->evlist; 184962306a36Sopenharmony_ci struct perf_tool *tool = session->tool; 185062306a36Sopenharmony_ci int ret; 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci if (session->header.needs_swap) 185362306a36Sopenharmony_ci event_swap(event, evlist__sample_id_all(evlist)); 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci if (event->header.type >= PERF_RECORD_HEADER_MAX) 185662306a36Sopenharmony_ci return -EINVAL; 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci events_stats__inc(&evlist->stats, event->header.type); 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci if (event->header.type >= PERF_RECORD_USER_TYPE_START) 186162306a36Sopenharmony_ci return perf_session__process_user_event(session, event, file_offset, file_path); 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci if (tool->ordered_events) { 186462306a36Sopenharmony_ci u64 timestamp = -1ULL; 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci ret = evlist__parse_sample_timestamp(evlist, event, ×tamp); 186762306a36Sopenharmony_ci if (ret && ret != -1) 186862306a36Sopenharmony_ci return ret; 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ci ret = perf_session__queue_event(session, event, timestamp, file_offset, file_path); 187162306a36Sopenharmony_ci if (ret != -ETIME) 187262306a36Sopenharmony_ci return ret; 187362306a36Sopenharmony_ci } 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci return perf_session__deliver_event(session, event, tool, file_offset, file_path); 187662306a36Sopenharmony_ci} 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_civoid perf_event_header__bswap(struct perf_event_header *hdr) 187962306a36Sopenharmony_ci{ 188062306a36Sopenharmony_ci hdr->type = bswap_32(hdr->type); 188162306a36Sopenharmony_ci hdr->misc = bswap_16(hdr->misc); 188262306a36Sopenharmony_ci hdr->size = bswap_16(hdr->size); 188362306a36Sopenharmony_ci} 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_cistruct thread *perf_session__findnew(struct perf_session *session, pid_t pid) 188662306a36Sopenharmony_ci{ 188762306a36Sopenharmony_ci return machine__findnew_thread(&session->machines.host, -1, pid); 188862306a36Sopenharmony_ci} 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ciint perf_session__register_idle_thread(struct perf_session *session) 189162306a36Sopenharmony_ci{ 189262306a36Sopenharmony_ci struct thread *thread = machine__idle_thread(&session->machines.host); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci /* machine__idle_thread() got the thread, so put it */ 189562306a36Sopenharmony_ci thread__put(thread); 189662306a36Sopenharmony_ci return thread ? 0 : -1; 189762306a36Sopenharmony_ci} 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_cistatic void 190062306a36Sopenharmony_ciperf_session__warn_order(const struct perf_session *session) 190162306a36Sopenharmony_ci{ 190262306a36Sopenharmony_ci const struct ordered_events *oe = &session->ordered_events; 190362306a36Sopenharmony_ci struct evsel *evsel; 190462306a36Sopenharmony_ci bool should_warn = true; 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci evlist__for_each_entry(session->evlist, evsel) { 190762306a36Sopenharmony_ci if (evsel->core.attr.write_backward) 190862306a36Sopenharmony_ci should_warn = false; 190962306a36Sopenharmony_ci } 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci if (!should_warn) 191262306a36Sopenharmony_ci return; 191362306a36Sopenharmony_ci if (oe->nr_unordered_events != 0) 191462306a36Sopenharmony_ci ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events); 191562306a36Sopenharmony_ci} 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_cistatic void perf_session__warn_about_errors(const struct perf_session *session) 191862306a36Sopenharmony_ci{ 191962306a36Sopenharmony_ci const struct events_stats *stats = &session->evlist->stats; 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci if (session->tool->lost == perf_event__process_lost && 192262306a36Sopenharmony_ci stats->nr_events[PERF_RECORD_LOST] != 0) { 192362306a36Sopenharmony_ci ui__warning("Processed %d events and lost %d chunks!\n\n" 192462306a36Sopenharmony_ci "Check IO/CPU overload!\n\n", 192562306a36Sopenharmony_ci stats->nr_events[0], 192662306a36Sopenharmony_ci stats->nr_events[PERF_RECORD_LOST]); 192762306a36Sopenharmony_ci } 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci if (session->tool->lost_samples == perf_event__process_lost_samples) { 193062306a36Sopenharmony_ci double drop_rate; 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_ci drop_rate = (double)stats->total_lost_samples / 193362306a36Sopenharmony_ci (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); 193462306a36Sopenharmony_ci if (drop_rate > 0.05) { 193562306a36Sopenharmony_ci ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n", 193662306a36Sopenharmony_ci stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, 193762306a36Sopenharmony_ci drop_rate * 100.0); 193862306a36Sopenharmony_ci } 193962306a36Sopenharmony_ci } 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci if (session->tool->aux == perf_event__process_aux && 194262306a36Sopenharmony_ci stats->total_aux_lost != 0) { 194362306a36Sopenharmony_ci ui__warning("AUX data lost %" PRIu64 " times out of %u!\n\n", 194462306a36Sopenharmony_ci stats->total_aux_lost, 194562306a36Sopenharmony_ci stats->nr_events[PERF_RECORD_AUX]); 194662306a36Sopenharmony_ci } 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci if (session->tool->aux == perf_event__process_aux && 194962306a36Sopenharmony_ci stats->total_aux_partial != 0) { 195062306a36Sopenharmony_ci bool vmm_exclusive = false; 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_ci (void)sysfs__read_bool("module/kvm_intel/parameters/vmm_exclusive", 195362306a36Sopenharmony_ci &vmm_exclusive); 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci ui__warning("AUX data had gaps in it %" PRIu64 " times out of %u!\n\n" 195662306a36Sopenharmony_ci "Are you running a KVM guest in the background?%s\n\n", 195762306a36Sopenharmony_ci stats->total_aux_partial, 195862306a36Sopenharmony_ci stats->nr_events[PERF_RECORD_AUX], 195962306a36Sopenharmony_ci vmm_exclusive ? 196062306a36Sopenharmony_ci "\nReloading kvm_intel module with vmm_exclusive=0\n" 196162306a36Sopenharmony_ci "will reduce the gaps to only guest's timeslices." : 196262306a36Sopenharmony_ci ""); 196362306a36Sopenharmony_ci } 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci if (session->tool->aux == perf_event__process_aux && 196662306a36Sopenharmony_ci stats->total_aux_collision != 0) { 196762306a36Sopenharmony_ci ui__warning("AUX data detected collision %" PRIu64 " times out of %u!\n\n", 196862306a36Sopenharmony_ci stats->total_aux_collision, 196962306a36Sopenharmony_ci stats->nr_events[PERF_RECORD_AUX]); 197062306a36Sopenharmony_ci } 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci if (stats->nr_unknown_events != 0) { 197362306a36Sopenharmony_ci ui__warning("Found %u unknown events!\n\n" 197462306a36Sopenharmony_ci "Is this an older tool processing a perf.data " 197562306a36Sopenharmony_ci "file generated by a more recent tool?\n\n" 197662306a36Sopenharmony_ci "If that is not the case, consider " 197762306a36Sopenharmony_ci "reporting to linux-kernel@vger.kernel.org.\n\n", 197862306a36Sopenharmony_ci stats->nr_unknown_events); 197962306a36Sopenharmony_ci } 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci if (stats->nr_unknown_id != 0) { 198262306a36Sopenharmony_ci ui__warning("%u samples with id not present in the header\n", 198362306a36Sopenharmony_ci stats->nr_unknown_id); 198462306a36Sopenharmony_ci } 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_ci if (stats->nr_invalid_chains != 0) { 198762306a36Sopenharmony_ci ui__warning("Found invalid callchains!\n\n" 198862306a36Sopenharmony_ci "%u out of %u events were discarded for this reason.\n\n" 198962306a36Sopenharmony_ci "Consider reporting to linux-kernel@vger.kernel.org.\n\n", 199062306a36Sopenharmony_ci stats->nr_invalid_chains, 199162306a36Sopenharmony_ci stats->nr_events[PERF_RECORD_SAMPLE]); 199262306a36Sopenharmony_ci } 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci if (stats->nr_unprocessable_samples != 0) { 199562306a36Sopenharmony_ci ui__warning("%u unprocessable samples recorded.\n" 199662306a36Sopenharmony_ci "Do you have a KVM guest running and not using 'perf kvm'?\n", 199762306a36Sopenharmony_ci stats->nr_unprocessable_samples); 199862306a36Sopenharmony_ci } 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci perf_session__warn_order(session); 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci events_stats__auxtrace_error_warn(stats); 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci if (stats->nr_proc_map_timeout != 0) { 200562306a36Sopenharmony_ci ui__warning("%d map information files for pre-existing threads were\n" 200662306a36Sopenharmony_ci "not processed, if there are samples for addresses they\n" 200762306a36Sopenharmony_ci "will not be resolved, you may find out which are these\n" 200862306a36Sopenharmony_ci "threads by running with -v and redirecting the output\n" 200962306a36Sopenharmony_ci "to a file.\n" 201062306a36Sopenharmony_ci "The time limit to process proc map is too short?\n" 201162306a36Sopenharmony_ci "Increase it by --proc-map-timeout\n", 201262306a36Sopenharmony_ci stats->nr_proc_map_timeout); 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci} 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_cistatic int perf_session__flush_thread_stack(struct thread *thread, 201762306a36Sopenharmony_ci void *p __maybe_unused) 201862306a36Sopenharmony_ci{ 201962306a36Sopenharmony_ci return thread_stack__flush(thread); 202062306a36Sopenharmony_ci} 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_cistatic int perf_session__flush_thread_stacks(struct perf_session *session) 202362306a36Sopenharmony_ci{ 202462306a36Sopenharmony_ci return machines__for_each_thread(&session->machines, 202562306a36Sopenharmony_ci perf_session__flush_thread_stack, 202662306a36Sopenharmony_ci NULL); 202762306a36Sopenharmony_ci} 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_civolatile sig_atomic_t session_done; 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_cistatic int __perf_session__process_decomp_events(struct perf_session *session); 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_cistatic int __perf_session__process_pipe_events(struct perf_session *session) 203462306a36Sopenharmony_ci{ 203562306a36Sopenharmony_ci struct ordered_events *oe = &session->ordered_events; 203662306a36Sopenharmony_ci struct perf_tool *tool = session->tool; 203762306a36Sopenharmony_ci union perf_event *event; 203862306a36Sopenharmony_ci uint32_t size, cur_size = 0; 203962306a36Sopenharmony_ci void *buf = NULL; 204062306a36Sopenharmony_ci s64 skip = 0; 204162306a36Sopenharmony_ci u64 head; 204262306a36Sopenharmony_ci ssize_t err; 204362306a36Sopenharmony_ci void *p; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci perf_tool__fill_defaults(tool); 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci head = 0; 204862306a36Sopenharmony_ci cur_size = sizeof(union perf_event); 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci buf = malloc(cur_size); 205162306a36Sopenharmony_ci if (!buf) 205262306a36Sopenharmony_ci return -errno; 205362306a36Sopenharmony_ci ordered_events__set_copy_on_queue(oe, true); 205462306a36Sopenharmony_cimore: 205562306a36Sopenharmony_ci event = buf; 205662306a36Sopenharmony_ci err = perf_data__read(session->data, event, 205762306a36Sopenharmony_ci sizeof(struct perf_event_header)); 205862306a36Sopenharmony_ci if (err <= 0) { 205962306a36Sopenharmony_ci if (err == 0) 206062306a36Sopenharmony_ci goto done; 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci pr_err("failed to read event header\n"); 206362306a36Sopenharmony_ci goto out_err; 206462306a36Sopenharmony_ci } 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci if (session->header.needs_swap) 206762306a36Sopenharmony_ci perf_event_header__bswap(&event->header); 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci size = event->header.size; 207062306a36Sopenharmony_ci if (size < sizeof(struct perf_event_header)) { 207162306a36Sopenharmony_ci pr_err("bad event header size\n"); 207262306a36Sopenharmony_ci goto out_err; 207362306a36Sopenharmony_ci } 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci if (size > cur_size) { 207662306a36Sopenharmony_ci void *new = realloc(buf, size); 207762306a36Sopenharmony_ci if (!new) { 207862306a36Sopenharmony_ci pr_err("failed to allocate memory to read event\n"); 207962306a36Sopenharmony_ci goto out_err; 208062306a36Sopenharmony_ci } 208162306a36Sopenharmony_ci buf = new; 208262306a36Sopenharmony_ci cur_size = size; 208362306a36Sopenharmony_ci event = buf; 208462306a36Sopenharmony_ci } 208562306a36Sopenharmony_ci p = event; 208662306a36Sopenharmony_ci p += sizeof(struct perf_event_header); 208762306a36Sopenharmony_ci 208862306a36Sopenharmony_ci if (size - sizeof(struct perf_event_header)) { 208962306a36Sopenharmony_ci err = perf_data__read(session->data, p, 209062306a36Sopenharmony_ci size - sizeof(struct perf_event_header)); 209162306a36Sopenharmony_ci if (err <= 0) { 209262306a36Sopenharmony_ci if (err == 0) { 209362306a36Sopenharmony_ci pr_err("unexpected end of event stream\n"); 209462306a36Sopenharmony_ci goto done; 209562306a36Sopenharmony_ci } 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci pr_err("failed to read event data\n"); 209862306a36Sopenharmony_ci goto out_err; 209962306a36Sopenharmony_ci } 210062306a36Sopenharmony_ci } 210162306a36Sopenharmony_ci 210262306a36Sopenharmony_ci if ((skip = perf_session__process_event(session, event, head, "pipe")) < 0) { 210362306a36Sopenharmony_ci pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 210462306a36Sopenharmony_ci head, event->header.size, event->header.type); 210562306a36Sopenharmony_ci err = -EINVAL; 210662306a36Sopenharmony_ci goto out_err; 210762306a36Sopenharmony_ci } 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci head += size; 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci if (skip > 0) 211262306a36Sopenharmony_ci head += skip; 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci err = __perf_session__process_decomp_events(session); 211562306a36Sopenharmony_ci if (err) 211662306a36Sopenharmony_ci goto out_err; 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci if (!session_done()) 211962306a36Sopenharmony_ci goto more; 212062306a36Sopenharmony_cidone: 212162306a36Sopenharmony_ci /* do the final flush for ordered samples */ 212262306a36Sopenharmony_ci err = ordered_events__flush(oe, OE_FLUSH__FINAL); 212362306a36Sopenharmony_ci if (err) 212462306a36Sopenharmony_ci goto out_err; 212562306a36Sopenharmony_ci err = auxtrace__flush_events(session, tool); 212662306a36Sopenharmony_ci if (err) 212762306a36Sopenharmony_ci goto out_err; 212862306a36Sopenharmony_ci err = perf_session__flush_thread_stacks(session); 212962306a36Sopenharmony_ciout_err: 213062306a36Sopenharmony_ci free(buf); 213162306a36Sopenharmony_ci if (!tool->no_warn) 213262306a36Sopenharmony_ci perf_session__warn_about_errors(session); 213362306a36Sopenharmony_ci ordered_events__free(&session->ordered_events); 213462306a36Sopenharmony_ci auxtrace__free_events(session); 213562306a36Sopenharmony_ci return err; 213662306a36Sopenharmony_ci} 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_cistatic union perf_event * 213962306a36Sopenharmony_ciprefetch_event(char *buf, u64 head, size_t mmap_size, 214062306a36Sopenharmony_ci bool needs_swap, union perf_event *error) 214162306a36Sopenharmony_ci{ 214262306a36Sopenharmony_ci union perf_event *event; 214362306a36Sopenharmony_ci u16 event_size; 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci /* 214662306a36Sopenharmony_ci * Ensure we have enough space remaining to read 214762306a36Sopenharmony_ci * the size of the event in the headers. 214862306a36Sopenharmony_ci */ 214962306a36Sopenharmony_ci if (head + sizeof(event->header) > mmap_size) 215062306a36Sopenharmony_ci return NULL; 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci event = (union perf_event *)(buf + head); 215362306a36Sopenharmony_ci if (needs_swap) 215462306a36Sopenharmony_ci perf_event_header__bswap(&event->header); 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci event_size = event->header.size; 215762306a36Sopenharmony_ci if (head + event_size <= mmap_size) 215862306a36Sopenharmony_ci return event; 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci /* We're not fetching the event so swap back again */ 216162306a36Sopenharmony_ci if (needs_swap) 216262306a36Sopenharmony_ci perf_event_header__bswap(&event->header); 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_ci /* Check if the event fits into the next mmapped buf. */ 216562306a36Sopenharmony_ci if (event_size <= mmap_size - head % page_size) { 216662306a36Sopenharmony_ci /* Remap buf and fetch again. */ 216762306a36Sopenharmony_ci return NULL; 216862306a36Sopenharmony_ci } 216962306a36Sopenharmony_ci 217062306a36Sopenharmony_ci /* Invalid input. Event size should never exceed mmap_size. */ 217162306a36Sopenharmony_ci pr_debug("%s: head=%#" PRIx64 " event->header.size=%#x, mmap_size=%#zx:" 217262306a36Sopenharmony_ci " fuzzed or compressed perf.data?\n", __func__, head, event_size, mmap_size); 217362306a36Sopenharmony_ci 217462306a36Sopenharmony_ci return error; 217562306a36Sopenharmony_ci} 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_cistatic union perf_event * 217862306a36Sopenharmony_cifetch_mmaped_event(u64 head, size_t mmap_size, char *buf, bool needs_swap) 217962306a36Sopenharmony_ci{ 218062306a36Sopenharmony_ci return prefetch_event(buf, head, mmap_size, needs_swap, ERR_PTR(-EINVAL)); 218162306a36Sopenharmony_ci} 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_cistatic union perf_event * 218462306a36Sopenharmony_cifetch_decomp_event(u64 head, size_t mmap_size, char *buf, bool needs_swap) 218562306a36Sopenharmony_ci{ 218662306a36Sopenharmony_ci return prefetch_event(buf, head, mmap_size, needs_swap, NULL); 218762306a36Sopenharmony_ci} 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_cistatic int __perf_session__process_decomp_events(struct perf_session *session) 219062306a36Sopenharmony_ci{ 219162306a36Sopenharmony_ci s64 skip; 219262306a36Sopenharmony_ci u64 size; 219362306a36Sopenharmony_ci struct decomp *decomp = session->active_decomp->decomp_last; 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci if (!decomp) 219662306a36Sopenharmony_ci return 0; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci while (decomp->head < decomp->size && !session_done()) { 219962306a36Sopenharmony_ci union perf_event *event = fetch_decomp_event(decomp->head, decomp->size, decomp->data, 220062306a36Sopenharmony_ci session->header.needs_swap); 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci if (!event) 220362306a36Sopenharmony_ci break; 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci size = event->header.size; 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci if (size < sizeof(struct perf_event_header) || 220862306a36Sopenharmony_ci (skip = perf_session__process_event(session, event, decomp->file_pos, 220962306a36Sopenharmony_ci decomp->file_path)) < 0) { 221062306a36Sopenharmony_ci pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 221162306a36Sopenharmony_ci decomp->file_pos + decomp->head, event->header.size, event->header.type); 221262306a36Sopenharmony_ci return -EINVAL; 221362306a36Sopenharmony_ci } 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci if (skip) 221662306a36Sopenharmony_ci size += skip; 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_ci decomp->head += size; 221962306a36Sopenharmony_ci } 222062306a36Sopenharmony_ci 222162306a36Sopenharmony_ci return 0; 222262306a36Sopenharmony_ci} 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci/* 222562306a36Sopenharmony_ci * On 64bit we can mmap the data file in one go. No need for tiny mmap 222662306a36Sopenharmony_ci * slices. On 32bit we use 32MB. 222762306a36Sopenharmony_ci */ 222862306a36Sopenharmony_ci#if BITS_PER_LONG == 64 222962306a36Sopenharmony_ci#define MMAP_SIZE ULLONG_MAX 223062306a36Sopenharmony_ci#define NUM_MMAPS 1 223162306a36Sopenharmony_ci#else 223262306a36Sopenharmony_ci#define MMAP_SIZE (32 * 1024 * 1024ULL) 223362306a36Sopenharmony_ci#define NUM_MMAPS 128 223462306a36Sopenharmony_ci#endif 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_cistruct reader; 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_citypedef s64 (*reader_cb_t)(struct perf_session *session, 223962306a36Sopenharmony_ci union perf_event *event, 224062306a36Sopenharmony_ci u64 file_offset, 224162306a36Sopenharmony_ci const char *file_path); 224262306a36Sopenharmony_ci 224362306a36Sopenharmony_cistruct reader { 224462306a36Sopenharmony_ci int fd; 224562306a36Sopenharmony_ci const char *path; 224662306a36Sopenharmony_ci u64 data_size; 224762306a36Sopenharmony_ci u64 data_offset; 224862306a36Sopenharmony_ci reader_cb_t process; 224962306a36Sopenharmony_ci bool in_place_update; 225062306a36Sopenharmony_ci char *mmaps[NUM_MMAPS]; 225162306a36Sopenharmony_ci size_t mmap_size; 225262306a36Sopenharmony_ci int mmap_idx; 225362306a36Sopenharmony_ci char *mmap_cur; 225462306a36Sopenharmony_ci u64 file_pos; 225562306a36Sopenharmony_ci u64 file_offset; 225662306a36Sopenharmony_ci u64 head; 225762306a36Sopenharmony_ci u64 size; 225862306a36Sopenharmony_ci bool done; 225962306a36Sopenharmony_ci struct zstd_data zstd_data; 226062306a36Sopenharmony_ci struct decomp_data decomp_data; 226162306a36Sopenharmony_ci}; 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_cistatic int 226462306a36Sopenharmony_cireader__init(struct reader *rd, bool *one_mmap) 226562306a36Sopenharmony_ci{ 226662306a36Sopenharmony_ci u64 data_size = rd->data_size; 226762306a36Sopenharmony_ci char **mmaps = rd->mmaps; 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ci rd->head = rd->data_offset; 227062306a36Sopenharmony_ci data_size += rd->data_offset; 227162306a36Sopenharmony_ci 227262306a36Sopenharmony_ci rd->mmap_size = MMAP_SIZE; 227362306a36Sopenharmony_ci if (rd->mmap_size > data_size) { 227462306a36Sopenharmony_ci rd->mmap_size = data_size; 227562306a36Sopenharmony_ci if (one_mmap) 227662306a36Sopenharmony_ci *one_mmap = true; 227762306a36Sopenharmony_ci } 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_ci memset(mmaps, 0, sizeof(rd->mmaps)); 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci if (zstd_init(&rd->zstd_data, 0)) 228262306a36Sopenharmony_ci return -1; 228362306a36Sopenharmony_ci rd->decomp_data.zstd_decomp = &rd->zstd_data; 228462306a36Sopenharmony_ci 228562306a36Sopenharmony_ci return 0; 228662306a36Sopenharmony_ci} 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_cistatic void 228962306a36Sopenharmony_cireader__release_decomp(struct reader *rd) 229062306a36Sopenharmony_ci{ 229162306a36Sopenharmony_ci perf_decomp__release_events(rd->decomp_data.decomp); 229262306a36Sopenharmony_ci zstd_fini(&rd->zstd_data); 229362306a36Sopenharmony_ci} 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_cistatic int 229662306a36Sopenharmony_cireader__mmap(struct reader *rd, struct perf_session *session) 229762306a36Sopenharmony_ci{ 229862306a36Sopenharmony_ci int mmap_prot, mmap_flags; 229962306a36Sopenharmony_ci char *buf, **mmaps = rd->mmaps; 230062306a36Sopenharmony_ci u64 page_offset; 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci mmap_prot = PROT_READ; 230362306a36Sopenharmony_ci mmap_flags = MAP_SHARED; 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_ci if (rd->in_place_update) { 230662306a36Sopenharmony_ci mmap_prot |= PROT_WRITE; 230762306a36Sopenharmony_ci } else if (session->header.needs_swap) { 230862306a36Sopenharmony_ci mmap_prot |= PROT_WRITE; 230962306a36Sopenharmony_ci mmap_flags = MAP_PRIVATE; 231062306a36Sopenharmony_ci } 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci if (mmaps[rd->mmap_idx]) { 231362306a36Sopenharmony_ci munmap(mmaps[rd->mmap_idx], rd->mmap_size); 231462306a36Sopenharmony_ci mmaps[rd->mmap_idx] = NULL; 231562306a36Sopenharmony_ci } 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci page_offset = page_size * (rd->head / page_size); 231862306a36Sopenharmony_ci rd->file_offset += page_offset; 231962306a36Sopenharmony_ci rd->head -= page_offset; 232062306a36Sopenharmony_ci 232162306a36Sopenharmony_ci buf = mmap(NULL, rd->mmap_size, mmap_prot, mmap_flags, rd->fd, 232262306a36Sopenharmony_ci rd->file_offset); 232362306a36Sopenharmony_ci if (buf == MAP_FAILED) { 232462306a36Sopenharmony_ci pr_err("failed to mmap file\n"); 232562306a36Sopenharmony_ci return -errno; 232662306a36Sopenharmony_ci } 232762306a36Sopenharmony_ci mmaps[rd->mmap_idx] = rd->mmap_cur = buf; 232862306a36Sopenharmony_ci rd->mmap_idx = (rd->mmap_idx + 1) & (ARRAY_SIZE(rd->mmaps) - 1); 232962306a36Sopenharmony_ci rd->file_pos = rd->file_offset + rd->head; 233062306a36Sopenharmony_ci if (session->one_mmap) { 233162306a36Sopenharmony_ci session->one_mmap_addr = buf; 233262306a36Sopenharmony_ci session->one_mmap_offset = rd->file_offset; 233362306a36Sopenharmony_ci } 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ci return 0; 233662306a36Sopenharmony_ci} 233762306a36Sopenharmony_ci 233862306a36Sopenharmony_cienum { 233962306a36Sopenharmony_ci READER_OK, 234062306a36Sopenharmony_ci READER_NODATA, 234162306a36Sopenharmony_ci}; 234262306a36Sopenharmony_ci 234362306a36Sopenharmony_cistatic int 234462306a36Sopenharmony_cireader__read_event(struct reader *rd, struct perf_session *session, 234562306a36Sopenharmony_ci struct ui_progress *prog) 234662306a36Sopenharmony_ci{ 234762306a36Sopenharmony_ci u64 size; 234862306a36Sopenharmony_ci int err = READER_OK; 234962306a36Sopenharmony_ci union perf_event *event; 235062306a36Sopenharmony_ci s64 skip; 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci event = fetch_mmaped_event(rd->head, rd->mmap_size, rd->mmap_cur, 235362306a36Sopenharmony_ci session->header.needs_swap); 235462306a36Sopenharmony_ci if (IS_ERR(event)) 235562306a36Sopenharmony_ci return PTR_ERR(event); 235662306a36Sopenharmony_ci 235762306a36Sopenharmony_ci if (!event) 235862306a36Sopenharmony_ci return READER_NODATA; 235962306a36Sopenharmony_ci 236062306a36Sopenharmony_ci size = event->header.size; 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci skip = -EINVAL; 236362306a36Sopenharmony_ci 236462306a36Sopenharmony_ci if (size < sizeof(struct perf_event_header) || 236562306a36Sopenharmony_ci (skip = rd->process(session, event, rd->file_pos, rd->path)) < 0) { 236662306a36Sopenharmony_ci pr_err("%#" PRIx64 " [%#x]: failed to process type: %d [%s]\n", 236762306a36Sopenharmony_ci rd->file_offset + rd->head, event->header.size, 236862306a36Sopenharmony_ci event->header.type, strerror(-skip)); 236962306a36Sopenharmony_ci err = skip; 237062306a36Sopenharmony_ci goto out; 237162306a36Sopenharmony_ci } 237262306a36Sopenharmony_ci 237362306a36Sopenharmony_ci if (skip) 237462306a36Sopenharmony_ci size += skip; 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_ci rd->size += size; 237762306a36Sopenharmony_ci rd->head += size; 237862306a36Sopenharmony_ci rd->file_pos += size; 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci err = __perf_session__process_decomp_events(session); 238162306a36Sopenharmony_ci if (err) 238262306a36Sopenharmony_ci goto out; 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci ui_progress__update(prog, size); 238562306a36Sopenharmony_ci 238662306a36Sopenharmony_ciout: 238762306a36Sopenharmony_ci return err; 238862306a36Sopenharmony_ci} 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_cistatic inline bool 239162306a36Sopenharmony_cireader__eof(struct reader *rd) 239262306a36Sopenharmony_ci{ 239362306a36Sopenharmony_ci return (rd->file_pos >= rd->data_size + rd->data_offset); 239462306a36Sopenharmony_ci} 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_cistatic int 239762306a36Sopenharmony_cireader__process_events(struct reader *rd, struct perf_session *session, 239862306a36Sopenharmony_ci struct ui_progress *prog) 239962306a36Sopenharmony_ci{ 240062306a36Sopenharmony_ci int err; 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci err = reader__init(rd, &session->one_mmap); 240362306a36Sopenharmony_ci if (err) 240462306a36Sopenharmony_ci goto out; 240562306a36Sopenharmony_ci 240662306a36Sopenharmony_ci session->active_decomp = &rd->decomp_data; 240762306a36Sopenharmony_ci 240862306a36Sopenharmony_ciremap: 240962306a36Sopenharmony_ci err = reader__mmap(rd, session); 241062306a36Sopenharmony_ci if (err) 241162306a36Sopenharmony_ci goto out; 241262306a36Sopenharmony_ci 241362306a36Sopenharmony_cimore: 241462306a36Sopenharmony_ci err = reader__read_event(rd, session, prog); 241562306a36Sopenharmony_ci if (err < 0) 241662306a36Sopenharmony_ci goto out; 241762306a36Sopenharmony_ci else if (err == READER_NODATA) 241862306a36Sopenharmony_ci goto remap; 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci if (session_done()) 242162306a36Sopenharmony_ci goto out; 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci if (!reader__eof(rd)) 242462306a36Sopenharmony_ci goto more; 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ciout: 242762306a36Sopenharmony_ci session->active_decomp = &session->decomp_data; 242862306a36Sopenharmony_ci return err; 242962306a36Sopenharmony_ci} 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_cistatic s64 process_simple(struct perf_session *session, 243262306a36Sopenharmony_ci union perf_event *event, 243362306a36Sopenharmony_ci u64 file_offset, 243462306a36Sopenharmony_ci const char *file_path) 243562306a36Sopenharmony_ci{ 243662306a36Sopenharmony_ci return perf_session__process_event(session, event, file_offset, file_path); 243762306a36Sopenharmony_ci} 243862306a36Sopenharmony_ci 243962306a36Sopenharmony_cistatic int __perf_session__process_events(struct perf_session *session) 244062306a36Sopenharmony_ci{ 244162306a36Sopenharmony_ci struct reader rd = { 244262306a36Sopenharmony_ci .fd = perf_data__fd(session->data), 244362306a36Sopenharmony_ci .path = session->data->file.path, 244462306a36Sopenharmony_ci .data_size = session->header.data_size, 244562306a36Sopenharmony_ci .data_offset = session->header.data_offset, 244662306a36Sopenharmony_ci .process = process_simple, 244762306a36Sopenharmony_ci .in_place_update = session->data->in_place_update, 244862306a36Sopenharmony_ci }; 244962306a36Sopenharmony_ci struct ordered_events *oe = &session->ordered_events; 245062306a36Sopenharmony_ci struct perf_tool *tool = session->tool; 245162306a36Sopenharmony_ci struct ui_progress prog; 245262306a36Sopenharmony_ci int err; 245362306a36Sopenharmony_ci 245462306a36Sopenharmony_ci perf_tool__fill_defaults(tool); 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci if (rd.data_size == 0) 245762306a36Sopenharmony_ci return -1; 245862306a36Sopenharmony_ci 245962306a36Sopenharmony_ci ui_progress__init_size(&prog, rd.data_size, "Processing events..."); 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci err = reader__process_events(&rd, session, &prog); 246262306a36Sopenharmony_ci if (err) 246362306a36Sopenharmony_ci goto out_err; 246462306a36Sopenharmony_ci /* do the final flush for ordered samples */ 246562306a36Sopenharmony_ci err = ordered_events__flush(oe, OE_FLUSH__FINAL); 246662306a36Sopenharmony_ci if (err) 246762306a36Sopenharmony_ci goto out_err; 246862306a36Sopenharmony_ci err = auxtrace__flush_events(session, tool); 246962306a36Sopenharmony_ci if (err) 247062306a36Sopenharmony_ci goto out_err; 247162306a36Sopenharmony_ci err = perf_session__flush_thread_stacks(session); 247262306a36Sopenharmony_ciout_err: 247362306a36Sopenharmony_ci ui_progress__finish(); 247462306a36Sopenharmony_ci if (!tool->no_warn) 247562306a36Sopenharmony_ci perf_session__warn_about_errors(session); 247662306a36Sopenharmony_ci /* 247762306a36Sopenharmony_ci * We may switching perf.data output, make ordered_events 247862306a36Sopenharmony_ci * reusable. 247962306a36Sopenharmony_ci */ 248062306a36Sopenharmony_ci ordered_events__reinit(&session->ordered_events); 248162306a36Sopenharmony_ci auxtrace__free_events(session); 248262306a36Sopenharmony_ci reader__release_decomp(&rd); 248362306a36Sopenharmony_ci session->one_mmap = false; 248462306a36Sopenharmony_ci return err; 248562306a36Sopenharmony_ci} 248662306a36Sopenharmony_ci 248762306a36Sopenharmony_ci/* 248862306a36Sopenharmony_ci * Processing 2 MB of data from each reader in sequence, 248962306a36Sopenharmony_ci * because that's the way the ordered events sorting works 249062306a36Sopenharmony_ci * most efficiently. 249162306a36Sopenharmony_ci */ 249262306a36Sopenharmony_ci#define READER_MAX_SIZE (2 * 1024 * 1024) 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci/* 249562306a36Sopenharmony_ci * This function reads, merge and process directory data. 249662306a36Sopenharmony_ci * It assumens the version 1 of directory data, where each 249762306a36Sopenharmony_ci * data file holds per-cpu data, already sorted by kernel. 249862306a36Sopenharmony_ci */ 249962306a36Sopenharmony_cistatic int __perf_session__process_dir_events(struct perf_session *session) 250062306a36Sopenharmony_ci{ 250162306a36Sopenharmony_ci struct perf_data *data = session->data; 250262306a36Sopenharmony_ci struct perf_tool *tool = session->tool; 250362306a36Sopenharmony_ci int i, ret, readers, nr_readers; 250462306a36Sopenharmony_ci struct ui_progress prog; 250562306a36Sopenharmony_ci u64 total_size = perf_data__size(session->data); 250662306a36Sopenharmony_ci struct reader *rd; 250762306a36Sopenharmony_ci 250862306a36Sopenharmony_ci perf_tool__fill_defaults(tool); 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci ui_progress__init_size(&prog, total_size, "Sorting events..."); 251162306a36Sopenharmony_ci 251262306a36Sopenharmony_ci nr_readers = 1; 251362306a36Sopenharmony_ci for (i = 0; i < data->dir.nr; i++) { 251462306a36Sopenharmony_ci if (data->dir.files[i].size) 251562306a36Sopenharmony_ci nr_readers++; 251662306a36Sopenharmony_ci } 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci rd = zalloc(nr_readers * sizeof(struct reader)); 251962306a36Sopenharmony_ci if (!rd) 252062306a36Sopenharmony_ci return -ENOMEM; 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci rd[0] = (struct reader) { 252362306a36Sopenharmony_ci .fd = perf_data__fd(session->data), 252462306a36Sopenharmony_ci .path = session->data->file.path, 252562306a36Sopenharmony_ci .data_size = session->header.data_size, 252662306a36Sopenharmony_ci .data_offset = session->header.data_offset, 252762306a36Sopenharmony_ci .process = process_simple, 252862306a36Sopenharmony_ci .in_place_update = session->data->in_place_update, 252962306a36Sopenharmony_ci }; 253062306a36Sopenharmony_ci ret = reader__init(&rd[0], NULL); 253162306a36Sopenharmony_ci if (ret) 253262306a36Sopenharmony_ci goto out_err; 253362306a36Sopenharmony_ci ret = reader__mmap(&rd[0], session); 253462306a36Sopenharmony_ci if (ret) 253562306a36Sopenharmony_ci goto out_err; 253662306a36Sopenharmony_ci readers = 1; 253762306a36Sopenharmony_ci 253862306a36Sopenharmony_ci for (i = 0; i < data->dir.nr; i++) { 253962306a36Sopenharmony_ci if (!data->dir.files[i].size) 254062306a36Sopenharmony_ci continue; 254162306a36Sopenharmony_ci rd[readers] = (struct reader) { 254262306a36Sopenharmony_ci .fd = data->dir.files[i].fd, 254362306a36Sopenharmony_ci .path = data->dir.files[i].path, 254462306a36Sopenharmony_ci .data_size = data->dir.files[i].size, 254562306a36Sopenharmony_ci .data_offset = 0, 254662306a36Sopenharmony_ci .process = process_simple, 254762306a36Sopenharmony_ci .in_place_update = session->data->in_place_update, 254862306a36Sopenharmony_ci }; 254962306a36Sopenharmony_ci ret = reader__init(&rd[readers], NULL); 255062306a36Sopenharmony_ci if (ret) 255162306a36Sopenharmony_ci goto out_err; 255262306a36Sopenharmony_ci ret = reader__mmap(&rd[readers], session); 255362306a36Sopenharmony_ci if (ret) 255462306a36Sopenharmony_ci goto out_err; 255562306a36Sopenharmony_ci readers++; 255662306a36Sopenharmony_ci } 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci i = 0; 255962306a36Sopenharmony_ci while (readers) { 256062306a36Sopenharmony_ci if (session_done()) 256162306a36Sopenharmony_ci break; 256262306a36Sopenharmony_ci 256362306a36Sopenharmony_ci if (rd[i].done) { 256462306a36Sopenharmony_ci i = (i + 1) % nr_readers; 256562306a36Sopenharmony_ci continue; 256662306a36Sopenharmony_ci } 256762306a36Sopenharmony_ci if (reader__eof(&rd[i])) { 256862306a36Sopenharmony_ci rd[i].done = true; 256962306a36Sopenharmony_ci readers--; 257062306a36Sopenharmony_ci continue; 257162306a36Sopenharmony_ci } 257262306a36Sopenharmony_ci 257362306a36Sopenharmony_ci session->active_decomp = &rd[i].decomp_data; 257462306a36Sopenharmony_ci ret = reader__read_event(&rd[i], session, &prog); 257562306a36Sopenharmony_ci if (ret < 0) { 257662306a36Sopenharmony_ci goto out_err; 257762306a36Sopenharmony_ci } else if (ret == READER_NODATA) { 257862306a36Sopenharmony_ci ret = reader__mmap(&rd[i], session); 257962306a36Sopenharmony_ci if (ret) 258062306a36Sopenharmony_ci goto out_err; 258162306a36Sopenharmony_ci } 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci if (rd[i].size >= READER_MAX_SIZE) { 258462306a36Sopenharmony_ci rd[i].size = 0; 258562306a36Sopenharmony_ci i = (i + 1) % nr_readers; 258662306a36Sopenharmony_ci } 258762306a36Sopenharmony_ci } 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_ci ret = ordered_events__flush(&session->ordered_events, OE_FLUSH__FINAL); 259062306a36Sopenharmony_ci if (ret) 259162306a36Sopenharmony_ci goto out_err; 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci ret = perf_session__flush_thread_stacks(session); 259462306a36Sopenharmony_ciout_err: 259562306a36Sopenharmony_ci ui_progress__finish(); 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci if (!tool->no_warn) 259862306a36Sopenharmony_ci perf_session__warn_about_errors(session); 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci /* 260162306a36Sopenharmony_ci * We may switching perf.data output, make ordered_events 260262306a36Sopenharmony_ci * reusable. 260362306a36Sopenharmony_ci */ 260462306a36Sopenharmony_ci ordered_events__reinit(&session->ordered_events); 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci session->one_mmap = false; 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci session->active_decomp = &session->decomp_data; 260962306a36Sopenharmony_ci for (i = 0; i < nr_readers; i++) 261062306a36Sopenharmony_ci reader__release_decomp(&rd[i]); 261162306a36Sopenharmony_ci zfree(&rd); 261262306a36Sopenharmony_ci 261362306a36Sopenharmony_ci return ret; 261462306a36Sopenharmony_ci} 261562306a36Sopenharmony_ci 261662306a36Sopenharmony_ciint perf_session__process_events(struct perf_session *session) 261762306a36Sopenharmony_ci{ 261862306a36Sopenharmony_ci if (perf_session__register_idle_thread(session) < 0) 261962306a36Sopenharmony_ci return -ENOMEM; 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci if (perf_data__is_pipe(session->data)) 262262306a36Sopenharmony_ci return __perf_session__process_pipe_events(session); 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ci if (perf_data__is_dir(session->data) && session->data->dir.nr) 262562306a36Sopenharmony_ci return __perf_session__process_dir_events(session); 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci return __perf_session__process_events(session); 262862306a36Sopenharmony_ci} 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_cibool perf_session__has_traces(struct perf_session *session, const char *msg) 263162306a36Sopenharmony_ci{ 263262306a36Sopenharmony_ci struct evsel *evsel; 263362306a36Sopenharmony_ci 263462306a36Sopenharmony_ci evlist__for_each_entry(session->evlist, evsel) { 263562306a36Sopenharmony_ci if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) 263662306a36Sopenharmony_ci return true; 263762306a36Sopenharmony_ci } 263862306a36Sopenharmony_ci 263962306a36Sopenharmony_ci pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg); 264062306a36Sopenharmony_ci return false; 264162306a36Sopenharmony_ci} 264262306a36Sopenharmony_ci 264362306a36Sopenharmony_ciint map__set_kallsyms_ref_reloc_sym(struct map *map, const char *symbol_name, u64 addr) 264462306a36Sopenharmony_ci{ 264562306a36Sopenharmony_ci char *bracket; 264662306a36Sopenharmony_ci struct ref_reloc_sym *ref; 264762306a36Sopenharmony_ci struct kmap *kmap; 264862306a36Sopenharmony_ci 264962306a36Sopenharmony_ci ref = zalloc(sizeof(struct ref_reloc_sym)); 265062306a36Sopenharmony_ci if (ref == NULL) 265162306a36Sopenharmony_ci return -ENOMEM; 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci ref->name = strdup(symbol_name); 265462306a36Sopenharmony_ci if (ref->name == NULL) { 265562306a36Sopenharmony_ci free(ref); 265662306a36Sopenharmony_ci return -ENOMEM; 265762306a36Sopenharmony_ci } 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci bracket = strchr(ref->name, ']'); 266062306a36Sopenharmony_ci if (bracket) 266162306a36Sopenharmony_ci *bracket = '\0'; 266262306a36Sopenharmony_ci 266362306a36Sopenharmony_ci ref->addr = addr; 266462306a36Sopenharmony_ci 266562306a36Sopenharmony_ci kmap = map__kmap(map); 266662306a36Sopenharmony_ci if (kmap) 266762306a36Sopenharmony_ci kmap->ref_reloc_sym = ref; 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci return 0; 267062306a36Sopenharmony_ci} 267162306a36Sopenharmony_ci 267262306a36Sopenharmony_cisize_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp) 267362306a36Sopenharmony_ci{ 267462306a36Sopenharmony_ci return machines__fprintf_dsos(&session->machines, fp); 267562306a36Sopenharmony_ci} 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_cisize_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp, 267862306a36Sopenharmony_ci bool (skip)(struct dso *dso, int parm), int parm) 267962306a36Sopenharmony_ci{ 268062306a36Sopenharmony_ci return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm); 268162306a36Sopenharmony_ci} 268262306a36Sopenharmony_ci 268362306a36Sopenharmony_cisize_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp, 268462306a36Sopenharmony_ci bool skip_empty) 268562306a36Sopenharmony_ci{ 268662306a36Sopenharmony_ci size_t ret; 268762306a36Sopenharmony_ci const char *msg = ""; 268862306a36Sopenharmony_ci 268962306a36Sopenharmony_ci if (perf_header__has_feat(&session->header, HEADER_AUXTRACE)) 269062306a36Sopenharmony_ci msg = " (excludes AUX area (e.g. instruction trace) decoded / synthesized events)"; 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci ret = fprintf(fp, "\nAggregated stats:%s\n", msg); 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci ret += events_stats__fprintf(&session->evlist->stats, fp, skip_empty); 269562306a36Sopenharmony_ci return ret; 269662306a36Sopenharmony_ci} 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_cisize_t perf_session__fprintf(struct perf_session *session, FILE *fp) 269962306a36Sopenharmony_ci{ 270062306a36Sopenharmony_ci /* 270162306a36Sopenharmony_ci * FIXME: Here we have to actually print all the machines in this 270262306a36Sopenharmony_ci * session, not just the host... 270362306a36Sopenharmony_ci */ 270462306a36Sopenharmony_ci return machine__fprintf(&session->machines.host, fp); 270562306a36Sopenharmony_ci} 270662306a36Sopenharmony_ci 270762306a36Sopenharmony_cistruct evsel *perf_session__find_first_evtype(struct perf_session *session, 270862306a36Sopenharmony_ci unsigned int type) 270962306a36Sopenharmony_ci{ 271062306a36Sopenharmony_ci struct evsel *pos; 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci evlist__for_each_entry(session->evlist, pos) { 271362306a36Sopenharmony_ci if (pos->core.attr.type == type) 271462306a36Sopenharmony_ci return pos; 271562306a36Sopenharmony_ci } 271662306a36Sopenharmony_ci return NULL; 271762306a36Sopenharmony_ci} 271862306a36Sopenharmony_ci 271962306a36Sopenharmony_ciint perf_session__cpu_bitmap(struct perf_session *session, 272062306a36Sopenharmony_ci const char *cpu_list, unsigned long *cpu_bitmap) 272162306a36Sopenharmony_ci{ 272262306a36Sopenharmony_ci int i, err = -1; 272362306a36Sopenharmony_ci struct perf_cpu_map *map; 272462306a36Sopenharmony_ci int nr_cpus = min(session->header.env.nr_cpus_avail, MAX_NR_CPUS); 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci for (i = 0; i < PERF_TYPE_MAX; ++i) { 272762306a36Sopenharmony_ci struct evsel *evsel; 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_ci evsel = perf_session__find_first_evtype(session, i); 273062306a36Sopenharmony_ci if (!evsel) 273162306a36Sopenharmony_ci continue; 273262306a36Sopenharmony_ci 273362306a36Sopenharmony_ci if (!(evsel->core.attr.sample_type & PERF_SAMPLE_CPU)) { 273462306a36Sopenharmony_ci pr_err("File does not contain CPU events. " 273562306a36Sopenharmony_ci "Remove -C option to proceed.\n"); 273662306a36Sopenharmony_ci return -1; 273762306a36Sopenharmony_ci } 273862306a36Sopenharmony_ci } 273962306a36Sopenharmony_ci 274062306a36Sopenharmony_ci map = perf_cpu_map__new(cpu_list); 274162306a36Sopenharmony_ci if (map == NULL) { 274262306a36Sopenharmony_ci pr_err("Invalid cpu_list\n"); 274362306a36Sopenharmony_ci return -1; 274462306a36Sopenharmony_ci } 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_ci for (i = 0; i < perf_cpu_map__nr(map); i++) { 274762306a36Sopenharmony_ci struct perf_cpu cpu = perf_cpu_map__cpu(map, i); 274862306a36Sopenharmony_ci 274962306a36Sopenharmony_ci if (cpu.cpu >= nr_cpus) { 275062306a36Sopenharmony_ci pr_err("Requested CPU %d too large. " 275162306a36Sopenharmony_ci "Consider raising MAX_NR_CPUS\n", cpu.cpu); 275262306a36Sopenharmony_ci goto out_delete_map; 275362306a36Sopenharmony_ci } 275462306a36Sopenharmony_ci 275562306a36Sopenharmony_ci __set_bit(cpu.cpu, cpu_bitmap); 275662306a36Sopenharmony_ci } 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci err = 0; 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ciout_delete_map: 276162306a36Sopenharmony_ci perf_cpu_map__put(map); 276262306a36Sopenharmony_ci return err; 276362306a36Sopenharmony_ci} 276462306a36Sopenharmony_ci 276562306a36Sopenharmony_civoid perf_session__fprintf_info(struct perf_session *session, FILE *fp, 276662306a36Sopenharmony_ci bool full) 276762306a36Sopenharmony_ci{ 276862306a36Sopenharmony_ci if (session == NULL || fp == NULL) 276962306a36Sopenharmony_ci return; 277062306a36Sopenharmony_ci 277162306a36Sopenharmony_ci fprintf(fp, "# ========\n"); 277262306a36Sopenharmony_ci perf_header__fprintf_info(session, fp, full); 277362306a36Sopenharmony_ci fprintf(fp, "# ========\n#\n"); 277462306a36Sopenharmony_ci} 277562306a36Sopenharmony_ci 277662306a36Sopenharmony_cistatic int perf_session__register_guest(struct perf_session *session, pid_t machine_pid) 277762306a36Sopenharmony_ci{ 277862306a36Sopenharmony_ci struct machine *machine = machines__findnew(&session->machines, machine_pid); 277962306a36Sopenharmony_ci struct thread *thread; 278062306a36Sopenharmony_ci 278162306a36Sopenharmony_ci if (!machine) 278262306a36Sopenharmony_ci return -ENOMEM; 278362306a36Sopenharmony_ci 278462306a36Sopenharmony_ci machine->single_address_space = session->machines.host.single_address_space; 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci thread = machine__idle_thread(machine); 278762306a36Sopenharmony_ci if (!thread) 278862306a36Sopenharmony_ci return -ENOMEM; 278962306a36Sopenharmony_ci thread__put(thread); 279062306a36Sopenharmony_ci 279162306a36Sopenharmony_ci machine->kallsyms_filename = perf_data__guest_kallsyms_name(session->data, machine_pid); 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci return 0; 279462306a36Sopenharmony_ci} 279562306a36Sopenharmony_ci 279662306a36Sopenharmony_cistatic int perf_session__set_guest_cpu(struct perf_session *session, pid_t pid, 279762306a36Sopenharmony_ci pid_t tid, int guest_cpu) 279862306a36Sopenharmony_ci{ 279962306a36Sopenharmony_ci struct machine *machine = &session->machines.host; 280062306a36Sopenharmony_ci struct thread *thread = machine__findnew_thread(machine, pid, tid); 280162306a36Sopenharmony_ci 280262306a36Sopenharmony_ci if (!thread) 280362306a36Sopenharmony_ci return -ENOMEM; 280462306a36Sopenharmony_ci thread__set_guest_cpu(thread, guest_cpu); 280562306a36Sopenharmony_ci thread__put(thread); 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci return 0; 280862306a36Sopenharmony_ci} 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ciint perf_event__process_id_index(struct perf_session *session, 281162306a36Sopenharmony_ci union perf_event *event) 281262306a36Sopenharmony_ci{ 281362306a36Sopenharmony_ci struct evlist *evlist = session->evlist; 281462306a36Sopenharmony_ci struct perf_record_id_index *ie = &event->id_index; 281562306a36Sopenharmony_ci size_t sz = ie->header.size - sizeof(*ie); 281662306a36Sopenharmony_ci size_t i, nr, max_nr; 281762306a36Sopenharmony_ci size_t e1_sz = sizeof(struct id_index_entry); 281862306a36Sopenharmony_ci size_t e2_sz = sizeof(struct id_index_entry_2); 281962306a36Sopenharmony_ci size_t etot_sz = e1_sz + e2_sz; 282062306a36Sopenharmony_ci struct id_index_entry_2 *e2; 282162306a36Sopenharmony_ci pid_t last_pid = 0; 282262306a36Sopenharmony_ci 282362306a36Sopenharmony_ci max_nr = sz / e1_sz; 282462306a36Sopenharmony_ci nr = ie->nr; 282562306a36Sopenharmony_ci if (nr > max_nr) { 282662306a36Sopenharmony_ci printf("Too big: nr %zu max_nr %zu\n", nr, max_nr); 282762306a36Sopenharmony_ci return -EINVAL; 282862306a36Sopenharmony_ci } 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci if (sz >= nr * etot_sz) { 283162306a36Sopenharmony_ci max_nr = sz / etot_sz; 283262306a36Sopenharmony_ci if (nr > max_nr) { 283362306a36Sopenharmony_ci printf("Too big2: nr %zu max_nr %zu\n", nr, max_nr); 283462306a36Sopenharmony_ci return -EINVAL; 283562306a36Sopenharmony_ci } 283662306a36Sopenharmony_ci e2 = (void *)ie + sizeof(*ie) + nr * e1_sz; 283762306a36Sopenharmony_ci } else { 283862306a36Sopenharmony_ci e2 = NULL; 283962306a36Sopenharmony_ci } 284062306a36Sopenharmony_ci 284162306a36Sopenharmony_ci if (dump_trace) 284262306a36Sopenharmony_ci fprintf(stdout, " nr: %zu\n", nr); 284362306a36Sopenharmony_ci 284462306a36Sopenharmony_ci for (i = 0; i < nr; i++, (e2 ? e2++ : 0)) { 284562306a36Sopenharmony_ci struct id_index_entry *e = &ie->entries[i]; 284662306a36Sopenharmony_ci struct perf_sample_id *sid; 284762306a36Sopenharmony_ci int ret; 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_ci if (dump_trace) { 285062306a36Sopenharmony_ci fprintf(stdout, " ... id: %"PRI_lu64, e->id); 285162306a36Sopenharmony_ci fprintf(stdout, " idx: %"PRI_lu64, e->idx); 285262306a36Sopenharmony_ci fprintf(stdout, " cpu: %"PRI_ld64, e->cpu); 285362306a36Sopenharmony_ci fprintf(stdout, " tid: %"PRI_ld64, e->tid); 285462306a36Sopenharmony_ci if (e2) { 285562306a36Sopenharmony_ci fprintf(stdout, " machine_pid: %"PRI_ld64, e2->machine_pid); 285662306a36Sopenharmony_ci fprintf(stdout, " vcpu: %"PRI_lu64"\n", e2->vcpu); 285762306a36Sopenharmony_ci } else { 285862306a36Sopenharmony_ci fprintf(stdout, "\n"); 285962306a36Sopenharmony_ci } 286062306a36Sopenharmony_ci } 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci sid = evlist__id2sid(evlist, e->id); 286362306a36Sopenharmony_ci if (!sid) 286462306a36Sopenharmony_ci return -ENOENT; 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_ci sid->idx = e->idx; 286762306a36Sopenharmony_ci sid->cpu.cpu = e->cpu; 286862306a36Sopenharmony_ci sid->tid = e->tid; 286962306a36Sopenharmony_ci 287062306a36Sopenharmony_ci if (!e2) 287162306a36Sopenharmony_ci continue; 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci sid->machine_pid = e2->machine_pid; 287462306a36Sopenharmony_ci sid->vcpu.cpu = e2->vcpu; 287562306a36Sopenharmony_ci 287662306a36Sopenharmony_ci if (!sid->machine_pid) 287762306a36Sopenharmony_ci continue; 287862306a36Sopenharmony_ci 287962306a36Sopenharmony_ci if (sid->machine_pid != last_pid) { 288062306a36Sopenharmony_ci ret = perf_session__register_guest(session, sid->machine_pid); 288162306a36Sopenharmony_ci if (ret) 288262306a36Sopenharmony_ci return ret; 288362306a36Sopenharmony_ci last_pid = sid->machine_pid; 288462306a36Sopenharmony_ci perf_guest = true; 288562306a36Sopenharmony_ci } 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_ci ret = perf_session__set_guest_cpu(session, sid->machine_pid, e->tid, e2->vcpu); 288862306a36Sopenharmony_ci if (ret) 288962306a36Sopenharmony_ci return ret; 289062306a36Sopenharmony_ci } 289162306a36Sopenharmony_ci return 0; 289262306a36Sopenharmony_ci} 2893