From nobody Mon May 25 05:54:09 2026 Received: from mail-dl1-f73.google.com (mail-dl1-f73.google.com [74.125.82.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0733381AFF for ; Mon, 18 May 2026 04:31:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779078715; cv=none; b=YFyCX3ktYozJRyy9qh4wprZkVcK+/l9bv3zhyZLky73hPiOqn6st/IzE3oAlok2AhGdSjzfBuIA8eGYsFV7GIsepiLk3vZ3x+HGvjmbAj9q2aGEvlbxcllVgc7ahbZgNqjKSOVQjKvjZiCWWj0lFzkrKdLBGAeQ08v0XMa6Ghl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779078715; c=relaxed/simple; bh=MC0apQYF85j3TEweHcfBKqRQbO2appaCBP/O5NDlFo0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=hRiHraNvhPMZ/fRl8pyh0jXoZzhFm0zB3BzfHtpYY8SbRvGCFUrAsMqrv31bpt5nm/wY6tmxEWXa9XrPOQC191hP2PXtXtVWb7o79/HqH714MywP7E63+4N3J9hhEfCQjIRYpdOVtaNPfL58STk8XmX2yToHj1DVl556vWE0Z7A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=bpqCy7lN; arc=none smtp.client-ip=74.125.82.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bpqCy7lN" Received: by mail-dl1-f73.google.com with SMTP id a92af1059eb24-13312be8a31so2333072c88.1 for ; Sun, 17 May 2026 21:31:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1779078709; x=1779683509; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=5aCwUis7hcNvoBcusHclileUNp7B3j+0iZpWDTdHqro=; b=bpqCy7lNIqzRhbOw/XffD5ulmijjQoCy8SGlg04tsKOTNb34TPXdCSI0BN5Ozzn9qr tas77AMhUyidyP6Te+bT8FTWPpzUrEK0WLB+lcQonc3fOwQNexEW2sK0gP/BL0N0PL8B mX7bpNnj7iYuiQkedCtNOlH1czTZRS30lfglX3fBlwT/CINDs8IyzS9KTutqiUQxxDNQ CyD9D5M+v3+eacMAQEiax7CyeLyzlxXVEflT7oxPL3XCFxHxzCPLJSgnBKX+Q1VOFT+n 9uYMXiCf2xYv+f9ZXEzoJDNYLmO+Iy9Te+KYc4QqvQw2SezagJq781cgLkmd6BAEqSb8 SbnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779078709; x=1779683509; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5aCwUis7hcNvoBcusHclileUNp7B3j+0iZpWDTdHqro=; b=ghAPMXoPcBnacbwupTGL6Db9H2YsP2f/DAc8IfJ2G9p72b2Gl86qRy4HltnVMBF8i6 xBy8W8WH3ymL2ZlDKMBpri5cRfvLM4M5RNkKS6H8WCWaVd37egChwoEaKYcZYr3+uNEG j+84Eag9HZAbh19Eeqadje4gBkUDlB1Rh63p/5ACAFB/J9Mh9RbM2iVHU9vIdFEzwC9T 2sF9A48FmAkiC3qjv+H1OXwDDt4ebYKSkEiqs0+2dQ901NULlqtqwn5h1CDOg4bryu/2 uK+wTnIqv4SWh5eukcmpHF/k+IiTY0a5nG2syk8BrVsQ+mlol9p9kkaMR59M5/YEotGT RzLw== X-Forwarded-Encrypted: i=1; AFNElJ/GQqO0DT5ESqK1lRTT4NaXbxh8eI/2v0LzjgaaJayiA2RMl3Zs9s+wM4hY7lmqICLa9DXIvkrb7vs3MC4=@vger.kernel.org X-Gm-Message-State: AOJu0YweeePWDQbuUFnY4FR7Rnh/FiTza9+86sGqNGZVWNmtgeWwqYmQ RSy2auzGnkDqT5y41LM//QigWv8R/g9NhWft4Faq/2RXMepqJChy1nc1SSKzAEfQkqN4SpoIk/J v8CkrXqfCGg== X-Received: from dybut1.prod.google.com ([2002:a05:7301:e0c1:b0:2f1:5dbf:fd4e]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:693c:3009:b0:2ea:b7a9:580d with SMTP id 5a478bee46e88-3039816dab4mr5748603eec.9.1779078709162; Sun, 17 May 2026 21:31:49 -0700 (PDT) Date: Sun, 17 May 2026 21:31:39 -0700 In-Reply-To: <20260518043140.2522141-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260518023225.2472122-1-irogers@google.com> <20260518043140.2522141-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.563.g4f69b47b94-goog Message-ID: <20260518043140.2522141-2-irogers@google.com> Subject: [PATCH v7 1/2] perf tests: Add test for uncore event sorting From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org Cc: 9erthalion6@gmail.com, adrian.hunter@intel.com, alexander.shishkin@linux.intel.com, collin.funk1@gmail.com, german.gomez@arm.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, peterz@infradead.org, zide.chen@intel.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a test for uncore event sorting matching multiple PMUs. Uncore PMUs may have a common prefix, like the PMUs uncore_imc_free_running_0 and uncore_imc_free_running_1 have a prefix of uncore_imc_free_running. Parsing an event group like "{data_read,data_write}" for those PMUs should result with two groups "{uncore_imc_free_running_0/data_read/,uncore_imc_free_running_0/data_write= /}, {uncore_imc_free_running_1/data_read/,uncore_imc_free_running_1/data_write/= }" which means the evsels need resorting as when initially parsed the evsels are ordered with mixed PMUs: "{uncore_imc_free_running_0/data_read/,uncore_imc_free_running_1/data_read/, uncore_imc_free_running_0/data_write/,uncore_imc_free_running_1/data_write/= }". Signed-off-by: Ian Rogers Tested-by: Zide Chen --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 1 + tools/perf/tests/tests.h | 1 + tools/perf/tests/uncore-event-sorting.c | 178 ++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 tools/perf/tests/uncore-event-sorting.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index c2a67ce45941..66944a4f4968 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -3,6 +3,7 @@ perf-test-y +=3D builtin-test.o perf-test-y +=3D tests-scripts.o perf-test-y +=3D parse-events.o +perf-test-y +=3D uncore-event-sorting.o perf-test-y +=3D dso-data.o perf-test-y +=3D vmlinux-kallsyms.o perf-test-y +=3D openat-syscall.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-tes= t.c index 06507066213b..f2c135891477 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -71,6 +71,7 @@ static struct test_suite *generic_tests[] =3D { &suite__basic_mmap, &suite__mem, &suite__parse_events, + &suite__uncore_event_sorting, &suite__expr, &suite__PERF_RECORD, &suite__pmu, diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index f5f1238d1f7f..ee00518bf36f 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -177,6 +177,7 @@ DECLARE_SUITE(sigtrap); DECLARE_SUITE(event_groups); DECLARE_SUITE(symbols); DECLARE_SUITE(util); +DECLARE_SUITE(uncore_event_sorting); DECLARE_SUITE(subcmd_help); DECLARE_SUITE(kallsyms_split); =20 diff --git a/tools/perf/tests/uncore-event-sorting.c b/tools/perf/tests/unc= ore-event-sorting.c new file mode 100644 index 000000000000..594fe7ff7bf6 --- /dev/null +++ b/tools/perf/tests/uncore-event-sorting.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +#include + +#include "debug.h" +#include "evlist.h" +#include "parse-events.h" +#include "pmu.h" +#include "pmus.h" +#include "tests.h" + +struct match_state { + char *event1; + char *event2; +}; + +static char *clean_event_name(struct pmu_event_info *info) +{ + const char *name =3D info->name; + const char *pmu_name =3D info->pmu->name; + size_t pmu_len =3D strlen(pmu_name); + char *res; + size_t len; + + if (!strncmp(name, pmu_name, pmu_len) && name[pmu_len] =3D=3D '/') + name +=3D pmu_len + 1; + + res =3D strdup(name); + if (!res) + return NULL; + + len =3D strlen(res); + if (len > 0 && res[len - 1] =3D=3D '/') + res[len - 1] =3D '\0'; + + return res; +} + +static int event_cb(void *state, struct pmu_event_info *info) +{ + struct match_state *m =3D state; + char *clean_name; + + if (m->event1 && m->event2) + return 1; + + clean_name =3D clean_event_name(info); + if (!clean_name) + return 0; + + if (!m->event1) { + m->event1 =3D clean_name; + } else if (!m->event2) { + if (strcmp(m->event1, clean_name)) { + m->event2 =3D clean_name; + return 1; + } + free(clean_name); + } else { + free(clean_name); + } + return 0; +} + +#define CHECK_COND(cond, text) \ +do { \ + if (!(cond)) { \ + pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + ret =3D TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +#define CHECK_EQUAL(val, expected, text) \ +do { \ + if ((val) !=3D (expected)) { \ + pr_debug("FAILED %s:%d %s (%d !=3D %d)\n", \ + __FILE__, __LINE__, text, (val), (expected)); \ + ret =3D TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +static int test__uncore_event_sorting(struct test_suite *test __maybe_unus= ed, + int subtest __maybe_unused) +{ + struct evlist *evlist =3D NULL; + struct parse_events_error err; + struct evsel *evsel; + struct perf_pmu *pmu =3D NULL; + char *pmu_prefix =3D NULL; + struct match_state m =3D { NULL, NULL }; + char buf[1024]; + int ret; + + parse_events_error__init(&err); + + while ((pmu =3D perf_pmus__scan(pmu)) !=3D NULL) { + size_t len; + struct perf_pmu *sibling; + + if (pmu->is_core) + continue; + + len =3D pmu_name_len_no_suffix(pmu->name); + if (len =3D=3D strlen(pmu->name)) + continue; + + sibling =3D pmu; + while ((sibling =3D perf_pmus__scan(sibling)) !=3D NULL) { + if (sibling->is_core) + continue; + if (pmu_name_len_no_suffix(sibling->name) =3D=3D len && + !strncmp(pmu->name, sibling->name, len)) + break; + } + + if (!sibling) + continue; + + m.event1 =3D m.event2 =3D NULL; + perf_pmu__for_each_event(pmu, false, &m, event_cb); + + if (m.event1 && m.event2) { + pmu_prefix =3D strndup(pmu->name, len); + break; + } + zfree(&m.event1); + } + + if (!pmu_prefix) { + pr_debug("No suitable uncore PMU found\n"); + ret =3D TEST_SKIP; + goto out_err; + } + + evlist =3D evlist__new(); + if (!evlist) { + ret =3D TEST_FAIL; + goto out_err; + } + + snprintf(buf, sizeof(buf), "{%s/%s/,%s/%s/}", pmu_prefix, m.event1, pmu_p= refix, m.event2); + pr_debug("Parsing: %s\n", buf); + + ret =3D parse_events(evlist, buf, &err); + if (ret) { + pr_debug("parse_events failed\n"); + ret =3D TEST_FAIL; + goto out_err; + } + + CHECK_COND(evlist->core.nr_entries >=3D 4, "Number of events is >=3D 4"); + CHECK_EQUAL(evlist->core.nr_entries % 2, 0, "Number of events is a multip= le of 2"); + + evlist__for_each_entry(evlist, evsel) { + struct evsel *next; + + if (!evsel__is_group_leader(evsel)) + continue; + + next =3D evsel__next(evsel); + CHECK_EQUAL(evsel->core.nr_members, 2, "Group size is 2"); + CHECK_COND(evsel->pmu =3D=3D next->pmu, "PMU match"); + CHECK_COND(strstr(evsel__name(evsel), m.event1) !=3D NULL, "First event = name"); + CHECK_COND(strstr(evsel__name(next), m.event2) !=3D NULL, "Second event = name"); + } + ret =3D TEST_OK; + +out_err: + evlist__delete(evlist); + parse_events_error__exit(&err); + zfree(&pmu_prefix); + zfree(&m.event1); + zfree(&m.event2); + return ret; +} + +DEFINE_SUITE("Uncore event sorting", uncore_event_sorting); --=20 2.54.0.563.g4f69b47b94-goog From nobody Mon May 25 05:54:09 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A061381AEC for ; Mon, 18 May 2026 04:31:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779078715; cv=none; b=umXn6gMt3O0yT8/+hBCtBtLxHFconHciuf6Gxi7dM0x9CKUAR/TB32AjLXbAvKn/+SNEHI8hn30IWTw1qaWmgPC8zkKyXhl1AvbBHAVEdnEGNRJa6xNOwhvKYETpDI9uGtkNqpYlcvLSs0D6B5HOxC4oa/e3YDz09hCOPiCAw8M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779078715; c=relaxed/simple; bh=3g9O2Yw3w3xaXapO32wDQKH9lNWe5WACrGuWp7AIlYk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dSroM/YKV6EPULqzHg3y69yzJt0FN0UWznRyHkBD7ckTGN0Ybxthbg60TjuYCq5QcaeSw3dP1ZgsitG8riWFDKYsfN9w9ChjT2yvxNJoVmiypB1SJUz5u6WYffOAeMmxPpL81rsLAjsfi7lQagXzefQXIVoUH3vcZrMxL8h+yAk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=sOcWUnnn; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sOcWUnnn" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2bda35eab74so1476987eec.0 for ; Sun, 17 May 2026 21:31:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1779078711; x=1779683511; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=I5egDoittCoF2sloPTEbRjge2u/Al3G2t4aOQQynxZU=; b=sOcWUnnnGzceOZpL13M278bU9F+XNGXIe0j/fi7L42zZE04rTupjt6jFjGNz3tBPGH dZmKIE7ZUdulii1OdMv7z4PdaGQoxHfiHF1xSyGtnd5eEMf2P+EROy8yW3qRkiFx/LMz uN5iAh/DMGa89BTCORE04mhTAheKKB30U1l+xDdw9EHJMAEwVOeJsfvyulXdk+z6Xetc YjrZOHYujKkrP4iB75UiBb0FCX7BP75U8CN9X/1tee8vQoxk0IR8XU8B2LxSlBmDjsED I3KY0kGu8x6qEWyx/CMfgKPp/1UfPmXCyxFxChzK0Ye5CR3A7/YWO4PYl8u4Urpg8XUf u22g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779078711; x=1779683511; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=I5egDoittCoF2sloPTEbRjge2u/Al3G2t4aOQQynxZU=; b=DHcl8e/ceLDSgknWjNN3xTi6QyB6G802yx2t/zKnOq9yqKRFu7XKgeour9HPhJ6oY7 66YeGrUBMA6CS0ZiC8Tr1rVqUsD6zJ9UWEh0SjLF8rY9NekuslP1BLxaUcirmARVhyFm p5conL3wS55lNIg5KRFExQYGx1Am77ByUuFGnWdac15oktJLLn2Xy2VLrLy1aFZdBkqB 5tZS2Be9vgArjC4DzPp8XhnPPswOgUpjKDwzdIScGTqw/csrmo+ne/d1s1UfOK+tNEQS boYxGwdMQZLL+Mn0uwl/kWYYBnQIAAsvfLtk1CeBjh40s+wR2kc4PO+Vd6SPgyn0uJKp +HzQ== X-Forwarded-Encrypted: i=1; AFNElJ+Gh6+xy6pvSc1n9nOhWq2ZFVZ0ctNSydzM9JC7YcFMVqryr8f7WGcKilnMRXO/pN1KC6x1NBpmSMMqY8Y=@vger.kernel.org X-Gm-Message-State: AOJu0YwzO+J9jE49oWnrW6Puq1iNUZrLrnNF8jsS8Z6olEabj8qZTVs5 WFmyOD8EcoJhRrfGmetV5tmo8Sje+y1nza7yAWJSYJUu5bHz8ckrJCrebY8oL+9QqAsxOyLa+47 xeIIw5YsZXw== X-Received: from dycnr6-n1.prod.google.com ([2002:a05:7300:e9c6:10b0:2da:2af9:bfe2]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:7885:b0:2c1:82c2:bc31 with SMTP id 5a478bee46e88-3026197f5b2mr7305963eec.10.1779078710839; Sun, 17 May 2026 21:31:50 -0700 (PDT) Date: Sun, 17 May 2026 21:31:40 -0700 In-Reply-To: <20260518043140.2522141-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260518023225.2472122-1-irogers@google.com> <20260518043140.2522141-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.563.g4f69b47b94-goog Message-ID: <20260518043140.2522141-3-irogers@google.com> Subject: [PATCH v7 2/2] perf arch x86 tests: Add test for topdown event sorting From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org Cc: 9erthalion6@gmail.com, adrian.hunter@intel.com, alexander.shishkin@linux.intel.com, collin.funk1@gmail.com, german.gomez@arm.com, james.clark@linaro.org, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, peterz@infradead.org, zide.chen@intel.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a test to capture the comment in tools/perf/arch/x86/util/evlist.c. Test that slots and topdown-retiring get appropriately sorted with respect to instructions when they're all specified together. When the PMU requires topdown event grouping (indicated by the pressence of the slots event) metric events should be after slots, which should be the group leader. Add a related test that when the slots event isn't given it is injected into the appropriate group. Signed-off-by: Ian Rogers Tested-by: Zide Chen --- tools/perf/arch/x86/tests/topdown.c | 166 +++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/tools/perf/arch/x86/tests/topdown.c b/tools/perf/arch/x86/test= s/topdown.c index 3ee4e5e71be3..221f2c4bbb61 100644 --- a/tools/perf/arch/x86/tests/topdown.c +++ b/tools/perf/arch/x86/tests/topdown.c @@ -75,4 +75,168 @@ static int test__x86_topdown(struct test_suite *test __= maybe_unused, int subtest return ret; } =20 -DEFINE_SUITE("x86 topdown", x86_topdown); +#define CHECK_COND(cond, text) \ +do { \ + if (!(cond)) { \ + pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + ret =3D TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +#define CHECK_EQUAL(val, expected, text) \ +do { \ + if ((val) !=3D (expected)) { \ + pr_debug("FAILED %s:%d %s (%d !=3D %d)\n", \ + __FILE__, __LINE__, text, (val), (expected)); \ + ret =3D TEST_FAIL; \ + goto out_err; \ + } \ +} while (0) + +static int test_sort(const char *str, int expected_slots_group_size, + int expected_instructions_group_size) +{ + struct evlist *evlist =3D NULL; + struct parse_events_error err; + struct evsel *evsel; + int ret =3D TEST_FAIL; + bool slots_seen =3D false; + + parse_events_error__init(&err); + + evlist =3D evlist__new(); + if (!evlist) + goto out_err; + + if (parse_events(evlist, str, &err)) { + pr_debug("parse_events failed for %s\n", str); + goto out_err; + } + + evlist__for_each_entry(evlist, evsel) { + if (!evsel__is_group_leader(evsel)) + continue; + + if (strstr(evsel__name(evsel), "slots")) { + /* + * Slots as a leader means the PMU is for a perf metric + * group as the slots event isn't present when not. + */ + slots_seen =3D true; + CHECK_EQUAL(evsel->core.nr_members, expected_slots_group_size, + "slots group size"); + if (expected_slots_group_size =3D=3D 3) { + struct evsel *next =3D evsel__next(evsel); + struct evsel *next2 =3D evsel__next(next); + + CHECK_COND(strstr(evsel__name(next), "instructions") !=3D NULL, + "slots second event is instructions"); + CHECK_COND(strstr(evsel__name(next2), "topdown-retiring") !=3D NULL, + "slots third event is topdown-retiring"); + } else if (expected_slots_group_size =3D=3D 2) { + struct evsel *next =3D evsel__next(evsel); + + CHECK_COND(strstr(evsel__name(next), "topdown-retiring") !=3D NULL, + "slots second event is topdown-retiring"); + } + } else if (strstr(evsel__name(evsel), "instructions")) { + CHECK_EQUAL(evsel->core.nr_members, expected_instructions_group_size, + "instructions group size"); + if (expected_instructions_group_size =3D=3D 2) { + /* + * On Intel hybrid CPUs (e.g., Alder Lake/ + * Raptor Lake), E-cores (cpu_atom) do not + * support/enforce the slots event. When + * parsing event groups containing slots + * across all PMUs, slots is automatically + * filtered out from cpu_atom, leaving + * {cpu_atom/instructions/, + * cpu_atom/topdown-retiring/}. On cpu_atom, + * instructions correctly leads this group of + * 2 without slots reordering. + */ + struct evsel *next =3D evsel__next(evsel); + + CHECK_COND(strstr(evsel__name(next), "topdown-retiring") !=3D NULL, + "instructions second event is topdown-retiring"); + } + } else if (strstr(evsel__name(evsel), "topdown-retiring")) { + /* + * A perf metric event where the PMU doesn't require + * slots as a leader. + */ + CHECK_EQUAL(evsel->core.nr_members, 1, "topdown-retiring group size"); + } else if (strstr(evsel__name(evsel), "cycles")) { + CHECK_EQUAL(evsel->core.nr_members, 1, "cycles group size"); + } + } + CHECK_COND(slots_seen, "slots seen"); + ret =3D TEST_OK; +out_err: + evlist__delete(evlist); + parse_events_error__exit(&err); + return ret; +} + +static int test__x86_topdown_sorting(struct test_suite *test __maybe_unuse= d, + int subtest __maybe_unused) +{ + int ret; + + if (!topdown_sys_has_perf_metrics()) + return TEST_OK; + + ret =3D test_sort("{instructions,topdown-retiring,slots}", 3, 2); + TEST_ASSERT_EQUAL("all events in a group", ret, TEST_OK); + ret =3D test_sort("instructions,topdown-retiring,slots", 2, 1); + TEST_ASSERT_EQUAL("all events not in a group", ret, TEST_OK); + ret =3D test_sort("{instructions,slots},topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("slots event in a group but topdown metrics events outs= ide the group", + ret, TEST_OK); + ret =3D test_sort("{instructions,slots},{topdown-retiring}", 2, 1); + TEST_ASSERT_EQUAL("slots event and topdown metrics events in two groups", + ret, TEST_OK); + ret =3D test_sort("{instructions,slots},cycles,topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("slots event and metrics event are not in a group and n= ot adjacent", + ret, TEST_OK); + + return TEST_OK; +} + +static int test__x86_topdown_slots_injection(struct test_suite *test __may= be_unused, + int subtest __maybe_unused) +{ + int ret; + + if (!topdown_sys_has_perf_metrics()) + return TEST_OK; + + ret =3D test_sort("{instructions,topdown-retiring}", 3, 2); + TEST_ASSERT_EQUAL("all events in a group", ret, TEST_OK); + ret =3D test_sort("instructions,topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("all events not in a group", ret, TEST_OK); + ret =3D test_sort("{instructions},topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("event in a group but topdown metrics events outside th= e group", + ret, TEST_OK); + ret =3D test_sort("{instructions},{topdown-retiring}", 2, 1); + TEST_ASSERT_EQUAL("event and topdown metrics events in two groups", + ret, TEST_OK); + ret =3D test_sort("{instructions},cycles,topdown-retiring", 2, 1); + TEST_ASSERT_EQUAL("event and metrics event are not in a group and not adj= acent", + ret, TEST_OK); + + return TEST_OK; +} + +static struct test_case x86_topdown_tests[] =3D { + TEST_CASE("topdown events", x86_topdown), + TEST_CASE("topdown sorting", x86_topdown_sorting), + TEST_CASE("topdown slots injection", x86_topdown_slots_injection), + { .name =3D NULL, } +}; + +struct test_suite suite__x86_topdown =3D { + .desc =3D "x86 topdown", + .test_cases =3D x86_topdown_tests, +}; --=20 2.54.0.563.g4f69b47b94-goog