diff options
Diffstat (limited to 'tools/perf/util/pfm.c')
| -rw-r--r-- | tools/perf/util/pfm.c | 88 |
1 files changed, 69 insertions, 19 deletions
diff --git a/tools/perf/util/pfm.c b/tools/perf/util/pfm.c index ac3227ba769c..d9043f4afbe7 100644 --- a/tools/perf/util/pfm.c +++ b/tools/perf/util/pfm.c @@ -10,10 +10,12 @@ #include "util/evlist.h" #include "util/evsel.h" #include "util/parse-events.h" -#include "util/pmu.h" +#include "util/pmus.h" #include "util/pfm.h" #include "util/strbuf.h" +#include "util/thread_map.h" +#include <errno.h> #include <string.h> #include <linux/kernel.h> #include <perfmon/pfmlib_perf_event.h> @@ -46,10 +48,6 @@ int parse_libpfm_events_option(const struct option *opt, const char *str, p_orig = p = strdup(str); if (!p) return -1; - /* - * force loading of the PMU list - */ - perf_pmu__scan(NULL); for (q = p; strsep(&p, ",{}"); q = p) { sep = p ? str + (p - p_orig - 1) : ""; @@ -86,7 +84,7 @@ int parse_libpfm_events_option(const struct option *opt, const char *str, goto error; } - pmu = perf_pmu__find_by_type((unsigned int)attr.type); + pmu = perf_pmus__find_by_type((unsigned int)attr.type); evsel = parse_events__add_event(evlist->core.nr_entries, &attr, q, /*metric_id=*/NULL, pmu); @@ -112,7 +110,6 @@ int parse_libpfm_events_option(const struct option *opt, const char *str, "cannot close a non-existing event group\n"); goto error; } - evlist->core.nr_groups++; grp_leader = NULL; grp_evt = -1; } @@ -124,6 +121,49 @@ error: return -1; } +static bool is_libpfm_event_supported(const char *name, struct perf_cpu_map *cpus, + struct perf_thread_map *threads) +{ + struct perf_pmu *pmu; + struct evsel *evsel; + struct perf_event_attr attr = {}; + bool result = true; + int ret; + + ret = pfm_get_perf_event_encoding(name, PFM_PLM0|PFM_PLM3, + &attr, NULL, NULL); + if (ret != PFM_SUCCESS) + return false; + + pmu = perf_pmus__find_by_type((unsigned int)attr.type); + evsel = parse_events__add_event(0, &attr, name, /*metric_id=*/NULL, pmu); + if (evsel == NULL) + return false; + + evsel->is_libpfm_event = true; + + ret = evsel__open(evsel, cpus, threads); + if (ret == -EACCES) { + /* + * This happens if the paranoid value + * /proc/sys/kernel/perf_event_paranoid is set to 2 + * Re-run with exclude_kernel set; we don't do that + * by default as some ARM machines do not support it. + * + */ + evsel->core.attr.exclude_kernel = 1; + ret = evsel__open(evsel, cpus, threads); + + } + if (ret < 0) + result = false; + + evsel__close(evsel); + evsel__delete(evsel); + + return result; +} + static const char *srcs[PFM_ATTR_CTRL_MAX] = { [PFM_ATTR_CTRL_UNKNOWN] = "???", [PFM_ATTR_CTRL_PMU] = "PMU", @@ -147,6 +187,8 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state, { int j, ret; char topic[80], name[80]; + struct perf_cpu_map *cpus = perf_cpu_map__empty_new(1); + struct perf_thread_map *threads = thread_map__new_by_tid(0); strbuf_setlen(buf, 0); snprintf(topic, sizeof(topic), "pfm %s", pinfo->name); @@ -186,15 +228,16 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state, ainfo.name, ainfo.desc); } } - print_cb->print_event(print_state, - pinfo->name, - topic, - name, info->equiv, - /*scale_unit=*/NULL, - /*deprecated=*/NULL, "PFM event", - info->desc, /*long_desc=*/NULL, - /*encoding_desc=*/buf->buf, - /*metric_name=*/NULL, /*metric_expr=*/NULL); + + if (is_libpfm_event_supported(name, cpus, threads)) { + print_cb->print_event(print_state, topic, pinfo->name, + /*pmu_type=*/PERF_TYPE_RAW, + name, info->equiv, + /*scale_unit=*/NULL, + /*deprecated=*/NULL, "PFM event", + info->desc, /*long_desc=*/NULL, + /*encoding_desc=*/buf->buf); + } pfm_for_each_event_attr(j, info) { pfm_event_attr_info_t ainfo; @@ -217,17 +260,24 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state, print_attr_flags(buf, &ainfo); snprintf(name, sizeof(name), "%s::%s:%s", pinfo->name, info->name, ainfo.name); + + if (!is_libpfm_event_supported(name, cpus, threads)) + continue; + print_cb->print_event(print_state, - pinfo->name, topic, + pinfo->name, + /*pmu_type=*/PERF_TYPE_RAW, name, /*alias=*/NULL, /*scale_unit=*/NULL, /*deprecated=*/NULL, "PFM event", ainfo.desc, /*long_desc=*/NULL, - /*encoding_desc=*/buf->buf, - /*metric_name=*/NULL, /*metric_expr=*/NULL); + /*encoding_desc=*/buf->buf); } } + + perf_cpu_map__put(cpus); + perf_thread_map__put(threads); } void print_libpfm_events(const struct print_callbacks *print_cb, void *print_state) |
