perf stat: Make cputype filter generic
authorIan Rogers <irogers@google.com>
Tue, 2 May 2023 22:38:37 +0000 (15:38 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 15 May 2023 12:12:14 +0000 (09:12 -0300)
Rather than limit the --cputype argument for "perf list" and "perf
stat" to hybrid PMUs of just cpu_atom and cpu_core, allow any PMU.

Note, that if cpu_atom isn't mounted but a filter of cpu_atom is
requested, then this will now fail. As such a filter would never
succeed, no events can come from that unmounted PMU, then this
behavior could never have been useful and failing is clearer.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Kan Liang <kan.liang@linux.intel.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ahmad Yasin <ahmad.yasin@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Caleb Biggers <caleb.biggers@intel.com>
Cc: Edward Baker <edward.baker@intel.com>
Cc: Florian Fischer <florian.fischer@muhq.space>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kang Minchul <tegongkang@gmail.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Perry Taylor <perry.taylor@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Samantha Alt <samantha.alt@intel.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Link: https://lore.kernel.org/r/20230502223851.2234828-31-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-list.c
tools/perf/builtin-stat.c
tools/perf/util/pmu-hybrid.c
tools/perf/util/pmu-hybrid.h
tools/perf/util/pmus.c
tools/perf/util/pmus.h

index 1f5dbd5..c6bd0aa 100644 (file)
@@ -11,8 +11,8 @@
 #include "builtin.h"
 
 #include "util/print-events.h"
+#include "util/pmus.h"
 #include "util/pmu.h"
-#include "util/pmu-hybrid.h"
 #include "util/debug.h"
 #include "util/metricgroup.h"
 #include "util/string2.h"
@@ -429,7 +429,7 @@ int cmd_list(int argc, const char **argv)
                .print_event = default_print_event,
                .print_metric = default_print_metric,
        };
-       const char *hybrid_name = NULL;
+       const char *cputype = NULL;
        const char *unit_name = NULL;
        bool json = false;
        struct option list_options[] = {
@@ -443,8 +443,8 @@ int cmd_list(int argc, const char **argv)
                            "Print information on the perf event names and expressions used internally by events."),
                OPT_BOOLEAN(0, "deprecated", &default_ps.deprecated,
                            "Print deprecated events."),
-               OPT_STRING(0, "cputype", &hybrid_name, "hybrid cpu type",
-                          "Limit PMU or metric printing to the given hybrid PMU (e.g. core or atom)."),
+               OPT_STRING(0, "cputype", &cputype, "cpu type",
+                          "Limit PMU or metric printing to the given PMU (e.g. cpu, core or atom)."),
                OPT_STRING(0, "unit", &unit_name, "PMU name",
                           "Limit PMU or metric printing to the specified PMU."),
                OPT_INCR(0, "debug", &verbose,
@@ -484,10 +484,15 @@ int cmd_list(int argc, const char **argv)
                assert(default_ps.visited_metrics);
                if (unit_name)
                        default_ps.pmu_glob = strdup(unit_name);
-               else if (hybrid_name) {
-                       default_ps.pmu_glob = perf_pmu__hybrid_type_to_pmu(hybrid_name);
-                       if (!default_ps.pmu_glob)
-                               pr_warning("WARNING: hybrid cputype is not supported!\n");
+               else if (cputype) {
+                       const struct perf_pmu *pmu = perf_pmus__pmu_for_pmu_filter(cputype);
+
+                       if (!pmu) {
+                               pr_err("ERROR: cputype is not supported!\n");
+                               ret = -1;
+                               goto out;
+                       }
+                       default_ps.pmu_glob = pmu->name;
                }
        }
        print_cb.print_start(ps);
index de2e915..fe9c6fa 100644 (file)
@@ -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"
 
@@ -1089,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)) {
@@ -1100,11 +1101,12 @@ static int parse_hybrid_type(const struct option *opt,
                return -1;
        }
 
-       parse_events_option_args.pmu_filter = perf_pmu__hybrid_type_to_pmu(str);
-       if (!parse_events_option_args.pmu_filter) {
+       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;
 }
@@ -1230,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",
index 3862880..bc4cb07 100644 (file)
@@ -50,23 +50,3 @@ bool perf_pmu__is_hybrid(const char *name)
 {
        return perf_pmu__find_hybrid_pmu(name) != NULL;
 }
-
-char *perf_pmu__hybrid_type_to_pmu(const char *type)
-{
-       char *pmu_name = NULL;
-
-       if (asprintf(&pmu_name, "cpu_%s", type) < 0)
-               return NULL;
-
-       if (perf_pmu__is_hybrid(pmu_name))
-               return pmu_name;
-
-       /*
-        * pmu may be not scanned, check the sysfs.
-        */
-       if (perf_pmu__hybrid_mounted(pmu_name))
-               return pmu_name;
-
-       free(pmu_name);
-       return NULL;
-}
index 2b186c2..206b949 100644 (file)
@@ -17,7 +17,6 @@ bool perf_pmu__hybrid_mounted(const char *name);
 
 struct perf_pmu *perf_pmu__find_hybrid_pmu(const char *name);
 bool perf_pmu__is_hybrid(const char *name);
-char *perf_pmu__hybrid_type_to_pmu(const char *type);
 
 static inline int perf_pmu__hybrid_pmu_num(void)
 {
index 7f3b93c..140e11f 100644 (file)
@@ -1,5 +1,28 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/list.h>
-#include <pmus.h>
+#include <string.h>
+#include "pmus.h"
+#include "pmu.h"
 
 LIST_HEAD(pmus);
+
+const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str)
+{
+       struct perf_pmu *pmu = NULL;
+
+       while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+               if (!strcmp(pmu->name, str))
+                       return pmu;
+               /* Ignore "uncore_" prefix. */
+               if (!strncmp(pmu->name, "uncore_", 7)) {
+                       if (!strcmp(pmu->name + 7, str))
+                               return pmu;
+               }
+               /* Ignore "cpu_" prefix on Intel hybrid PMUs. */
+               if (!strncmp(pmu->name, "cpu_", 4)) {
+                       if (!strcmp(pmu->name + 4, str))
+                               return pmu;
+               }
+       }
+       return NULL;
+}
index 5ec1200..d475e29 100644 (file)
@@ -3,7 +3,10 @@
 #define __PMUS_H
 
 extern struct list_head pmus;
+struct perf_pmu;
 
 #define perf_pmus__for_each_pmu(pmu) list_for_each_entry(pmu, &pmus, list)
 
+const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str);
+
 #endif /* __PMUS_H */