^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * auxtrace.c: AUX area trace support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2013-2015, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/time64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sys/param.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "dso.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include "pmu.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include "evsel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "evsel_config.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include "symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include "util/perf_api_probe.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include "util/synthetic-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include "thread_map.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include "asm/bug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include "auxtrace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include "event.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include "record.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include "session.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <subcmd/parse-options.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include "cs-etm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include "intel-pt.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include "intel-bts.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include "arm-spe.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include "s390-cpumsf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include "util/mmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include "symbol/kallsyms.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <internal/lib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * Make a group from 'leader' to 'last', requiring that the events were not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * already grouped to a different leader.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int perf_evlist__regroup(struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct evsel *leader,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct evsel *last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) bool grp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!evsel__is_group_leader(leader))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) grp = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (grp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!(evsel->leader == leader ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) (evsel->leader == evsel &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) evsel->core.nr_members <= 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) } else if (evsel == leader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) grp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (evsel == last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) grp = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (grp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (evsel->leader != leader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) evsel->leader = leader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (leader->core.nr_members < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) leader->core.nr_members = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) leader->core.nr_members += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) } else if (evsel == leader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) grp = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (evsel == last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static bool auxtrace__dont_decode(struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return !session->itrace_synth_opts ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) session->itrace_synth_opts->dont_decode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct auxtrace_mmap_params *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) void *userpg, int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct perf_event_mmap_page *pc = userpg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) WARN_ONCE(mm->base, "Uninitialized auxtrace_mmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mm->userpg = userpg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mm->mask = mp->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) mm->len = mp->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) mm->prev = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) mm->idx = mp->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mm->tid = mp->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) mm->cpu = mp->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!mp->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) mm->base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #if BITS_PER_LONG != 64 && !defined(HAVE_SYNC_COMPARE_AND_SWAP_SUPPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) pr_err("Cannot use AUX area tracing mmaps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) pc->aux_offset = mp->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pc->aux_size = mp->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) mm->base = mmap(NULL, mp->len, mp->prot, MAP_SHARED, fd, mp->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (mm->base == MAP_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pr_debug2("failed to mmap AUX area\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) mm->base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) void auxtrace_mmap__munmap(struct auxtrace_mmap *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (mm->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) munmap(mm->base, mm->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) mm->base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void auxtrace_mmap_params__init(struct auxtrace_mmap_params *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) off_t auxtrace_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned int auxtrace_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bool auxtrace_overwrite)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (auxtrace_pages) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mp->offset = auxtrace_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mp->len = auxtrace_pages * (size_t)page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) mp->mask = is_power_of_2(mp->len) ? mp->len - 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mp->prot = PROT_READ | (auxtrace_overwrite ? 0 : PROT_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) pr_debug2("AUX area mmap length %zu\n", mp->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) mp->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct evlist *evlist, int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) bool per_cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) mp->idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (per_cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) mp->cpu = evlist->core.cpus->map[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (evlist->core.threads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mp->tid = perf_thread_map__pid(evlist->core.threads, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) mp->tid = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) mp->cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) mp->tid = perf_thread_map__pid(evlist->core.threads, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define AUXTRACE_INIT_NR_QUEUES 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static struct auxtrace_queue *auxtrace_alloc_queue_array(unsigned int nr_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct auxtrace_queue *queue_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned int max_nr_queues, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) max_nr_queues = UINT_MAX / sizeof(struct auxtrace_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (nr_queues > max_nr_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) queue_array = calloc(nr_queues, sizeof(struct auxtrace_queue));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!queue_array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) for (i = 0; i < nr_queues; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) INIT_LIST_HEAD(&queue_array[i].head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) queue_array[i].priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return queue_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int auxtrace_queues__init(struct auxtrace_queues *queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) queues->nr_queues = AUXTRACE_INIT_NR_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) queues->queue_array = auxtrace_alloc_queue_array(queues->nr_queues);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!queues->queue_array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int auxtrace_queues__grow(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned int new_nr_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) unsigned int nr_queues = queues->nr_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct auxtrace_queue *queue_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (!nr_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) nr_queues = AUXTRACE_INIT_NR_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) while (nr_queues && nr_queues < new_nr_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) nr_queues <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (nr_queues < queues->nr_queues || nr_queues < new_nr_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) queue_array = auxtrace_alloc_queue_array(nr_queues);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!queue_array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) for (i = 0; i < queues->nr_queues; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) list_splice_tail(&queues->queue_array[i].head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) &queue_array[i].head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) queue_array[i].tid = queues->queue_array[i].tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) queue_array[i].cpu = queues->queue_array[i].cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) queue_array[i].set = queues->queue_array[i].set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) queue_array[i].priv = queues->queue_array[i].priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) queues->nr_queues = nr_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) queues->queue_array = queue_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) static void *auxtrace_copy_data(u64 size, struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int fd = perf_data__fd(session->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) void *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (size > SSIZE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) p = malloc(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ret = readn(fd, p, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (ret != (ssize_t)size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) free(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int auxtrace_queues__queue_buffer(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) unsigned int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct auxtrace_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct auxtrace_queue *queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (idx >= queues->nr_queues) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) err = auxtrace_queues__grow(queues, idx + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) queue = &queues->queue_array[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!queue->set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) queue->set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) queue->tid = buffer->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) queue->cpu = buffer->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) buffer->buffer_nr = queues->next_buffer_nr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) list_add_tail(&buffer->list, &queue->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) queues->new_data = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) queues->populated = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* Limit buffers to 32MiB on 32-bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) #define BUFFER_LIMIT_FOR_32_BIT (32 * 1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) unsigned int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct auxtrace_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) u64 sz = buffer->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) bool consecutive = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct auxtrace_buffer *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) while (sz > BUFFER_LIMIT_FOR_32_BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) b = memdup(buffer, sizeof(struct auxtrace_buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (!b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) b->size = BUFFER_LIMIT_FOR_32_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) b->consecutive = consecutive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) err = auxtrace_queues__queue_buffer(queues, idx, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) auxtrace_buffer__free(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) buffer->data_offset += BUFFER_LIMIT_FOR_32_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) sz -= BUFFER_LIMIT_FOR_32_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) consecutive = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) buffer->size = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) buffer->consecutive = consecutive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) static bool filter_cpu(struct perf_session *session, int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) unsigned int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct auxtrace_buffer *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct auxtrace_buffer **buffer_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (filter_cpu(session, buffer->cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) buffer = memdup(buffer, sizeof(*buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (session->one_mmap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) buffer->data = buffer->data_offset - session->one_mmap_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) session->one_mmap_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } else if (perf_data__is_pipe(session->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) buffer->data = auxtrace_copy_data(buffer->size, session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!buffer->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) buffer->data_needs_freeing = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) } else if (BITS_PER_LONG == 32 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) buffer->size > BUFFER_LIMIT_FOR_32_BIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) err = auxtrace_queues__split_buffer(queues, idx, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) err = auxtrace_queues__queue_buffer(queues, idx, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* FIXME: Doesn't work for split buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (buffer_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *buffer_ptr = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) auxtrace_buffer__free(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int auxtrace_queues__add_event(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) union perf_event *event, off_t data_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct auxtrace_buffer **buffer_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct auxtrace_buffer buffer = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .pid = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .tid = event->auxtrace.tid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .cpu = event->auxtrace.cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .data_offset = data_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .offset = event->auxtrace.offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .reference = event->auxtrace.reference,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .size = event->auxtrace.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) unsigned int idx = event->auxtrace.idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return auxtrace_queues__add_buffer(queues, session, idx, &buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) buffer_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) off_t file_offset, size_t sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) union perf_event *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) char buf[PERF_SAMPLE_MAX_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) err = perf_session__peek_event(session, file_offset, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) PERF_SAMPLE_MAX_SIZE, &event, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (event->header.type == PERF_RECORD_AUXTRACE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (event->header.size < sizeof(struct perf_record_auxtrace) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) event->header.size != sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) file_offset += event->header.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) err = auxtrace_queues__add_event(queues, session, event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) file_offset, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) void auxtrace_queues__free(struct auxtrace_queues *queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) for (i = 0; i < queues->nr_queues; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) while (!list_empty(&queues->queue_array[i].head)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct auxtrace_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) buffer = list_entry(queues->queue_array[i].head.next,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct auxtrace_buffer, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) list_del_init(&buffer->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) auxtrace_buffer__free(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) zfree(&queues->queue_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) queues->nr_queues = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static void auxtrace_heapify(struct auxtrace_heap_item *heap_array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) unsigned int pos, unsigned int queue_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) u64 ordinal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) unsigned int parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) while (pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) parent = (pos - 1) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (heap_array[parent].ordinal <= ordinal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) heap_array[pos] = heap_array[parent];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) pos = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) heap_array[pos].queue_nr = queue_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) heap_array[pos].ordinal = ordinal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int auxtrace_heap__add(struct auxtrace_heap *heap, unsigned int queue_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) u64 ordinal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct auxtrace_heap_item *heap_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (queue_nr >= heap->heap_sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) unsigned int heap_sz = AUXTRACE_INIT_NR_QUEUES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) while (heap_sz <= queue_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) heap_sz <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) heap_array = realloc(heap->heap_array,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) heap_sz * sizeof(struct auxtrace_heap_item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!heap_array)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) heap->heap_array = heap_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) heap->heap_sz = heap_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) auxtrace_heapify(heap->heap_array, heap->heap_cnt++, queue_nr, ordinal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) void auxtrace_heap__free(struct auxtrace_heap *heap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) zfree(&heap->heap_array);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) heap->heap_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) heap->heap_sz = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) void auxtrace_heap__pop(struct auxtrace_heap *heap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) unsigned int pos, last, heap_cnt = heap->heap_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct auxtrace_heap_item *heap_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (!heap_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) heap->heap_cnt -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) heap_array = heap->heap_array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) unsigned int left, right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) left = (pos << 1) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (left >= heap_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) right = left + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (right >= heap_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) heap_array[pos] = heap_array[left];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (heap_array[left].ordinal < heap_array[right].ordinal) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) heap_array[pos] = heap_array[left];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) pos = left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) heap_array[pos] = heap_array[right];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) pos = right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) last = heap_cnt - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) auxtrace_heapify(heap_array, pos, heap_array[last].queue_nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) heap_array[last].ordinal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct evlist *evlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (itr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return itr->info_priv_size(itr, evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static int auxtrace_not_supported(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) pr_err("AUX area tracing is not supported on this architecture\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) int auxtrace_record__info_fill(struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct perf_record_auxtrace_info *auxtrace_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) size_t priv_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (itr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return itr->info_fill(itr, session, auxtrace_info, priv_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return auxtrace_not_supported();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) void auxtrace_record__free(struct auxtrace_record *itr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if (itr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) itr->free(itr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) int auxtrace_record__snapshot_start(struct auxtrace_record *itr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (itr && itr->snapshot_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return itr->snapshot_start(itr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int auxtrace_record__snapshot_finish(struct auxtrace_record *itr, bool on_exit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (!on_exit && itr && itr->snapshot_finish)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return itr->snapshot_finish(itr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int auxtrace_record__find_snapshot(struct auxtrace_record *itr, int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct auxtrace_mmap *mm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) unsigned char *data, u64 *head, u64 *old)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (itr && itr->find_snapshot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return itr->find_snapshot(itr, idx, mm, data, head, old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int auxtrace_record__options(struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct record_opts *opts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (itr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) itr->evlist = evlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) return itr->recording_options(itr, evlist, opts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) u64 auxtrace_record__reference(struct auxtrace_record *itr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (itr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return itr->reference(itr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct record_opts *opts, const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* PMU-agnostic options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) switch (*str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) opts->auxtrace_snapshot_on_exit = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (itr && itr->parse_snapshot_options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return itr->parse_snapshot_options(itr, opts, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) pr_err("No AUX area tracing to snapshot\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int auxtrace_record__read_finish(struct auxtrace_record *itr, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (!itr->evlist || !itr->pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) evlist__for_each_entry(itr->evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (evsel->core.attr.type == itr->pmu->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (evsel->disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return perf_evlist__enable_event_idx(itr->evlist, evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * Event record size is 16-bit which results in a maximum size of about 64KiB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * Allow about 4KiB for the rest of the sample record, to give a maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * AUX area sample size of 60KiB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) #define MAX_AUX_SAMPLE_SIZE (60 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /* Arbitrary default size if no other default provided */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) #define DEFAULT_AUX_SAMPLE_SIZE (4 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static int auxtrace_validate_aux_sample_size(struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct record_opts *opts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) bool has_aux_leader = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) u32 sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) sz = evsel->core.attr.aux_sample_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) if (evsel__is_group_leader(evsel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) has_aux_leader = evsel__is_aux_event(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (has_aux_leader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) pr_err("Cannot add AUX area sampling to an AUX area event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) pr_err("Cannot add AUX area sampling to a group leader\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (sz > MAX_AUX_SAMPLE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) pr_err("AUX area sample size %u too big, max. %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) sz, MAX_AUX_SAMPLE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (!has_aux_leader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) pr_err("Cannot add AUX area sampling because group leader is not an AUX area event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) evsel__set_sample_bit(evsel, AUX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) opts->auxtrace_sample_mode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) evsel__reset_sample_bit(evsel, AUX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (!opts->auxtrace_sample_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) pr_err("AUX area sampling requires an AUX area event group leader plus other events to which to add samples\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (!perf_can_aux_sample()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) pr_err("AUX area sampling is not supported by kernel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int auxtrace_parse_sample_options(struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct record_opts *opts, const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) struct evsel_config_term *term;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct evsel *aux_evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) bool has_aux_sample_size = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) bool has_aux_leader = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) char *endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) unsigned long sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) goto no_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (!itr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) pr_err("No AUX area event to sample\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) sz = strtoul(str, &endptr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (*endptr || sz > UINT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) pr_err("Bad AUX area sampling option: '%s'\n", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (!sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) sz = itr->default_aux_sample_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (!sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) sz = DEFAULT_AUX_SAMPLE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) /* Set aux_sample_size based on --aux-sample option */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (evsel__is_group_leader(evsel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) has_aux_leader = evsel__is_aux_event(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) } else if (has_aux_leader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) evsel->core.attr.aux_sample_size = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) no_opt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) aux_evsel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* Override with aux_sample_size from config term */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (evsel__is_aux_event(evsel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) aux_evsel = evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) term = evsel__get_config_term(evsel, AUX_SAMPLE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (term) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) has_aux_sample_size = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) evsel->core.attr.aux_sample_size = term->val.aux_sample_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* If possible, group with the AUX event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (aux_evsel && evsel->core.attr.aux_sample_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) perf_evlist__regroup(evlist, aux_evsel, evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (!str && !has_aux_sample_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (!itr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) pr_err("No AUX area event to sample\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return auxtrace_validate_aux_sample_size(evlist, opts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct auxtrace_record *__weak
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) auxtrace_record__init(struct evlist *evlist __maybe_unused, int *err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) *err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static int auxtrace_index__alloc(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct auxtrace_index *auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) auxtrace_index = malloc(sizeof(struct auxtrace_index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!auxtrace_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) auxtrace_index->nr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) INIT_LIST_HEAD(&auxtrace_index->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) list_add_tail(&auxtrace_index->list, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) void auxtrace_index__free(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct auxtrace_index *auxtrace_index, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) list_for_each_entry_safe(auxtrace_index, n, head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) list_del_init(&auxtrace_index->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) free(auxtrace_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static struct auxtrace_index *auxtrace_index__last(struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct auxtrace_index *auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (list_empty(head)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) err = auxtrace_index__alloc(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) auxtrace_index = list_entry(head->prev, struct auxtrace_index, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (auxtrace_index->nr >= PERF_AUXTRACE_INDEX_ENTRY_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) err = auxtrace_index__alloc(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) auxtrace_index = list_entry(head->prev, struct auxtrace_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) int auxtrace_index__auxtrace_event(struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) union perf_event *event, off_t file_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct auxtrace_index *auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) size_t nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) auxtrace_index = auxtrace_index__last(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (!auxtrace_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) nr = auxtrace_index->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) auxtrace_index->entries[nr].file_offset = file_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) auxtrace_index->entries[nr].sz = event->header.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) auxtrace_index->nr += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static int auxtrace_index__do_write(int fd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct auxtrace_index *auxtrace_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct auxtrace_index_entry ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) for (i = 0; i < auxtrace_index->nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) ent.file_offset = auxtrace_index->entries[i].file_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ent.sz = auxtrace_index->entries[i].sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (writen(fd, &ent, sizeof(ent)) != sizeof(ent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) int auxtrace_index__write(int fd, struct list_head *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct auxtrace_index *auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) u64 total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) list_for_each_entry(auxtrace_index, head, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) total += auxtrace_index->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (writen(fd, &total, sizeof(total)) != sizeof(total))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) list_for_each_entry(auxtrace_index, head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) err = auxtrace_index__do_write(fd, auxtrace_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static int auxtrace_index__process_entry(int fd, struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) bool needs_swap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct auxtrace_index *auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct auxtrace_index_entry ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) size_t nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (readn(fd, &ent, sizeof(ent)) != sizeof(ent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) auxtrace_index = auxtrace_index__last(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (!auxtrace_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) nr = auxtrace_index->nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (needs_swap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) auxtrace_index->entries[nr].file_offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) bswap_64(ent.file_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) auxtrace_index->entries[nr].sz = bswap_64(ent.sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) auxtrace_index->entries[nr].file_offset = ent.file_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) auxtrace_index->entries[nr].sz = ent.sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) auxtrace_index->nr = nr + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) int auxtrace_index__process(int fd, u64 size, struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) bool needs_swap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct list_head *head = &session->auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) u64 nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (readn(fd, &nr, sizeof(u64)) != sizeof(u64))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (needs_swap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) nr = bswap_64(nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (sizeof(u64) + nr * sizeof(struct auxtrace_index_entry) > size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) while (nr--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) err = auxtrace_index__process_entry(fd, head, needs_swap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static int auxtrace_queues__process_index_entry(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) struct auxtrace_index_entry *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return auxtrace_queues__add_indexed_event(queues, session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ent->file_offset, ent->sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) int auxtrace_queues__process_index(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) struct auxtrace_index *auxtrace_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) struct auxtrace_index_entry *ent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) if (auxtrace__dont_decode(session))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) for (i = 0; i < auxtrace_index->nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) ent = &auxtrace_index->entries[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) err = auxtrace_queues__process_index_entry(queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) struct auxtrace_buffer *auxtrace_buffer__next(struct auxtrace_queue *queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct auxtrace_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (list_is_last(&buffer->list, &queue->head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return list_entry(buffer->list.next, struct auxtrace_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (list_empty(&queue->head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return list_entry(queue->head.next, struct auxtrace_buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) struct auxtrace_queue *auxtrace_queues__sample_queue(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) struct perf_sample_id *sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) u64 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) id = sample->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) sid = perf_evlist__id2sid(session->evlist, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (!sid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) idx = sid->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (idx >= queues->nr_queues)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return &queues->queue_array[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) int auxtrace_queues__add_sample(struct auxtrace_queues *queues,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) struct perf_sample *sample, u64 data_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) u64 reference)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) struct auxtrace_buffer buffer = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .pid = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) .data_offset = data_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) .reference = reference,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) .size = sample->aux_sample.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct perf_sample_id *sid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) u64 id = sample->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) sid = perf_evlist__id2sid(session->evlist, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (!sid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) idx = sid->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) buffer.tid = sid->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) buffer.cpu = sid->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return auxtrace_queues__add_buffer(queues, session, idx, &buffer, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) struct queue_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) bool samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) bool events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static int auxtrace_queue_data_cb(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) union perf_event *event, u64 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct queue_data *qd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct perf_sample sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (qd->events && event->header.type == PERF_RECORD_AUXTRACE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (event->header.size < sizeof(struct perf_record_auxtrace))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) offset += event->header.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return session->auxtrace->queue_data(session, NULL, event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (!qd->samples || event->header.type != PERF_RECORD_SAMPLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) err = perf_evlist__parse_sample(session->evlist, event, &sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (!sample.aux_sample.size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) offset += sample.aux_sample.data - (void *)event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return session->auxtrace->queue_data(session, &sample, NULL, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) int auxtrace_queue_data(struct perf_session *session, bool samples, bool events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) struct queue_data qd = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) .samples = samples,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) .events = events,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (auxtrace__dont_decode(session))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (!session->auxtrace || !session->auxtrace->queue_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return perf_session__peek_events(session, session->header.data_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) session->header.data_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) auxtrace_queue_data_cb, &qd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) void *auxtrace_buffer__get_data(struct auxtrace_buffer *buffer, int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) size_t adj = buffer->data_offset & (page_size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) size_t size = buffer->size + adj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) off_t file_offset = buffer->data_offset - adj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) void *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (buffer->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) return buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, file_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) if (addr == MAP_FAILED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) buffer->mmap_addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) buffer->mmap_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) buffer->data = addr + adj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) return buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) void auxtrace_buffer__put_data(struct auxtrace_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (!buffer->data || !buffer->mmap_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) munmap(buffer->mmap_addr, buffer->mmap_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) buffer->mmap_addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) buffer->mmap_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) buffer->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) buffer->use_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) void auxtrace_buffer__drop_data(struct auxtrace_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) auxtrace_buffer__put_data(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (buffer->data_needs_freeing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) buffer->data_needs_freeing = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) zfree(&buffer->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) buffer->use_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) buffer->size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) void auxtrace_buffer__free(struct auxtrace_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) auxtrace_buffer__drop_data(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) free(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) void auxtrace_synth_error(struct perf_record_auxtrace_error *auxtrace_error, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int code, int cpu, pid_t pid, pid_t tid, u64 ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) const char *msg, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) memset(auxtrace_error, 0, sizeof(struct perf_record_auxtrace_error));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) auxtrace_error->header.type = PERF_RECORD_AUXTRACE_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) auxtrace_error->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) auxtrace_error->code = code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) auxtrace_error->cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) auxtrace_error->pid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) auxtrace_error->tid = tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) auxtrace_error->fmt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) auxtrace_error->ip = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) auxtrace_error->time = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) strlcpy(auxtrace_error->msg, msg, MAX_AUXTRACE_ERROR_MSG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) size = (void *)auxtrace_error->msg - (void *)auxtrace_error +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) strlen(auxtrace_error->msg) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) auxtrace_error->header.size = PERF_ALIGN(size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) struct perf_tool *tool,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) perf_event__handler_t process)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) union perf_event *ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) size_t priv_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) pr_debug2("Synthesizing auxtrace information\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) priv_size = auxtrace_record__info_priv_size(itr, session->evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) ev = zalloc(sizeof(struct perf_record_auxtrace_info) + priv_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (!ev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) ev->auxtrace_info.header.type = PERF_RECORD_AUXTRACE_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) ev->auxtrace_info.header.size = sizeof(struct perf_record_auxtrace_info) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) priv_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) err = auxtrace_record__info_fill(itr, session, &ev->auxtrace_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) priv_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) err = process(tool, ev, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) free(ev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) static void unleader_evsel(struct evlist *evlist, struct evsel *leader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct evsel *new_leader = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) /* Find new leader for the group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (evsel->leader != leader || evsel == leader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) if (!new_leader)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) new_leader = evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) evsel->leader = new_leader;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) /* Update group information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (new_leader) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) zfree(&new_leader->group_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) new_leader->group_name = leader->group_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) leader->group_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) new_leader->core.nr_members = leader->core.nr_members - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) leader->core.nr_members = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static void unleader_auxtrace(struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) evlist__for_each_entry(session->evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (auxtrace__evsel_is_auxtrace(session, evsel) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) evsel__is_group_leader(evsel)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) unleader_evsel(session->evlist, evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) int perf_event__process_auxtrace_info(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) union perf_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) enum auxtrace_type type = event->auxtrace_info.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) if (dump_trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) fprintf(stdout, " type: %u\n", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) case PERF_AUXTRACE_INTEL_PT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) err = intel_pt_process_auxtrace_info(event, session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) case PERF_AUXTRACE_INTEL_BTS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) err = intel_bts_process_auxtrace_info(event, session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) case PERF_AUXTRACE_ARM_SPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) err = arm_spe_process_auxtrace_info(event, session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) case PERF_AUXTRACE_CS_ETM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) err = cs_etm__process_auxtrace_info(event, session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) case PERF_AUXTRACE_S390_CPUMSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) err = s390_cpumsf_process_auxtrace_info(event, session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) case PERF_AUXTRACE_UNKNOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) unleader_auxtrace(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) s64 perf_event__process_auxtrace(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) union perf_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) s64 err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) if (dump_trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) fprintf(stdout, " size: %#"PRI_lx64" offset: %#"PRI_lx64" ref: %#"PRI_lx64" idx: %u tid: %d cpu: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) event->auxtrace.size, event->auxtrace.offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) event->auxtrace.reference, event->auxtrace.idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) event->auxtrace.tid, event->auxtrace.cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (auxtrace__dont_decode(session))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return event->auxtrace.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) err = session->auxtrace->process_auxtrace_event(session, event, session->tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) return event->auxtrace.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) #define PERF_ITRACE_DEFAULT_PERIOD_TYPE PERF_ITRACE_PERIOD_NANOSECS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) #define PERF_ITRACE_DEFAULT_PERIOD 100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) #define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) #define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) #define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) #define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) bool no_sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) synth_opts->branches = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) synth_opts->transactions = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) synth_opts->ptwrites = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) synth_opts->pwr_events = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) synth_opts->other_events = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) synth_opts->errors = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) synth_opts->flc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) synth_opts->llc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) synth_opts->tlb = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) synth_opts->remote_access = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (no_sample) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) synth_opts->period_type = PERF_ITRACE_PERIOD_INSTRUCTIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) synth_opts->period = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) synth_opts->calls = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) synth_opts->instructions = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) synth_opts->initial_skip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) static int get_flag(const char **ptr, unsigned int *flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) char c = **ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) if (c >= 'a' && c <= 'z') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) *flags |= 1 << (c - 'a');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) ++*ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) } else if (c == ' ') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) ++*ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) static int get_flags(const char **ptr, unsigned int *plus_flags, unsigned int *minus_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) switch (**ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) case '+':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) ++*ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (get_flag(ptr, plus_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) case '-':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) ++*ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) if (get_flag(ptr, minus_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) case ' ':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) ++*ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) * Please check tools/perf/Documentation/perf-script.txt for information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * about the options parsed here, which is introduced after this cset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * when support in 'perf script' for these options is introduced.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) int itrace_parse_synth_opts(const struct option *opt, const char *str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) int unset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) struct itrace_synth_opts *synth_opts = opt->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) const char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) char *endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) bool period_type_set = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) bool period_set = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) synth_opts->set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (unset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) synth_opts->dont_decode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (!str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) itrace_synth_opts__set_default(synth_opts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) synth_opts->default_no_sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) for (p = str; *p;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) switch (*p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) synth_opts->instructions = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) while (*p == ' ' || *p == ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) p += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) if (isdigit(*p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) synth_opts->period = strtoull(p, &endptr, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) period_set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) p = endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) while (*p == ' ' || *p == ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) p += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) switch (*p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) synth_opts->period_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) PERF_ITRACE_PERIOD_INSTRUCTIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) period_type_set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) synth_opts->period_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) PERF_ITRACE_PERIOD_TICKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) period_type_set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) synth_opts->period *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /* Fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) case 'u':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) synth_opts->period *= 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) /* Fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (*p++ != 's')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) synth_opts->period_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) PERF_ITRACE_PERIOD_NANOSECS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) period_type_set = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) case '\0':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) synth_opts->branches = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) synth_opts->transactions = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) case 'w':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) synth_opts->ptwrites = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) synth_opts->pwr_events = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) case 'o':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) synth_opts->other_events = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) case 'e':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) synth_opts->errors = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (get_flags(&p, &synth_opts->error_plus_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) &synth_opts->error_minus_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) synth_opts->log = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) if (get_flags(&p, &synth_opts->log_plus_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) &synth_opts->log_minus_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) synth_opts->branches = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) synth_opts->calls = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) synth_opts->branches = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) synth_opts->returns = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) case 'G':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) case 'g':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if (p[-1] == 'G')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) synth_opts->add_callchain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) synth_opts->callchain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) synth_opts->callchain_sz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) while (*p == ' ' || *p == ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) p += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) if (isdigit(*p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) val = strtoul(p, &endptr, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) p = endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (!val || val > PERF_ITRACE_MAX_CALLCHAIN_SZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) synth_opts->callchain_sz = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) if (p[-1] == 'L')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) synth_opts->add_last_branch = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) synth_opts->last_branch = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) synth_opts->last_branch_sz =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) while (*p == ' ' || *p == ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) p += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) if (isdigit(*p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) val = strtoul(p, &endptr, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) p = endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) if (!val ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) val > PERF_ITRACE_MAX_LAST_BRANCH_SZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) synth_opts->last_branch_sz = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) case 's':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) synth_opts->initial_skip = strtoul(p, &endptr, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) if (p == endptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) p = endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) case 'f':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) synth_opts->flc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) synth_opts->llc = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) synth_opts->tlb = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) synth_opts->remote_access = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) case 'q':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) synth_opts->quick += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) case ' ':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) case ',':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (synth_opts->instructions) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (!period_type_set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) synth_opts->period_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) PERF_ITRACE_DEFAULT_PERIOD_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (!period_set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) pr_err("Bad Instruction Tracing options '%s'\n", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) static const char * const auxtrace_error_type_name[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) [PERF_AUXTRACE_ERROR_ITRACE] = "instruction trace",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) static const char *auxtrace_error_name(int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) const char *error_type_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) if (type < PERF_AUXTRACE_ERROR_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) error_type_name = auxtrace_error_type_name[type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) if (!error_type_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) error_type_name = "unknown AUX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) return error_type_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) struct perf_record_auxtrace_error *e = &event->auxtrace_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) unsigned long long nsecs = e->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) const char *msg = e->msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) ret = fprintf(fp, " %s error type %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) auxtrace_error_name(e->type), e->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) if (e->fmt && nsecs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) unsigned long secs = nsecs / NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) nsecs -= secs * NSEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) ret += fprintf(fp, " time %lu.%09llu", secs, nsecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) ret += fprintf(fp, " time 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (!e->fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) msg = (const char *)&e->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) ret += fprintf(fp, " cpu %d pid %d tid %d ip %#"PRI_lx64" code %u: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) e->cpu, e->pid, e->tid, e->ip, e->code, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) void perf_session__auxtrace_error_inc(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) union perf_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) struct perf_record_auxtrace_error *e = &event->auxtrace_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (e->type < PERF_AUXTRACE_ERROR_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) session->evlist->stats.nr_auxtrace_errors[e->type] += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) void events_stats__auxtrace_error_warn(const struct events_stats *stats)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) for (i = 0; i < PERF_AUXTRACE_ERROR_MAX; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) if (!stats->nr_auxtrace_errors[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) ui__warning("%u %s errors\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) stats->nr_auxtrace_errors[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) auxtrace_error_name(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) int perf_event__process_auxtrace_error(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) union perf_event *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if (auxtrace__dont_decode(session))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) perf_event__fprintf_auxtrace_error(event, stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) static int __auxtrace_mmap__read(struct mmap *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) struct perf_tool *tool, process_auxtrace_t fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) bool snapshot, size_t snapshot_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) struct auxtrace_mmap *mm = &map->auxtrace_mmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) u64 head, old = mm->prev, offset, ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) unsigned char *data = mm->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) size_t size, head_off, old_off, len1, len2, padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) union perf_event ev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) void *data1, *data2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) if (snapshot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) head = auxtrace_mmap__read_snapshot_head(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) if (auxtrace_record__find_snapshot(itr, mm->idx, mm, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) &head, &old))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) head = auxtrace_mmap__read_head(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (old == head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) pr_debug3("auxtrace idx %d old %#"PRIx64" head %#"PRIx64" diff %#"PRIx64"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) mm->idx, old, head, head - old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) if (mm->mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) head_off = head & mm->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) old_off = old & mm->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) head_off = head % mm->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) old_off = old % mm->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) if (head_off > old_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) size = head_off - old_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) size = mm->len - (old_off - head_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) if (snapshot && size > snapshot_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) size = snapshot_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) ref = auxtrace_record__reference(itr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) if (head > old || size <= head || mm->mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) offset = head - size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * When the buffer size is not a power of 2, 'head' wraps at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) * highest multiple of the buffer size, so we have to subtract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) * the remainder here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) u64 rem = (0ULL - mm->len) % mm->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) offset = head - size - rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) if (size > head_off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) len1 = size - head_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) data1 = &data[mm->len - len1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) len2 = head_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) data2 = &data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) len1 = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) data1 = &data[head_off - len1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) len2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) data2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) if (itr->alignment) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) unsigned int unwanted = len1 % itr->alignment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) len1 -= unwanted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) size -= unwanted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) /* padding must be written by fn() e.g. record__process_auxtrace() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) padding = size & (PERF_AUXTRACE_RECORD_ALIGNMENT - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) if (padding)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) padding = PERF_AUXTRACE_RECORD_ALIGNMENT - padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) memset(&ev, 0, sizeof(ev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) ev.auxtrace.header.type = PERF_RECORD_AUXTRACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) ev.auxtrace.header.size = sizeof(ev.auxtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) ev.auxtrace.size = size + padding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) ev.auxtrace.offset = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) ev.auxtrace.reference = ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) ev.auxtrace.idx = mm->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) ev.auxtrace.tid = mm->tid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) ev.auxtrace.cpu = mm->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) if (fn(tool, map, &ev, data1, len1, data2, len2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) mm->prev = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) if (!snapshot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) auxtrace_mmap__write_tail(mm, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) if (itr->read_finish) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) err = itr->read_finish(itr, mm->idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) int auxtrace_mmap__read(struct mmap *map, struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) struct perf_tool *tool, process_auxtrace_t fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) return __auxtrace_mmap__read(map, itr, tool, fn, false, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) int auxtrace_mmap__read_snapshot(struct mmap *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) struct auxtrace_record *itr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) struct perf_tool *tool, process_auxtrace_t fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) size_t snapshot_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) return __auxtrace_mmap__read(map, itr, tool, fn, true, snapshot_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) * struct auxtrace_cache - hash table to implement a cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) * @hashtable: the hashtable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) * @sz: hashtable size (number of hlists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) * @entry_size: size of an entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) * @limit: limit the number of entries to this maximum, when reached the cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) * is dropped and caching begins again with an empty cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) * @cnt: current number of entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) * @bits: hashtable size (@sz = 2^@bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) struct auxtrace_cache {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) struct hlist_head *hashtable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) size_t sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) size_t entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) size_t limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) size_t cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) unsigned int bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) struct auxtrace_cache *auxtrace_cache__new(unsigned int bits, size_t entry_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) unsigned int limit_percent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) struct auxtrace_cache *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) struct hlist_head *ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) size_t sz, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) c = zalloc(sizeof(struct auxtrace_cache));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) sz = 1UL << bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) ht = calloc(sz, sizeof(struct hlist_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) if (!ht)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) for (i = 0; i < sz; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) INIT_HLIST_HEAD(&ht[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) c->hashtable = ht;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) c->sz = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) c->entry_size = entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) c->limit = (c->sz * limit_percent) / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) c->bits = bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) free(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) static void auxtrace_cache__drop(struct auxtrace_cache *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) struct auxtrace_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) struct hlist_node *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) for (i = 0; i < c->sz; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) hlist_for_each_entry_safe(entry, tmp, &c->hashtable[i], hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) hlist_del(&entry->hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) auxtrace_cache__free_entry(c, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) c->cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) void auxtrace_cache__free(struct auxtrace_cache *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) auxtrace_cache__drop(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) zfree(&c->hashtable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) free(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) void *auxtrace_cache__alloc_entry(struct auxtrace_cache *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) return malloc(c->entry_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) void auxtrace_cache__free_entry(struct auxtrace_cache *c __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) void *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) free(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) int auxtrace_cache__add(struct auxtrace_cache *c, u32 key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) struct auxtrace_cache_entry *entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if (c->limit && ++c->cnt > c->limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) auxtrace_cache__drop(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) entry->key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) hlist_add_head(&entry->hash, &c->hashtable[hash_32(key, c->bits)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) static struct auxtrace_cache_entry *auxtrace_cache__rm(struct auxtrace_cache *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) u32 key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) struct auxtrace_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) struct hlist_head *hlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) struct hlist_node *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) hlist = &c->hashtable[hash_32(key, c->bits)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) hlist_for_each_entry_safe(entry, n, hlist, hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) if (entry->key == key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) hlist_del(&entry->hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) void auxtrace_cache__remove(struct auxtrace_cache *c, u32 key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) struct auxtrace_cache_entry *entry = auxtrace_cache__rm(c, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) auxtrace_cache__free_entry(c, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) struct auxtrace_cache_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) struct hlist_head *hlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) if (!c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) hlist = &c->hashtable[hash_32(key, c->bits)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) hlist_for_each_entry(entry, hlist, hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) if (entry->key == key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) static void addr_filter__free_str(struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) zfree(&filt->str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) filt->action = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) filt->sym_from = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) filt->sym_to = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) filt->filename = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) static struct addr_filter *addr_filter__new(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) struct addr_filter *filt = zalloc(sizeof(*filt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) if (filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) INIT_LIST_HEAD(&filt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) return filt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) static void addr_filter__free(struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) if (filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) addr_filter__free_str(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) free(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) static void addr_filters__add(struct addr_filters *filts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) list_add_tail(&filt->list, &filts->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) filts->cnt += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) static void addr_filters__del(struct addr_filters *filts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) list_del_init(&filt->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) filts->cnt -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) void addr_filters__init(struct addr_filters *filts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) INIT_LIST_HEAD(&filts->head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) filts->cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) void addr_filters__exit(struct addr_filters *filts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) struct addr_filter *filt, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) list_for_each_entry_safe(filt, n, &filts->head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) addr_filters__del(filts, filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) addr_filter__free(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) static int parse_num_or_str(char **inp, u64 *num, const char **str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) const char *str_delim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) *inp += strspn(*inp, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) if (isdigit(**inp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) char *endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) if (!num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) *num = strtoull(*inp, &endptr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) if (endptr == *inp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) *inp = endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) size_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) if (!str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) *inp += strspn(*inp, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) *str = *inp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) n = strcspn(*inp, str_delim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) if (!n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) *inp += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) if (**inp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) **inp = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) *inp += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) static int parse_action(struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) if (!strcmp(filt->action, "filter")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) filt->start = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) filt->range = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) } else if (!strcmp(filt->action, "start")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) filt->start = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) } else if (!strcmp(filt->action, "stop")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) filt->start = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) } else if (!strcmp(filt->action, "tracestop")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) filt->start = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) filt->range = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) filt->action += 5; /* Change 'tracestop' to 'stop' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) static int parse_sym_idx(char **inp, int *idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) *idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) *inp += strspn(*inp, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) if (**inp != '#')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) *inp += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) if (**inp == 'g' || **inp == 'G') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) *inp += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) *idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) unsigned long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) char *endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) num = strtoul(*inp, &endptr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if (errno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) if (endptr == *inp || num > INT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) *inp = endptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) *idx = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) static int parse_addr_size(char **inp, u64 *num, const char **str, int *idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) int err = parse_num_or_str(inp, num, str, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) if (!err && *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) err = parse_sym_idx(inp, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) static int parse_one_filter(struct addr_filter *filt, const char **filter_inp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) char *fstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) filt->str = fstr = strdup(*filter_inp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) if (!fstr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) err = parse_num_or_str(&fstr, NULL, &filt->action, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) err = parse_action(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) err = parse_addr_size(&fstr, &filt->addr, &filt->sym_from,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) &filt->sym_from_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) fstr += strspn(fstr, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) if (*fstr == '/') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) fstr += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) err = parse_addr_size(&fstr, &filt->size, &filt->sym_to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) &filt->sym_to_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) filt->range = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) fstr += strspn(fstr, " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) if (*fstr == '@') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) fstr += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) err = parse_num_or_str(&fstr, NULL, &filt->filename, " ,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) fstr += strspn(fstr, " ,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) *filter_inp += fstr - filt->str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) addr_filter__free_str(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) int addr_filters__parse_bare_filter(struct addr_filters *filts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) const char *filter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) struct addr_filter *filt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) const char *fstr = filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) while (*fstr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) filt = addr_filter__new();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) err = parse_one_filter(filt, &fstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) addr_filter__free(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) addr_filters__exit(filts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) addr_filters__add(filts, filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) struct sym_args {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) u64 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) u64 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) bool started;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) bool global;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) bool selected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) bool duplicate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) bool near;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) static bool kern_sym_match(struct sym_args *args, const char *name, char type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) /* A function with the same name, and global or the n'th found or any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) return kallsyms__is_function(type) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) !strcmp(name, args->name) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) ((args->global && isupper(type)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) (args->selected && ++(args->cnt) == args->idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) (!args->global && !args->selected));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) static int find_kern_sym_cb(void *arg, const char *name, char type, u64 start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) struct sym_args *args = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) if (args->started) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) if (!args->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) args->size = start - args->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) if (args->selected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) if (args->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) } else if (kern_sym_match(args, name, type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) args->duplicate = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) } else if (kern_sym_match(args, name, type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) args->started = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) args->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) static int print_kern_sym_cb(void *arg, const char *name, char type, u64 start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) struct sym_args *args = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) if (kern_sym_match(args, name, type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) ++args->cnt, start, type, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) args->near = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) } else if (args->near) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) args->near = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) pr_err("\t\twhich is near\t\t%s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) static int sym_not_found_error(const char *sym_name, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) if (idx > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) pr_err("N'th occurrence (N=%d) of symbol '%s' not found.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) idx, sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) } else if (!idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) pr_err("Global symbol '%s' not found.\n", sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) pr_err("Symbol '%s' not found.\n", sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) pr_err("Note that symbols must be functions.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) static int find_kern_sym(const char *sym_name, u64 *start, u64 *size, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) struct sym_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) .name = sym_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) .idx = idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) .global = !idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) .selected = idx > 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) *start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) *size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) err = kallsyms__parse("/proc/kallsyms", &args, find_kern_sym_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) pr_err("Failed to parse /proc/kallsyms\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) if (args.duplicate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) pr_err("Multiple kernel symbols with name '%s'\n", sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) args.cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) kallsyms__parse("/proc/kallsyms", &args, print_kern_sym_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) if (!args.started) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) pr_err("Kernel symbol lookup: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) return sym_not_found_error(sym_name, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) *start = args.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) *size = args.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) char type, u64 start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) struct sym_args *args = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) if (!kallsyms__is_function(type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) if (!args->started) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) args->started = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) args->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) /* Don't know exactly where the kernel ends, so we add a page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) args->size = round_up(start, page_size) + page_size - args->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) static int addr_filter__entire_kernel(struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) struct sym_args args = { .started = false };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) err = kallsyms__parse("/proc/kallsyms", &args, find_entire_kern_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) if (err < 0 || !args.started) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) pr_err("Failed to parse /proc/kallsyms\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) filt->addr = args.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) filt->size = args.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) static int check_end_after_start(struct addr_filter *filt, u64 start, u64 size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) if (start + size >= filt->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) if (filt->sym_from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) pr_err("Symbol '%s' (0x%"PRIx64") comes before '%s' (0x%"PRIx64")\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) filt->sym_to, start, filt->sym_from, filt->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) pr_err("Symbol '%s' (0x%"PRIx64") comes before address 0x%"PRIx64")\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) filt->sym_to, start, filt->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) bool no_size = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) u64 start, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) if (symbol_conf.kptr_restrict) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) pr_err("Kernel addresses are restricted. Unable to resolve kernel symbols.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) if (filt->sym_from && !strcmp(filt->sym_from, "*"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) return addr_filter__entire_kernel(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) if (filt->sym_from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) err = find_kern_sym(filt->sym_from, &start, &size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) filt->sym_from_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) filt->addr = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) if (filt->range && !filt->size && !filt->sym_to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) filt->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) no_size = !size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) if (filt->sym_to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) err = find_kern_sym(filt->sym_to, &start, &size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) filt->sym_to_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) err = check_end_after_start(filt, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) filt->size = start + size - filt->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) no_size = !size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) /* The very last symbol in kallsyms does not imply a particular size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) if (no_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) pr_err("Cannot determine size of symbol '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) filt->sym_to ? filt->sym_to : filt->sym_from);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) static struct dso *load_dso(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) struct map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) struct dso *dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) map = dso__new_map(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) if (!map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) if (map__load(map) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) pr_err("File '%s' not found or has no symbols.\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) dso = dso__get(map->dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) map__put(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) return dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) /* Same name, and global or the n'th found or any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) return !arch__compare_symbol_names(name, sym->name) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) ((!idx && sym->binding == STB_GLOBAL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) (idx > 0 && ++*cnt == idx) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) idx < 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) static void print_duplicate_syms(struct dso *dso, const char *sym_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) struct symbol *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) bool near = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) int cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) pr_err("Multiple symbols with name '%s'\n", sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) sym = dso__first_symbol(dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) while (sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) if (dso_sym_match(sym, sym_name, &cnt, -1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) ++cnt, sym->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) sym->binding == STB_GLOBAL ? 'g' :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) sym->binding == STB_LOCAL ? 'l' : 'w',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) near = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) } else if (near) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) near = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) pr_err("\t\twhich is near\t\t%s\n", sym->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) sym = dso__next_symbol(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) u64 *size, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) struct symbol *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) int cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) *start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) *size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) sym = dso__first_symbol(dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) while (sym) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) if (*start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) if (!*size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) *size = sym->start - *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) if (idx > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) if (*size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) print_duplicate_syms(dso, sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) *start = sym->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) *size = sym->end - sym->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) sym = dso__next_symbol(sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) if (!*start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) return sym_not_found_error(sym_name, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) if (dso__data_file_size(dso, NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) pr_err("Failed to determine filter for %s\nCannot determine file size.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) filt->filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) filt->addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) filt->size = dso->data.file_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) static int addr_filter__resolve_syms(struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) u64 start, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) struct dso *dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) if (!filt->sym_from && !filt->sym_to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) if (!filt->filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) return addr_filter__resolve_kernel_syms(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) dso = load_dso(filt->filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) if (!dso) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) pr_err("Failed to load symbols from: %s\n", filt->filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) if (filt->sym_from && !strcmp(filt->sym_from, "*")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) err = addr_filter__entire_dso(filt, dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) goto put_dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) if (filt->sym_from) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) err = find_dso_sym(dso, filt->sym_from, &start, &size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) filt->sym_from_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) goto put_dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) filt->addr = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) if (filt->range && !filt->size && !filt->sym_to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) filt->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) if (filt->sym_to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) err = find_dso_sym(dso, filt->sym_to, &start, &size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) filt->sym_to_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) goto put_dso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) err = check_end_after_start(filt, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) filt->size = start + size - filt->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) put_dso:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) dso__put(dso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) static char *addr_filter__to_str(struct addr_filter *filt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) char filename_buf[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) const char *at = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) const char *fn = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) char *filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) if (filt->filename) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) at = "@";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) fn = realpath(filt->filename, filename_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) if (!fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) if (filt->range) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) err = asprintf(&filter, "%s 0x%"PRIx64"/0x%"PRIx64"%s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) filt->action, filt->addr, filt->size, at, fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) err = asprintf(&filter, "%s 0x%"PRIx64"%s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) filt->action, filt->addr, at, fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) return err < 0 ? NULL : filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) static int parse_addr_filter(struct evsel *evsel, const char *filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) int max_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) struct addr_filters filts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) struct addr_filter *filt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) addr_filters__init(&filts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) err = addr_filters__parse_bare_filter(&filts, filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) goto out_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) if (filts.cnt > max_nr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) pr_err("Error: number of address filters (%d) exceeds maximum (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) filts.cnt, max_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) goto out_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) list_for_each_entry(filt, &filts.head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) char *new_filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) err = addr_filter__resolve_syms(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) goto out_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) new_filter = addr_filter__to_str(filt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) if (!new_filter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) goto out_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) if (evsel__append_addr_filter(evsel, new_filter)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) goto out_exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) out_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) addr_filters__exit(&filts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) pr_err("Failed to parse address filter: '%s'\n", filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) pr_err("Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [@<file name>]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) pr_err("Where multiple filters are separated by space or comma.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) static int evsel__nr_addr_filter(struct evsel *evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) struct perf_pmu *pmu = evsel__find_pmu(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) int nr_addr_filters = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) if (!pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) perf_pmu__scan_file(pmu, "nr_addr_filters", "%d", &nr_addr_filters);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) return nr_addr_filters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) int auxtrace_parse_filters(struct evlist *evlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) char *filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) int err, max_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) filter = evsel->filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) max_nr = evsel__nr_addr_filter(evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) if (!filter || !max_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) evsel->filter = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) err = parse_addr_filter(evsel, filter, max_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) free(filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) pr_debug("Address filter: %s\n", evsel->filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) int auxtrace__process_event(struct perf_session *session, union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) struct perf_sample *sample, struct perf_tool *tool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) if (!session->auxtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) return session->auxtrace->process_event(session, event, sample, tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) void auxtrace__dump_auxtrace_sample(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) if (!session->auxtrace || !session->auxtrace->dump_auxtrace_sample ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) auxtrace__dont_decode(session))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) session->auxtrace->dump_auxtrace_sample(session, sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) int auxtrace__flush_events(struct perf_session *session, struct perf_tool *tool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) if (!session->auxtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) return session->auxtrace->flush_events(session, tool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) void auxtrace__free_events(struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) if (!session->auxtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) return session->auxtrace->free_events(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) void auxtrace__free(struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) if (!session->auxtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) return session->auxtrace->free(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) bool auxtrace__evsel_is_auxtrace(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) struct evsel *evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) if (!session->auxtrace || !session->auxtrace->evsel_is_auxtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) return session->auxtrace->evsel_is_auxtrace(session, evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) }