#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"
#include "pmu.h"
#include "thread_map.h"
-#include "cpumap.h"
#include "probe-file.h"
#include "asm/bug.h"
#include "util/parse-branch-options.h"
#include "metricgroup.h"
+#include "util/evsel_config.h"
+#include "util/event.h"
#define MAX_NAME_LEN 100
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);
return NULL;
(*idx)++;
- evsel->cpus = cpu_map__get(cpus);
- evsel->own_cpus = cpu_map__get(cpus);
- evsel->system_wide = pmu ? pmu->is_uncore : false;
+ evsel->core.cpus = perf_cpu_map__get(cpus);
+ evsel->core.own_cpus = perf_cpu_map__get(cpus);
+ evsel->core.system_wide = pmu ? pmu->is_uncore : false;
evsel->auto_merge_stats = auto_merge_stats;
if (name)
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;
}
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,
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)) {
list_splice(&config_terms, &evsel->config_terms);
}
- list_add_tail(&evsel->node, list);
+ list_add_tail(&evsel->core.node, list);
return 0;
}
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);
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;
[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;
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;
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) {
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;
}
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);
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));
__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;
}
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");
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;
}
};
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;
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)
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;
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)
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,
};
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");
perf_evlist__splice_list_tail(evlist, &parse_state.list);
evlist->nr_groups += parse_state.nr_groups;
- last = perf_evlist__last(evlist);
+ last = evlist__last(evlist);
last->cmdline_group_boundary = true;
return 0;
/*
* 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;
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);
}
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;
/*
*
* So no need to WARN here, let *func do this.
*/
- if (evlist->nr_entries > 0)
- last = perf_evlist__last(evlist);
+ if (evlist->core.nr_entries > 0)
+ last = evlist__last(evlist);
do {
err = (*func)(last, arg);
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;
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");
}
while ((pmu = perf_pmu__scan(pmu)) != NULL)
- if (pmu->type == evsel->attr.type) {
+ if (pmu->type == evsel->core.attr.type) {
found = true;
break;
}
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;
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);
{
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) {
* 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;
}