Linux Perf Users
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Namhyung Kim <namhyung@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	James Clark <james.clark@linaro.org>,
	Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Clark Williams <williams@redhat.com>,
	linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH v2 02/19] perf test attr: Allow tests to require a core PMU
Date: Tue, 13 Oct 2026 17:13:57 -0300	[thread overview]
Message-ID: <20261013201415.36428-3-acme@kernel.org> (raw)
In-Reply-To: <20261013201415.36428-1-acme@kernel.org>

From: Arnaldo Carvalho de Melo <acme@redhat.com>

On machines without a usable core PMU, like an aarch64 box with no DT
node for the ARM PMU, the expectations that pin the legacy hardware
encoding can't be checked: without a core PMU at all 'cycles' doesn't
even resolve, and with one that can't be opened 'perf record' takes the
software fallback and records attributes they can never match:

  expected type=0, got 1
  expected config=0, got 1
  FAILED '.../attr/test-record-group-sampling1' - match failure

And since attr.py stops at the first failure, every expectation that
would come after that one ends up not being run at all.

Add a 'requires' limitation, modelled after the existing 'arch', 'auxv'
and 'kernel_since/until' ones, with 'core-pmu' as its first value, that
is checked by asking perf itself to open 'cycles' via its python
binding: a parse failure or an ENOENT means there is no PMU that can
count it, hence nothing to check and the test gets skipped, while any
other error means we can't tell, so the test keeps running as it does
today, where there is no binding to ask either.

An old distro python package may have a 'perf' module without
parse_events(), i.e. there is nothing to ask with, so that
AttributeError gets the same treatment as the ImportError: let the
expectations speak.

The expectations that have a strict 'type=0', plus the group tests,
where the fallback drops a member and leaves nothing to compare the
group leader attributes with, now state that they require a core PMU.
They are marked here, before the commit that has the group tests ask for
the legacy encodings, so the requisite comes with that dependency.

Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 .../shell/attr/test-record-group-sampling     |  1 +
 .../shell/attr/test-record-group-sampling1    |  1 +
 .../shell/attr/test-record-group-sampling2    |  1 +
 .../perf/tests/shell/attr/test-record-group1  |  1 +
 .../perf/tests/shell/attr/test-record-group2  |  1 +
 .../perf/tests/shell/attr/test-record-group3  |  1 +
 tools/perf/tests/shell/attr/test-stat-C0      |  1 +
 tools/perf/tests/shell/attr/test-stat-basic   |  1 +
 tools/perf/tests/shell/attr/test-stat-default |  1 +
 .../tests/shell/attr/test-stat-detailed-1     |  1 +
 .../tests/shell/attr/test-stat-detailed-2     |  1 +
 .../tests/shell/attr/test-stat-detailed-3     |  1 +
 tools/perf/tests/shell/attr/test-stat-group1  |  1 +
 .../tests/shell/attr/test-stat-no-inherit     |  1 +
 tools/perf/tests/shell/lib/attr.py            | 44 +++++++++++++++++++
 15 files changed, 58 insertions(+)

diff --git a/tools/perf/tests/shell/attr/test-record-group-sampling b/tools/perf/tests/shell/attr/test-record-group-sampling
index 86a940d7895d7404..b43d9fe3af75c096 100644
--- a/tools/perf/tests/shell/attr/test-record-group-sampling
+++ b/tools/perf/tests/shell/attr/test-record-group-sampling
@@ -3,6 +3,7 @@ command = record
 args    = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1
 ret     = 1
 kernel_until = 6.12
+requires = core-pmu
 
 [event-1:base-record]
 fd=1
diff --git a/tools/perf/tests/shell/attr/test-record-group-sampling1 b/tools/perf/tests/shell/attr/test-record-group-sampling1
index 4748ab7bf68437c7..3def72161820dca3 100644
--- a/tools/perf/tests/shell/attr/test-record-group-sampling1
+++ b/tools/perf/tests/shell/attr/test-record-group-sampling1
@@ -3,6 +3,7 @@ command = record
 args    = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1
 ret     = 1
 kernel_since = 6.12
+requires = core-pmu
 
 [event-1:base-record]
 fd=1
