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 10/19] perf test attr: Accept either sample id bit perf asks for
Date: Tue, 13 Oct 2026 17:14:05 -0300 [thread overview]
Message-ID: <20261013201415.36428-11-acme@kernel.org> (raw)
In-Reply-To: <20261013201415.36428-1-acme@kernel.org>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
evlist__config() asks for a way to tell the samples apart,
PERF_SAMPLE_IDENTIFIER where available, PERF_SAMPLE_ID otherwise:
bool sample_id = opts->sample_id;
...
if (opts->full_auxtrace || opts->sample_identifier) {
...
use_sample_identifier = perf_can_sample_identifier();
sample_id = true;
} else if (evlist__nr_entries(evlist) > 1) {
...
use_sample_identifier = perf_can_sample_identifier();
sample_id = true;
}
so the id is asked for whenever the evlist has more than one event, and
also when asked to outright, with --sample-identifier or by an auxtrace
session, or by record__config() for a pipe run, through opts->sample_id,
none of which depends on the sample types: 'perf record
--sample-identifier -e cycles' and the arm SPE expectations in this very
directory ask for it with a single event.
Which one it asks for depends on the composition of the evlist: with
more than one core PMU a request for 'cycles' becomes one event per core
PMU, the extra dummy tracking events then make the sample types differ and
perf goes for IDENTIFIER, while the expectations were written on machines
with a single core PMU, where perf asks for ID:
expected sample_type=263, got 65799 # 263 | (1 << 16)
expected sample_type=343, got 65815 # (343 & ~(1 << 6)) | (1 << 16), group-sampling
Both bits mean the same thing here, how the samples get associated with the
event that produced them, so when the expectation asks for one of them, ask
for "an id of some sort" on both sides, and when the expectation doesn't
ask for any, take the bits out of what got recorded: whether they are there
and which one it is are consequences of what was asked for and of how the
request got expanded, none of that is what these expectations are about.
Since Test.compare() looks at both directions, expectations matching the
recorded events and recorded events matching the expectations, keep track
of which side is the one perf recorded to take the bits out of the right
side.
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/tests/shell/lib/attr.py | 81 ++++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 5 deletions(-)
diff --git a/tools/perf/tests/shell/lib/attr.py b/tools/perf/tests/shell/lib/attr.py
index 151b884670952e9f..e911684428b1b74b 100644
--- a/tools/perf/tests/shell/lib/attr.py
+++ b/tools/perf/tests/shell/lib/attr.py
@@ -59,6 +59,8 @@ def core_pmu_available():
PERF_TYPE_HARDWARE = 0
PERF_TYPE_HW_CACHE = 3
+PERF_SAMPLE_ID = 1 << 6
+PERF_SAMPLE_IDENTIFIER = 1 << 16
# The legacy event types, where perf may qualify 'config' with the core PMU
# type in its top 32 bits when there is more than one core PMU.
@@ -90,6 +92,49 @@ def hide_core_pmu_type(value):
"""
return mask_bits(value, 0xffffffff00000000)
+# The two sample id bits mean the same thing here: how the samples of the
+# events in the evlist get associated with the event that produced them.
+SAMPLE_ID_BITS = PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER
+
+# No real sample_type bit is this high, so it can stand for "either of the
+# sample id bits" when comparing the two sides.
+SAMPLE_ID_EITHER = 1 << 40
+
+def hide_sample_id(expected, recorded):
+ """
+ perf asks for a way to tell the samples apart, PERF_SAMPLE_IDENTIFIER where
+ available, PERF_SAMPLE_ID otherwise, see evlist__config(): whenever the
+ evlist has more than one event, and when asked to outright, with
+ --sample-identifier, by an auxtrace session, or by record__config() for a
+ pipe run, none of which depends on the sample types, as those only choose
+ between the two bits:
+ with more than one core PMU the dummy tracking events make the sample types
+ differ, so IDENTIFIER is asked for even for events whose expectations ask
+ for ID, written on a machine with a single core PMU.
+
+ So treat the two as the same thing: when the expectation asks for either
+ of them, ask for "an id of some sort" on both sides, and when the
+ expectation doesn't ask for any, take the bits out of what got recorded.
+ """
+ try:
+ asked = int(expected, 0) & SAMPLE_ID_BITS
+ except ValueError:
+ # The expectation is a wildcard or a set of alternatives.
+ return expected, recorded
+
+ try:
+ recorded_id_bits = int(recorded, 0) & SAMPLE_ID_BITS
+ except ValueError:
+ # The recorded side is a wildcard or a set of alternatives.
+ return expected, mask_bits(recorded, SAMPLE_ID_BITS)
+
+ if not asked:
+ return expected, mask_bits(recorded, SAMPLE_ID_BITS)
+
+ return (str(int(expected, 0) & ~SAMPLE_ID_BITS | SAMPLE_ID_EITHER),
+ str(int(recorded, 0) & ~SAMPLE_ID_BITS |
+ (SAMPLE_ID_EITHER if recorded_id_bits else 0)))
+
class Fail(Exception):
def __init__(self, test, msg):
self.msg = msg
@@ -182,13 +227,33 @@ class Event(dict):
return value
+ def hide_event_count_dependent_terms(self, term, expected, recorded):
+ if term == 'sample_type':
+ return hide_sample_id(expected, recorded)
+
+ return expected, recorded
+
+ def recorded_side(self, other):
+ """
+ Which one is what perf recorded? Both directions get compared, see
+ Test.compare(), so this can't be taken from the arguments' order.
+ """
+ if getattr(other, 'recorded', False):
+ return other
+
+ return self if getattr(self, 'recorded', False) else None
+
def equal(self, other):
for t in Event.terms:
log.debug(" [%s] %s %s", t, self[t], other[t])
if t not in self or t not in other:
return False
- exp = self.hide_core_pmu_type(t, self[t], other)
- got = self.hide_core_pmu_type(t, other[t], other)
+ recorded = self.recorded_side(other)
+ expected = other if recorded is self else self
+ exp = self.hide_core_pmu_type(t, expected[t], recorded or expected)
+ got = self.hide_core_pmu_type(t, (recorded or self)[t], expected)
+ if recorded is not None:
+ exp, got = self.hide_event_count_dependent_terms(t, exp, got)
if not data_equal(exp, got):
return False
return True
@@ -202,10 +267,14 @@ class Event(dict):
for t in Event.terms:
if t not in self or t not in other:
continue
- exp = self.hide_core_pmu_type(t, self[t], other)
- got = self.hide_core_pmu_type(t, other[t], other)
+ recorded = self.recorded_side(other)
+ expected = other if recorded is self else self
+ exp = self.hide_core_pmu_type(t, expected[t], recorded or expected)
+ got = self.hide_core_pmu_type(t, (recorded or self)[t], expected)
+ if recorded is not None:
+ exp, got = self.hide_event_count_dependent_terms(t, exp, got)
if not data_equal(exp, got):
- log.warning("expected %s=%s, got %s", t, self[t], other[t])
+ log.warning("expected %s=%s, got %s", t, exp, got)
def parse_version(version):
if not version:
@@ -487,6 +556,8 @@ class Test(object):
log.debug(" loading result events")
for f in glob.glob(tempdir + '/event*'):
self.load_events(f, self.result)
+ for event in self.result.values():
+ event.recorded = True
# resolve group_fd to event names
self.resolve_groups(self.expect)
--
2.55.0
next prev 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 ` [PATCH v2 02/19] perf test attr: Allow tests to require a core PMU Arnaldo Carvalho de Melo
2026-10-13 20:28 ` 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 ` Arnaldo Carvalho de Melo [this message]
2026-10-13 20:24 ` [PATCH v2 10/19] perf test attr: Accept either sample id bit perf asks for 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-11-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