summaryrefslogtreecommitdiff
path: root/tools/perf/builtin-stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-stat.c')
-rw-r--r--tools/perf/builtin-stat.c77
1 files changed, 51 insertions, 26 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index cc9fa48d636f..bc45cee3f77c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -44,6 +44,7 @@
#include "util/cgroup.h"
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
+#include "util/pmus.h"
#include "util/pmu.h"
#include "util/event.h"
#include "util/evlist.h"
@@ -69,7 +70,6 @@
#include "util/pfm.h"
#include "util/bpf_counter.h"
#include "util/iostat.h"
-#include "util/pmu-hybrid.h"
#include "util/util.h"
#include "asm/bug.h"
@@ -101,6 +101,10 @@
static void print_counters(struct timespec *ts, int argc, const char **argv);
static struct evlist *evsel_list;
+static struct parse_events_option_args parse_events_option_args = {
+ .evlistp = &evsel_list,
+};
+
static bool all_counters_use_bpf = true;
static struct target target = {
@@ -667,6 +671,13 @@ static enum counter_recovery stat_handle_error(struct evsel *counter)
evsel_list->core.threads->err_thread = -1;
return COUNTER_RETRY;
}
+ } else if (counter->skippable) {
+ if (verbose > 0)
+ ui__warning("skipping event %s that kernel failed to open .\n",
+ evsel__name(counter));
+ counter->supported = false;
+ counter->errored = true;
+ return COUNTER_SKIP;
}
evsel__open_strerror(counter, &target, errno, msg, sizeof(msg));
@@ -1078,10 +1089,11 @@ static int parse_stat_cgroups(const struct option *opt,
return parse_cgroups(opt, str, unset);
}
-static int parse_hybrid_type(const struct option *opt,
+static int parse_cputype(const struct option *opt,
const char *str,
int unset __maybe_unused)
{
+ const struct perf_pmu *pmu;
struct evlist *evlist = *(struct evlist **)opt->value;
if (!list_empty(&evlist->core.entries)) {
@@ -1089,11 +1101,12 @@ static int parse_hybrid_type(const struct option *opt,
return -1;
}
- evlist->hybrid_pmu_name = perf_pmu__hybrid_type_to_pmu(str);
- if (!evlist->hybrid_pmu_name) {
+ pmu = perf_pmus__pmu_for_pmu_filter(str);
+ if (!pmu) {
fprintf(stderr, "--cputype %s is not supported!\n", str);
return -1;
}
+ parse_events_option_args.pmu_filter = pmu->name;
return 0;
}
@@ -1101,7 +1114,7 @@ static int parse_hybrid_type(const struct option *opt,
static struct option stat_options[] = {
OPT_BOOLEAN('T', "transaction", &transaction_run,
"hardware transaction statistics"),
- OPT_CALLBACK('e', "event", &evsel_list, "event",
+ OPT_CALLBACK('e', "event", &parse_events_option_args, "event",
"event selector. use 'perf list' to list available events",
parse_events_option),
OPT_CALLBACK(0, "filter", &evsel_list, "filter",
@@ -1219,7 +1232,7 @@ static struct option stat_options[] = {
OPT_CALLBACK(0, "cputype", &evsel_list, "hybrid cpu type",
"Only enable events on applying cpu with this type "
"for hybrid platform (e.g. core or atom)",
- parse_hybrid_type),
+ parse_cputype),
#ifdef HAVE_LIBPFM
OPT_CALLBACK(0, "pfm-events", &evsel_list, "event",
"libpfm4 event selector. use 'perf list' to list available events",
@@ -1770,6 +1783,7 @@ static int add_default_attributes(void)
};
struct perf_event_attr default_null_attrs[] = {};
+ const char *pmu = parse_events_option_args.pmu_filter ?: "all";
/* Set attrs if no event is selected and !null_run: */
if (stat_config.null_run)
@@ -1781,11 +1795,11 @@ static int add_default_attributes(void)
* will use this approach. To determine transaction support
* on an architecture test for such a metric name.
*/
- if (!metricgroup__has_metric("transaction")) {
+ if (!metricgroup__has_metric(pmu, "transaction")) {
pr_err("Missing transaction metrics");
return -1;
}
- return metricgroup__parse_groups(evsel_list, "transaction",
+ return metricgroup__parse_groups(evsel_list, pmu, "transaction",
stat_config.metric_no_group,
stat_config.metric_no_merge,
stat_config.metric_no_threshold,
@@ -1810,7 +1824,7 @@ static int add_default_attributes(void)
smi_reset = true;
}
- if (!metricgroup__has_metric("smi")) {
+ if (!metricgroup__has_metric(pmu, "smi")) {
pr_err("Missing smi metrics");
return -1;
}
@@ -1818,7 +1832,7 @@ static int add_default_attributes(void)
if (!force_metric_only)
stat_config.metric_only = true;
- return metricgroup__parse_groups(evsel_list, "smi",
+ return metricgroup__parse_groups(evsel_list, pmu, "smi",
stat_config.metric_no_group,
stat_config.metric_no_merge,
stat_config.metric_no_threshold,
@@ -1851,7 +1865,8 @@ static int add_default_attributes(void)
"Please print the result regularly, e.g. -I1000\n");
}
str[8] = stat_config.topdown_level + '0';
- if (metricgroup__parse_groups(evsel_list, str,
+ if (metricgroup__parse_groups(evsel_list,
+ pmu, str,
/*metric_no_group=*/false,
/*metric_no_merge=*/false,
/*metric_no_threshold=*/true,
@@ -1885,20 +1900,28 @@ static int add_default_attributes(void)
* Add TopdownL1 metrics if they exist. To minimize
* multiplexing, don't request threshold computation.
*/
- /*
- * TODO: TopdownL1 is disabled on hybrid CPUs to avoid a crashes
- * caused by exposing latent bugs. This is fixed properly in:
- * https://lore.kernel.org/lkml/bff481ba-e60a-763f-0aa0-3ee53302c480@linux.intel.com/
- */
- if (metricgroup__has_metric("TopdownL1") && !perf_pmu__has_hybrid() &&
- metricgroup__parse_groups(evsel_list, "TopdownL1",
- /*metric_no_group=*/false,
- /*metric_no_merge=*/false,
- /*metric_no_threshold=*/true,
- stat_config.user_requested_cpu_list,
- stat_config.system_wide,
- &stat_config.metric_events) < 0)
- return -1;
+ if (metricgroup__has_metric(pmu, "TopdownL1")) {
+ struct evlist *metric_evlist = evlist__new();
+ struct evsel *metric_evsel;
+
+ if (!metric_evlist)
+ return -1;
+
+ if (metricgroup__parse_groups(metric_evlist, pmu, "TopdownL1",
+ /*metric_no_group=*/false,
+ /*metric_no_merge=*/false,
+ /*metric_no_threshold=*/true,
+ stat_config.user_requested_cpu_list,
+ stat_config.system_wide,
+ &stat_config.metric_events) < 0)
+ return -1;
+
+ evlist__for_each_entry(metric_evlist, metric_evsel) {
+ metric_evsel->skippable = true;
+ }
+ evlist__splice_list_tail(evsel_list, &metric_evlist->core.entries);
+ evlist__delete(metric_evlist);
+ }
/* Platform specific attrs */
if (evlist__add_default_attrs(evsel_list, default_null_attrs) < 0)
@@ -2408,7 +2431,9 @@ int cmd_stat(int argc, const char **argv)
* knowing the target is system-wide.
*/
if (metrics) {
- metricgroup__parse_groups(evsel_list, metrics,
+ const char *pmu = parse_events_option_args.pmu_filter ?: "all";
+
+ metricgroup__parse_groups(evsel_list, pmu, metrics,
stat_config.metric_no_group,
stat_config.metric_no_merge,
stat_config.metric_no_threshold,