diff --git a/tools/perf/tests/shell/attr/test-record-group-sampling2 b/tools/perf/tests/shell/attr/test-record-group-sampling2
index e0432244a0eb7f6c..227c18bb221c4b2f 100644
--- a/tools/perf/tests/shell/attr/test-record-group-sampling2
+++ b/tools/perf/tests/shell/attr/test-record-group-sampling2
@@ -3,6 +3,7 @@ command = record
 args    = --no-bpf-event -c 10000 -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1
 ret     = 1
 kernel_since = 6.12
+requires = core-pmu
 
 [event-1:base-record]
 fd=1
diff --git a/tools/perf/tests/shell/attr/test-record-group1 b/tools/perf/tests/shell/attr/test-record-group1
index eeb1db392bc9ceac..a57c7ee8aaa4f9c9 100644
--- a/tools/perf/tests/shell/attr/test-record-group1
+++ b/tools/perf/tests/shell/attr/test-record-group1
@@ -2,6 +2,7 @@
 command = record
 args    = --no-bpf-event -e '{cycles,instructions}' kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 [event-1:base-record]
 fd=1
diff --git a/tools/perf/tests/shell/attr/test-record-group2 b/tools/perf/tests/shell/attr/test-record-group2
index 891d41a7bddf785a..fb6e664eeacc10ef 100644
--- a/tools/perf/tests/shell/attr/test-record-group2
+++ b/tools/perf/tests/shell/attr/test-record-group2
@@ -3,6 +3,7 @@ command = record
 args    = --no-bpf-event -e '{cycles/period=1234000/,instructions/period=6789000/}:S' kill >/dev/null 2>&1
 ret     = 1
 kernel_until = 6.12
+requires = core-pmu
 
 [event-1:base-record]
 fd=1
diff --git a/tools/perf/tests/shell/attr/test-record-group3 b/tools/perf/tests/shell/attr/test-record-group3
index 249be884959eaaba..7b90b4411d8f4b90 100644
--- a/tools/perf/tests/shell/attr/test-record-group3
+++ b/tools/perf/tests/shell/attr/test-record-group3
@@ -3,6 +3,7 @@ command = record
 args    = --no-bpf-event -e '{cycles/period=1234000/,instructions/period=6789000/}:S' kill >/dev/null 2>&1
 ret     = 1
 kernel_since = 6.12
+requires = core-pmu
 
 [event-1:base-record]
 fd=1
diff --git a/tools/perf/tests/shell/attr/test-stat-C0 b/tools/perf/tests/shell/attr/test-stat-C0
index a2c76d10b2bb2a15..9d242e93e3a92009 100644
--- a/tools/perf/tests/shell/attr/test-stat-C0
+++ b/tools/perf/tests/shell/attr/test-stat-C0
@@ -2,6 +2,7 @@
 command = stat
 args    = -e cycles -C 0 kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 [event:base-stat]
 # events are disabled by default when attached to cpu
diff --git a/tools/perf/tests/shell/attr/test-stat-basic b/tools/perf/tests/shell/attr/test-stat-basic
index 69867d049fda926f..277897bd2626a41f 100644
--- a/tools/perf/tests/shell/attr/test-stat-basic
+++ b/tools/perf/tests/shell/attr/test-stat-basic
@@ -2,6 +2,7 @@
 command = stat
 args    = -e cycles kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 [event:base-stat]
 optional=1
diff --git a/tools/perf/tests/shell/attr/test-stat-default b/tools/perf/tests/shell/attr/test-stat-default
index 8dd27c1fb661fb77..74691188e859a169 100644
--- a/tools/perf/tests/shell/attr/test-stat-default
+++ b/tools/perf/tests/shell/attr/test-stat-default
@@ -2,6 +2,7 @@
 command = stat
 args    = kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
 [event1:base-stat]
diff --git a/tools/perf/tests/shell/attr/test-stat-detailed-1 b/tools/perf/tests/shell/attr/test-stat-detailed-1
index 12a2ebf4e64a0077..d9a6236054f2dfb1 100644
--- a/tools/perf/tests/shell/attr/test-stat-detailed-1
+++ b/tools/perf/tests/shell/attr/test-stat-detailed-1
@@ -2,6 +2,7 @@
 command = stat
 args    = -d kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 
 # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
