]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
perf: Skip and warn on unknown format 'configN' attrs
authorRob Herring <robh@kernel.org>
Tue, 4 Oct 2022 19:12:35 +0000 (14:12 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 30 Oct 2022 08:41:18 +0000 (09:41 +0100)
[ Upstream commit e552b7be12ed62357df84392efa525ecb01910fb ]

If the kernel exposes a new perf_event_attr field in a format attr, perf
will return an error stating the specified PMU can't be found. For
example, a format attr with 'config3:0-63' causes an error as config3 is
unknown to perf. This causes a compatibility issue between a newer
kernel with older perf tool.

Before this change with a kernel adding 'config3' I get:

  $ perf record -e arm_spe// -- true
  event syntax error: 'arm_spe//'
                       \___ Cannot find PMU `arm_spe'. Missing kernel support?
  Run 'perf list' for a list of valid events

   Usage: perf record [<options>] [<command>]
      or: perf record [<options>] -- <command> [<options>]

      -e, --event <event>   event selector. use 'perf list' to list
  available events

After this change, I get:

  $ perf record -e arm_spe// -- true
  WARNING: 'arm_spe_0' format 'inv_event_filter' requires 'perf_event_attr::config3' which is not supported by this version of perf!
  [ perf record: Woken up 2 times to write data ]
  [ perf record: Captured and wrote 0.091 MB perf.data ]

To support unknown configN formats, rework the YACC implementation to
pass any config[0-9]+ format to perf_pmu__new_format() to handle with a
warning.

Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Rob Herring <robh@kernel.org>
Tested-by: Leo Yan <leo.yan@linaro.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20220914-arm-perf-tool-spe1-2-v2-v4-1-83c098e6212e@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
tools/perf/util/parse-events.c
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/pmu.l
tools/perf/util/pmu.y

index 36969fc8f1fcd8ad0d55f122c9e57b5f42800008..c56a4d9c3be9420608deb7ab96fb82499a7524e1 100644 (file)
@@ -356,6 +356,9 @@ __add_event(struct list_head *list, int *idx,
        struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) :
                               cpu_list ? perf_cpu_map__new(cpu_list) : NULL;
 
+       if (pmu)
+               perf_pmu__warn_invalid_formats(pmu);
+
        if (pmu && attr->type == PERF_TYPE_RAW)
                perf_pmu__warn_invalid_config(pmu, attr->config, name);
 
index 349012f7defbff2725371764c8da273d1f506ba2..ac45da0302a73c42ce7e202bc6c03fb1946aa77c 100644 (file)
@@ -862,6 +862,23 @@ static struct perf_pmu *pmu_lookup(const char *name)
        return pmu;
 }
 
+void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu)
+{
+       struct perf_pmu_format *format;
+
+       /* fake pmu doesn't have format list */
+       if (pmu == &perf_pmu__fake)
+               return;
+
+       list_for_each_entry(format, &pmu->format, list)
+               if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) {
+                       pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'"
+                                  "which is not supported by this version of perf!\n",
+                                  pmu->name, format->name, format->value);
+                       return;
+               }
+}
+
 static struct perf_pmu *pmu_find(const char *name)
 {
        struct perf_pmu *pmu;
index d9aa8c958d2184cd038aba3ac12039dad9fcacc4..7d208b850769527723e760ff73ddf71a74fae7d1 100644 (file)
@@ -15,6 +15,7 @@ enum {
        PERF_PMU_FORMAT_VALUE_CONFIG,
        PERF_PMU_FORMAT_VALUE_CONFIG1,
        PERF_PMU_FORMAT_VALUE_CONFIG2,
+       PERF_PMU_FORMAT_VALUE_CONFIG_END,
 };
 
 #define PERF_PMU_FORMAT_BITS 64
@@ -122,5 +123,6 @@ int perf_pmu__caps_parse(struct perf_pmu *pmu);
 
 void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
                                   char *name);
+void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu);
 
 #endif /* __PMU_H */
index a15d9fbd7c0ed99512b0163ffe26bdb8eaf313bf..58b4926cfaca906dab6f6f85bd7f359c943f166d 100644 (file)
@@ -27,8 +27,6 @@ num_dec         [0-9]+
 
 {num_dec}      { return value(10); }
 config         { return PP_CONFIG; }
-config1                { return PP_CONFIG1; }
-config2                { return PP_CONFIG2; }
 -              { return '-'; }
 :              { return ':'; }
 ,              { return ','; }
index bfd7e8509869b64b53fbcbcddafe89a4a73b93b3..283efe059819d81ddb12c35c7147a20d8300ff0b 100644 (file)
@@ -20,7 +20,7 @@ do { \
 
 %}
 
-%token PP_CONFIG PP_CONFIG1 PP_CONFIG2
+%token PP_CONFIG
 %token PP_VALUE PP_ERROR
 %type <num> PP_VALUE
 %type <bits> bit_term
@@ -47,18 +47,11 @@ PP_CONFIG ':' bits
                                      $3));
 }
 |
-PP_CONFIG1 ':' bits
+PP_CONFIG PP_VALUE ':' bits
 {
        ABORT_ON(perf_pmu__new_format(format, name,
-                                     PERF_PMU_FORMAT_VALUE_CONFIG1,
-                                     $3));
-}
-|
-PP_CONFIG2 ':' bits
-{
-       ABORT_ON(perf_pmu__new_format(format, name,
-                                     PERF_PMU_FORMAT_VALUE_CONFIG2,
-                                     $3));
+                                     $2,
+                                     $4));
 }
 
 bits: