diff options
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 167 |
1 files changed, 93 insertions, 74 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 371ff3aee769..5ec21d21113c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -10,20 +10,21 @@ #include <fcntl.h> #include <sys/param.h> #include "term.h" -#include "../perf.h" +#include "build-id.h" #include "evlist.h" #include "evsel.h" +#include <subcmd/pager.h> #include <subcmd/parse-options.h> #include "parse-events.h" #include <subcmd/exec-cmd.h> #include "string2.h" #include "strlist.h" #include "symbol.h" -#include "cache.h" #include "header.h" #include "bpf-loader.h" #include "debug.h" #include <api/fs/tracing_path.h> +#include <perf/cpumap.h> #include "parse-events-bison.h" #define YY_EXTRA_TYPE int #include "parse-events-flex.h" @@ -314,16 +315,16 @@ static char *get_config_name(struct list_head *head_terms) return NULL; } -static struct perf_evsel * +static struct evsel * __add_event(struct list_head *list, int *idx, struct perf_event_attr *attr, char *name, struct perf_pmu *pmu, struct list_head *config_terms, bool auto_merge_stats, const char *cpu_list) { - struct perf_evsel *evsel; - struct cpu_map *cpus = pmu ? pmu->cpus : - cpu_list ? cpu_map__new(cpu_list) : NULL; + struct evsel *evsel; + struct perf_cpu_map *cpus = pmu ? pmu->cpus : + cpu_list ? perf_cpu_map__new(cpu_list) : NULL; event_attr_init(attr); @@ -332,8 +333,8 @@ __add_event(struct list_head *list, int *idx, return NULL; (*idx)++; - evsel->cpus = cpu_map__get(cpus); - evsel->own_cpus = cpu_map__get(cpus); + evsel->core.cpus = perf_cpu_map__get(cpus); + evsel->core.own_cpus = perf_cpu_map__get(cpus); evsel->system_wide = pmu ? pmu->is_uncore : false; evsel->auto_merge_stats = auto_merge_stats; @@ -343,7 +344,7 @@ __add_event(struct list_head *list, int *idx, if (config_terms) list_splice(config_terms, &evsel->config_terms); - list_add_tail(&evsel->node, list); + list_add_tail(&evsel->core.node, list); return evsel; } @@ -357,7 +358,7 @@ static int add_event(struct list_head *list, int *idx, static int add_event_tool(struct list_head *list, int *idx, enum perf_tool_event tool_event) { - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_DUMMY, @@ -510,7 +511,7 @@ static int add_tracepoint(struct list_head *list, int *idx, struct parse_events_error *err, struct list_head *head_config) { - struct perf_evsel *evsel; + struct evsel *evsel; evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); if (IS_ERR(evsel)) { @@ -526,7 +527,7 @@ static int add_tracepoint(struct list_head *list, int *idx, list_splice(&config_terms, &evsel->config_terms); } - list_add_tail(&evsel->node, list); + list_add_tail(&evsel->core.node, list); return 0; } @@ -630,15 +631,24 @@ struct __add_bpf_event_param { struct list_head *head_config; }; -static int add_bpf_event(const char *group, const char *event, int fd, +static int add_bpf_event(const char *group, const char *event, int fd, struct bpf_object *obj, void *_param) { LIST_HEAD(new_evsels); struct __add_bpf_event_param *param = _param; struct parse_events_state *parse_state = param->parse_state; struct list_head *list = param->list; - struct perf_evsel *pos; + struct evsel *pos; int err; + /* + * Check if we should add the event, i.e. if it is a TP but starts with a '!', + * then don't add the tracepoint, this will be used for something else, like + * adding to a BPF_MAP_TYPE_PROG_ARRAY. + * + * See tools/perf/examples/bpf/augmented_raw_syscalls.c + */ + if (group[0] == '!') + return 0; pr_debug("add bpf event %s:%s and attach bpf program %d\n", group, event, fd); @@ -647,22 +657,23 @@ static int add_bpf_event(const char *group, const char *event, int fd, event, parse_state->error, param->head_config); if (err) { - struct perf_evsel *evsel, *tmp; + struct evsel *evsel, *tmp; pr_debug("Failed to add BPF event %s:%s\n", group, event); - list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { - list_del_init(&evsel->node); - perf_evsel__delete(evsel); + list_for_each_entry_safe(evsel, tmp, &new_evsels, core.node) { + list_del_init(&evsel->core.node); + evsel__delete(evsel); } return err; } pr_debug("adding %s:%s\n", group, event); - list_for_each_entry(pos, &new_evsels, node) { + list_for_each_entry(pos, &new_evsels, core.node) { pr_debug("adding %s:%s to %p\n", group, event, pos); pos->bpf_fd = fd; + pos->bpf_obj = obj; } list_splice(&new_evsels, list); return 0; @@ -952,6 +963,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", + [PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT] = "aux-output", }; static bool config_term_shrinked; @@ -1072,6 +1084,9 @@ do { \ return -EINVAL; } break; + case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: + CHECK_TYPE_VAL(NUM); + break; default: err->str = strdup("unknown term"); err->idx = term->err_term; @@ -1122,6 +1137,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr, case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: case PARSE_EVENTS__TERM_TYPE_OVERWRITE: case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: + case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: return config_term_common(attr, term, err); default: if (err) { @@ -1214,6 +1230,9 @@ do { \ ADD_CONFIG_TERM(PERCORE, percore, term->val.num ? true : false); break; + case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: + ADD_CONFIG_TERM(AUX_OUTPUT, aux_output, term->val.num ? 1 : 0); + break; default: break; } @@ -1296,7 +1315,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, struct perf_event_attr attr; struct perf_pmu_info info; struct perf_pmu *pmu; - struct perf_evsel *evsel; + struct evsel *evsel; struct parse_events_error *err = parse_state->error; bool use_uncore_alias; LIST_HEAD(config_terms); @@ -1443,13 +1462,13 @@ static int parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, struct parse_events_state *parse_state) { - struct perf_evsel *evsel, *leader; + struct evsel *evsel, *leader; uintptr_t *leaders; bool is_leader = true; int i, nr_pmu = 0, total_members, ret = 0; - leader = list_first_entry(list, struct perf_evsel, node); - evsel = list_last_entry(list, struct perf_evsel, node); + leader = list_first_entry(list, struct evsel, core.node); + evsel = list_last_entry(list, struct evsel, core.node); total_members = evsel->idx - leader->idx + 1; leaders = calloc(total_members, sizeof(uintptr_t)); @@ -1511,13 +1530,13 @@ parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, __evlist__for_each_entry(list, evsel) { if (i >= nr_pmu) i = 0; - evsel->leader = (struct perf_evsel *) leaders[i++]; + evsel->leader = (struct evsel *) leaders[i++]; } /* The number of members and group name are same for each group */ for (i = 0; i < nr_pmu; i++) { - evsel = (struct perf_evsel *) leaders[i]; - evsel->nr_members = total_members / nr_pmu; + evsel = (struct evsel *) leaders[i]; + evsel->core.nr_members = total_members / nr_pmu; evsel->group_name = name ? strdup(name) : NULL; } @@ -1534,7 +1553,7 @@ out: void parse_events__set_leader(char *name, struct list_head *list, struct parse_events_state *parse_state) { - struct perf_evsel *leader; + struct evsel *leader; if (list_empty(list)) { WARN_ONCE(true, "WARNING: failed to set leader: empty list"); @@ -1545,7 +1564,7 @@ void parse_events__set_leader(char *name, struct list_head *list, return; __perf_evlist__set_leader(list); - leader = list_entry(list->next, struct perf_evsel, node); + leader = list_entry(list->next, struct evsel, core.node); leader->group_name = name ? strdup(name) : NULL; } @@ -1578,18 +1597,18 @@ struct event_modifier { }; static int get_event_modifier(struct event_modifier *mod, char *str, - struct perf_evsel *evsel) -{ - int eu = evsel ? evsel->attr.exclude_user : 0; - int ek = evsel ? evsel->attr.exclude_kernel : 0; - int eh = evsel ? evsel->attr.exclude_hv : 0; - int eH = evsel ? evsel->attr.exclude_host : 0; - int eG = evsel ? evsel->attr.exclude_guest : 0; - int eI = evsel ? evsel->attr.exclude_idle : 0; - int precise = evsel ? evsel->attr.precise_ip : 0; + struct evsel *evsel) +{ + int eu = evsel ? evsel->core.attr.exclude_user : 0; + int ek = evsel ? evsel->core.attr.exclude_kernel : 0; + int eh = evsel ? evsel->core.attr.exclude_hv : 0; + int eH = evsel ? evsel->core.attr.exclude_host : 0; + int eG = evsel ? evsel->core.attr.exclude_guest : 0; + int eI = evsel ? evsel->core.attr.exclude_idle : 0; + int precise = evsel ? evsel->core.attr.precise_ip : 0; int precise_max = 0; int sample_read = 0; - int pinned = evsel ? evsel->attr.pinned : 0; + int pinned = evsel ? evsel->core.attr.pinned : 0; int exclude = eu | ek | eh; int exclude_GH = evsel ? evsel->exclude_GH : 0; @@ -1691,7 +1710,7 @@ static int check_modifier(char *str) int parse_events__modifier_event(struct list_head *list, char *str, bool add) { - struct perf_evsel *evsel; + struct evsel *evsel; struct event_modifier mod; if (str == NULL) @@ -1707,20 +1726,20 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) if (add && get_event_modifier(&mod, str, evsel)) return -EINVAL; - evsel->attr.exclude_user = mod.eu; - evsel->attr.exclude_kernel = mod.ek; - evsel->attr.exclude_hv = mod.eh; - evsel->attr.precise_ip = mod.precise; - evsel->attr.exclude_host = mod.eH; - evsel->attr.exclude_guest = mod.eG; - evsel->attr.exclude_idle = mod.eI; + evsel->core.attr.exclude_user = mod.eu; + evsel->core.attr.exclude_kernel = mod.ek; + evsel->core.attr.exclude_hv = mod.eh; + evsel->core.attr.precise_ip = mod.precise; + evsel->core.attr.exclude_host = mod.eH; + evsel->core.attr.exclude_guest = mod.eG; + evsel->core.attr.exclude_idle = mod.eI; evsel->exclude_GH = mod.exclude_GH; evsel->sample_read = mod.sample_read; evsel->precise_max = mod.precise_max; evsel->weak_group = mod.weak; if (perf_evsel__is_group_leader(evsel)) - evsel->attr.pinned = mod.pinned; + evsel->core.attr.pinned = mod.pinned; } return 0; @@ -1728,7 +1747,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) int parse_events_name(struct list_head *list, char *name) { - struct perf_evsel *evsel; + struct evsel *evsel; __evlist__for_each_entry(list, evsel) { if (!evsel->name) @@ -1894,12 +1913,12 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct perf_evlist *evlist, const char *str, +int parse_events(struct evlist *evlist, const char *str, struct parse_events_error *err) { struct parse_events_state parse_state = { .list = LIST_HEAD_INIT(parse_state.list), - .idx = evlist->nr_entries, + .idx = evlist->core.nr_entries, .error = err, .evlist = evlist, }; @@ -1908,7 +1927,7 @@ int parse_events(struct perf_evlist *evlist, const char *str, ret = parse_events__scanner(str, &parse_state, PE_START_EVENTS); perf_pmu__parse_cleanup(); if (!ret) { - struct perf_evsel *last; + struct evsel *last; if (list_empty(&parse_state.list)) { WARN_ONCE(true, "WARNING: event parser found nothing\n"); @@ -1925,7 +1944,7 @@ int parse_events(struct perf_evlist *evlist, const char *str, /* * There are 2 users - builtin-record and builtin-test objects. - * Both call perf_evlist__delete in case of error, so we dont + * Both call evlist__delete in case of error, so we dont * need to bother. */ return ret; @@ -2003,7 +2022,7 @@ void parse_events_print_error(struct parse_events_error *err, int parse_events_option(const struct option *opt, const char *str, int unset __maybe_unused) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct evlist *evlist = *(struct evlist **)opt->value; struct parse_events_error err = { .idx = 0, }; int ret = parse_events(evlist, str, &err); @@ -2016,12 +2035,12 @@ int parse_events_option(const struct option *opt, const char *str, } static int -foreach_evsel_in_last_glob(struct perf_evlist *evlist, - int (*func)(struct perf_evsel *evsel, +foreach_evsel_in_last_glob(struct evlist *evlist, + int (*func)(struct evsel *evsel, const void *arg), const void *arg) { - struct perf_evsel *last = NULL; + struct evsel *last = NULL; int err; /* @@ -2030,7 +2049,7 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist, * * So no need to WARN here, let *func do this. */ - if (evlist->nr_entries > 0) + if (evlist->core.nr_entries > 0) last = perf_evlist__last(evlist); do { @@ -2040,15 +2059,15 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist, if (!last) return 0; - if (last->node.prev == &evlist->entries) + if (last->core.node.prev == &evlist->core.entries) return 0; - last = list_entry(last->node.prev, struct perf_evsel, node); + last = list_entry(last->core.node.prev, struct evsel, core.node); } while (!last->cmdline_group_boundary); return 0; } -static int set_filter(struct perf_evsel *evsel, const void *arg) +static int set_filter(struct evsel *evsel, const void *arg) { const char *str = arg; bool found = false; @@ -2061,7 +2080,7 @@ static int set_filter(struct perf_evsel *evsel, const void *arg) return -1; } - if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { if (perf_evsel__append_tp_filter(evsel, str) < 0) { fprintf(stderr, "not enough memory to hold filter string\n"); @@ -2072,7 +2091,7 @@ static int set_filter(struct perf_evsel *evsel, const void *arg) } while ((pmu = perf_pmu__scan(pmu)) != NULL) - if (pmu->type == evsel->attr.type) { + if (pmu->type == evsel->core.attr.type) { found = true; break; } @@ -2099,18 +2118,18 @@ static int set_filter(struct perf_evsel *evsel, const void *arg) int parse_filter(const struct option *opt, const char *str, int unset __maybe_unused) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct evlist *evlist = *(struct evlist **)opt->value; return foreach_evsel_in_last_glob(evlist, set_filter, (const void *)str); } -static int add_exclude_perf_filter(struct perf_evsel *evsel, +static int add_exclude_perf_filter(struct evsel *evsel, const void *arg __maybe_unused) { char new_filter[64]; - if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) { + if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { fprintf(stderr, "--exclude-perf option should follow a -e tracepoint option\n"); return -1; @@ -2131,7 +2150,7 @@ int exclude_perf(const struct option *opt, const char *arg __maybe_unused, int unset __maybe_unused) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + struct evlist *evlist = *(struct evlist **)opt->value; return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter, NULL); @@ -2297,20 +2316,20 @@ static bool is_event_supported(u8 type, unsigned config) { bool ret = true; int open_return; - struct perf_evsel *evsel; + struct evsel *evsel; struct perf_event_attr attr = { .type = type, .config = config, .disabled = 1, }; - struct thread_map *tmap = thread_map__new_by_tid(0); + struct perf_thread_map *tmap = thread_map__new_by_tid(0); if (tmap == NULL) return false; - evsel = perf_evsel__new(&attr); + evsel = evsel__new(&attr); if (evsel) { - open_return = perf_evsel__open(evsel, NULL, tmap); + open_return = evsel__open(evsel, NULL, tmap); ret = open_return >= 0; if (open_return == -EACCES) { @@ -2321,13 +2340,13 @@ static bool is_event_supported(u8 type, unsigned config) * by default as some ARM machines do not support it. * */ - evsel->attr.exclude_kernel = 1; - ret = perf_evsel__open(evsel, NULL, tmap) >= 0; + evsel->core.attr.exclude_kernel = 1; + ret = evsel__open(evsel, NULL, tmap) >= 0; } - perf_evsel__delete(evsel); + evsel__delete(evsel); } - thread_map__put(tmap); + perf_thread_map__put(tmap); return ret; } |