diff --git a/tools/perf/tests/shell/attr/test-stat-detailed-2 b/tools/perf/tests/shell/attr/test-stat-detailed-2
index 66ea25b7d38f8d59..582a30289ccfa6df 100644
--- a/tools/perf/tests/shell/attr/test-stat-detailed-2
+++ b/tools/perf/tests/shell/attr/test-stat-detailed-2
@@ -2,6 +2,7 @@
 command = stat
 args    = -dd kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 
 # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
diff --git a/tools/perf/tests/shell/attr/test-stat-detailed-3 b/tools/perf/tests/shell/attr/test-stat-detailed-3
index 4a27bbfb9f87a538..2d0fca8b5020f504 100644
--- a/tools/perf/tests/shell/attr/test-stat-detailed-3
+++ b/tools/perf/tests/shell/attr/test-stat-detailed-3
@@ -2,6 +2,7 @@
 command = stat
 args    = -ddd kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 
 # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
diff --git a/tools/perf/tests/shell/attr/test-stat-group1 b/tools/perf/tests/shell/attr/test-stat-group1
index 1746751123dcb2c4..3d8b44ba42d6ae19 100644
--- a/tools/perf/tests/shell/attr/test-stat-group1
+++ b/tools/perf/tests/shell/attr/test-stat-group1
@@ -2,6 +2,7 @@
 command = stat
 args    = -e '{cycles,instructions}' kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 [event-1:base-stat]
 fd=1
diff --git a/tools/perf/tests/shell/attr/test-stat-no-inherit b/tools/perf/tests/shell/attr/test-stat-no-inherit
index 924fbb9300d16259..38f746855b1b3e11 100644
--- a/tools/perf/tests/shell/attr/test-stat-no-inherit
+++ b/tools/perf/tests/shell/attr/test-stat-no-inherit
@@ -2,6 +2,7 @@
 command = stat
 args    = -i -e cycles kill >/dev/null 2>&1
 ret     = 1
+requires = core-pmu
 
 [event:base-stat]
 inherit=0
diff --git a/tools/perf/tests/shell/lib/attr.py b/tools/perf/tests/shell/lib/attr.py
index 68f06df9565a0811..b55c9b881e59852f 100644
--- a/tools/perf/tests/shell/lib/attr.py
+++ b/tools/perf/tests/shell/lib/attr.py
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 import configparser
+import errno
 import os
 import sys
 import glob
@@ -28,6 +29,34 @@ def data_equal(a, b):
 
     return False
 
+def core_pmu_available():
+    """
+    Is there a core PMU on this machine? Without one hardware events aren't
+    supported and get replaced by the software fallback, so there's no way to
+    check the expectations that pin their legacy encodings.
+    """
+    try:
+        import perf
+        parse_events = perf.parse_events
+    except (ImportError, AttributeError):
+        # Nothing to ask about it, let the expectations speak.
+        return True
+
+    try:
+        evlist = parse_events('cycles')
+    except OSError:
+        # No PMU that can count it, the same as the ENOENT below.
+        return False
+
+    try:
+        evlist.open()
+    except OSError as err:
+        # Anything else is a permission problem or alike, not our business here.
+        return err.errno != errno.ENOENT
+    evlist.close()
+
+    return True
+
 class Fail(Exception):
     def __init__(self, test, msg):
         self.msg = msg
@@ -138,6 +167,9 @@ def parse_version(version):
 #     'arch'    - architecture specific test (optional)
 #                 comma separated list, ! at the beginning
 #                 negates it.
+#     'requires' - Comma separated list of things the test needs, it is
+#                 skipped when any of them isn't there, currently:
+#                   core-pmu - the machine can count hardware events.
 #     'auxv'    - Truthy statement that is evaled in the scope of the auxv map. When false,
 #                 the test is skipped. For example 'auxv["AT_HWCAP"] == 10'. (optional)
 #     'kernel_since' - Inclusive kernel version from which the test will start running. Only the
@@ -173,6 +205,7 @@ class Test(object):
             self.arch  = ''
 
         self.auxv = parser.get('config', 'auxv', fallback=None)
+        self.requires = parser.get('config', 'requires', fallback='')
         self.kernel_since = parse_version(parser.get('config', 'kernel_since', fallback=None))
         self.kernel_until = parse_version(parser.get('config', 'kernel_until', fallback=None))
         self.expect   = {}
@@ -242,6 +275,14 @@ class Test(object):
                 return False
         return True
 
+    def skip_test_requires(self):
+        for requirement in filter(None, map(str.strip, self.requires.split(','))):
+            if requirement == 'core-pmu' and not core_pmu_available():
+                log.warning("test limitation 'requires %s'", requirement)
+                return True
+
+        return False
+
     def restore_sample_rate(self, value=10000):
         try:
             # Check value of sample_rate
@@ -296,6 +337,9 @@ class Test(object):
         if self.skip_test_kernel_until():
             raise Notest(self, "new kernel skip")
 
+        if self.skip_test_requires():
+            raise Notest(self, "requirements skip")
+
         self.restore_sample_rate()
         cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir,
               self.perf, self.command, tempdir, self.args)
-- 
2.55.0


  parent reply	other threads:[~2026-10-13 20:14 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 20:13 [PATCH v2 0/19] perf test attr: Report the failures again and cope with more than one core PMU Arnaldo Carvalho de Melo
2026-10-13 20:13 ` [PATCH v2 01/19] perf test attr: Fix record dwarf sample_type expectation Arnaldo Carvalho de Melo
2026-10-13 20:21   ` sashiko-bot
2026-10-13 20:13 ` Arnaldo Carvalho de Melo [this message]
2026-10-13 20:28   ` [PATCH v2 02/19] perf test attr: Allow tests to require a core PMU sashiko-bot
2026-10-13 20:13 ` [PATCH v2 03/19] perf test attr: Fix legacy event encodings in group tests Arnaldo Carvalho de Melo
2026-10-13 20:22   ` sashiko-bot
2026-10-13 20:13 ` [PATCH v2 04/19] perf test attr: Fix default stat metrics expectations Arnaldo Carvalho de Melo
2026-10-13 20:37   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 05/19] perf test attr: Relax group checking for ungrouped expectations Arnaldo Carvalho de Melo
2026-10-13 20:18   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 06/19] perf evsel: Mark the event as supported when retrying an open Arnaldo Carvalho de Melo
2026-10-13 20:23   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 07/19] perf test attr: Ignore the core PMU type perf puts in 'config' Arnaldo Carvalho de Melo
2026-10-13 20:25   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 08/19] perf evsel: Don't dump probe events to PERF_TEST_ATTR Arnaldo Carvalho de Melo
2026-10-13 20:26   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 09/19] perf test attr: Introduce mask_bits(), generalizing hide_core_pmu_type() Arnaldo Carvalho de Melo
2026-10-13 20:19   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 10/19] perf test attr: Accept either sample id bit perf asks for Arnaldo Carvalho de Melo
2026-10-13 20:24   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 11/19] perf test attr: Ignore the dummy tracking event and the terms it carries Arnaldo Carvalho de Melo
2026-10-13 20:21   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 12/19] perf test attr: Leave out the events of the other core PMUs Arnaldo Carvalho de Melo
2026-10-13 20:21   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 13/19] perf test attr: Ignore the group read_format bit the PMU count can remove Arnaldo Carvalho de Melo
2026-10-13 20:20   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 14/19] perf test attr: State, spelled out in a line, why a test is skipped Arnaldo Carvalho de Melo
2026-10-13 20:22   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 15/19] perf tests: Introduce a 'needs_mlock' suite flag Arnaldo Carvalho de Melo
2026-10-13 20:23   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 16/19] perf mutex: Add a robust, process-shared mutex initializer Arnaldo Carvalho de Melo
2026-10-13 20:27   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 17/19] perf test: Take turns using the perf mlock budget in the mmaping tests Arnaldo Carvalho de Melo
2026-10-13 20:26   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 18/19] perf tests: Mark the C tests mapping perf ring buffers Arnaldo Carvalho de Melo
2026-10-13 20:25   ` sashiko-bot
2026-10-13 20:14 ` [PATCH v2 19/19] perf tests: Mark the shell tests not " Arnaldo Carvalho de Melo
2026-10-13 20:27   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261013201415.36428-3-acme@kernel.org \
    --to=acme@kernel.org \
    --cc=acme@redhat.com \
    --cc=adrian.hunter@intel.com \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=williams@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox