From nobody Mon Jun 8 04:15:56 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 240C43783AA for ; Tue, 2 Jun 2026 07:31:45 +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=1780385509; cv=none; b=iZVrIZdXHUNSkOBCoYpqGUe34EYKSjkIDuqskKAX70NNklL01REM5tVtfxc1/RkguRYafFf25Q8nQ3/PEd4WO6EaU8vJGcIV/i4uVbwYRRixBvA+w+Gy8UQ8Ge26+xCX7Uz6MoXxKdz0BvHrnoIkm44wFSC/KED/TiRI0ytnhOg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780385509; c=relaxed/simple; bh=HOLsGrzPwb4DNT0okKLiE6IWyUmPVujvsWI4pn0MeAU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=QFXwClmG5v6W93ldmVy7Pd3j0bIOT1Wy1F8B67rrgqQZH3NbDw4PmSeFOrfVseJnlKBsTeqwpZQxMAqkyOg/QE/E2lg5shbsy6dxrZJ8Dr97BwyygtjUigQvw4KHcWX8uX/T5T0hIU0ulk9LUjCs4b0+Q+y3k22Mq/QgJVrjdaA= 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=WDpQvSJo; 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="WDpQvSJo" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-304e7fbfaf5so6505489eec.1 for ; Tue, 02 Jun 2026 00:31:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1780385505; x=1780990305; 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=JLGKD2UBqZ0IwdY88He6qVXzMezl5EdtyP0MxhmdBzw=; b=WDpQvSJoCukafR0wHZhUHjoahiHlBqCHB+qX9rFw8oQ3TYYlid1D/uCLblprqRHwND FLJG+H0H0N35FWJTMSgfgOLTg9ZsyvaU7I26pE4WvGvdWLWzYzrzgWNYiNRAZnll4BWI YJY5ZDXv4Ic0HNlmwZRLvadp+URHBzbd+nqNtVzRWgjhdjcds9TkQrChJt9x/HJTS5eZ +M6MwWz5Pd4sZrrWn5rrqheGnhRZL8gwWFaAr9iuul167E03g03AkPvE9hj2REbA9lHu y+ZZ5TdZWowCqHy5SsMpdQxVvDnlN2ehYa4+f16wZwZ1vuy7jSWDDzSeTQMFr2Hyt8mr Kqtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780385505; x=1780990305; 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=JLGKD2UBqZ0IwdY88He6qVXzMezl5EdtyP0MxhmdBzw=; b=h8rYAL68uzP4dSGKDCqcADZeiQhzc2zqV4/pEDetCn5jO8QHjcbWsG34W65u393Lf5 +ZBNij6XIMHaK3Qr08+kmFJkwokdwqL7FzX0lfzjqFxE5TLL5RPdXD5zB2IzDFqIWtLn hKXVzTBiWS59fQCNnQTVWgvcqvRIiD0YGZOfWcLm5xF6S91nm46x1tBtNqIkEvRPz6vH tNhyD/oZ+zjQL9UZ1fGL3WDS+zEo+E6cvSgYql6O9k4CpkGpl7YwQBE/c3fDOIFe98Xe rmrLfZRl7w7gMjIrAHon0SGKU7j7sGVGfrXqTEMVnp6qqjtkSSVoSYMyZdRjGUaL5Ey/ VrUA== X-Forwarded-Encrypted: i=1; AFNElJ/IQfWLUbGLzCrSREwi/NVUW6nGzI+btuFUORXB0NQnDx9L/cU2z3xDDwADekcD8YDDu1JHE9XBytmfoyM=@vger.kernel.org X-Gm-Message-State: AOJu0YwQVK1OnLga7zF1e4PDRkN8el08k1oSjvqblzG/5huEcpIp8c3G iJgNZUDFziVfyytEs0nvSmDsQqjmEBKjzIk6e9SyqS3PWF9PHtdBgmkSOKSvA5Sr9jOVsKaRUWj Ijc8Q4vm9kw== X-Received: from dyaf2-n1.prod.google.com ([2002:a05:693c:8382:10b0:304:dfee:3633]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:2313:b0:304:2af3:5ffa with SMTP id 5a478bee46e88-304fa5a949cmr7666821eec.19.1780385504662; Tue, 02 Jun 2026 00:31:44 -0700 (PDT) Date: Tue, 2 Jun 2026 00:31:18 -0700 In-Reply-To: <20260602073132.2653307-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: <20260601061401.1541457-1-irogers@google.com> <20260602073132.2653307-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.929.g9b7fa37559-goog Message-ID: <20260602073132.2653307-4-irogers@google.com> Subject: [PATCH v7] perf pmu-events: Add API to get metric table name and iterate tables From: Ian Rogers To: irogers@google.com, acme@kernel.org, namhyung@kernel.org Cc: adrian.hunter@intel.com, alexander.shishkin@linux.intel.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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add name field to struct pmu_metrics_table and populate it in generated tables. Add pmu_metrics_table__name() to retrieve the name. Add pmu_metrics_table__for_each_table() to iterate over all known metric tables. This will be used to break apart slow metric tests per table. Assisted-by: Gemini-CLI:Google Gemini 3 Signed-off-by: Ian Rogers --- tools/perf/pmu-events/empty-pmu-events.c | 46 ++++++++++++++++++- tools/perf/pmu-events/jevents.py | 56 +++++++++++++++++++++++- tools/perf/pmu-events/pmu-events.h | 5 +++ 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-even= ts/empty-pmu-events.c index ad5ade37adb0..2af4865713be 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -5403,6 +5403,7 @@ struct pmu_events_table { =20 /* Struct used to make the PMU metric table implementation opaque to calle= rs. */ struct pmu_metrics_table { + const char *name; const struct pmu_table_entry *pmus; uint32_t num_pmus; }; @@ -5435,6 +5436,7 @@ static const struct pmu_events_map pmu_events_map[] = =3D { .num_pmus =3D ARRAY_SIZE(pmu_events__common), }, .metric_table =3D { + .name =3D "common", .pmus =3D pmu_metrics__common, .num_pmus =3D ARRAY_SIZE(pmu_metrics__common), }, @@ -5447,6 +5449,7 @@ static const struct pmu_events_map pmu_events_map[] = =3D { .num_pmus =3D ARRAY_SIZE(pmu_events__test_soc_cpu), }, .metric_table =3D { + .name =3D "test_soc_cpu", .pmus =3D pmu_metrics__test_soc_cpu, .num_pmus =3D ARRAY_SIZE(pmu_metrics__test_soc_cpu), } @@ -5455,7 +5458,7 @@ static const struct pmu_events_map pmu_events_map[] = =3D { .arch =3D 0, .cpuid =3D 0, .event_table =3D { 0, 0 }, - .metric_table =3D { 0, 0 }, + .metric_table =3D { 0 }, } }; =20 @@ -5475,7 +5478,7 @@ static const struct pmu_sys_events pmu_sys_event_tabl= es[] =3D { }, { .event_table =3D { 0, 0 }, - .metric_table =3D { 0, 0 }, + .metric_table =3D { 0 }, }, }; =20 @@ -5990,6 +5993,45 @@ int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, v= oid *data) } /* clang-format on */ =20 +const char *pmu_metrics_table__name(const struct pmu_metrics_table *table) +{ + return table ? table->name : NULL; +} + +int pmu_metrics_table__iterate_tables(pmu_metrics_table_iter_t fn, void *d= ata) +{ + size_t i; + int ret; + + for (i =3D 0; pmu_events_map[i].cpuid; i++) { + size_t j; + bool found =3D false; + + if (!pmu_events_map[i].metric_table.pmus) + continue; + for (j =3D 0; j < i; j++) { + if (pmu_events_map[j].metric_table.pmus =3D=3D + pmu_events_map[i].metric_table.pmus) { + found =3D true; + break; + } + } + if (found) + continue; + ret =3D fn(&pmu_events_map[i].metric_table, data); + if (ret) + return ret; + } + for (i =3D 0; pmu_sys_event_tables[i].name; i++) { + if (!pmu_sys_event_tables[i].metric_table.pmus) + continue; + ret =3D fn(&pmu_sys_event_tables[i].metric_table, data); + if (ret) + return ret; + } + return 0; +} + static const int metricgroups[][2] =3D { =20 }; diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jeven= ts.py index 6f80f937f9f9..3e56c20f2978 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -712,6 +712,7 @@ struct pmu_events_table { =20 /* Struct used to make the PMU metric table implementation opaque to calle= rs. */ struct pmu_metrics_table { +\tconst char *name; \tconst struct pmu_table_entry *pmus; \tuint32_t num_pmus; }; @@ -747,6 +748,7 @@ static const struct pmu_events_map pmu_events_map[] =3D= { \t\t.num_pmus =3D ARRAY_SIZE(pmu_events__test_soc_cpu), \t}, \t.metric_table =3D { +\t\t.name =3D "test_soc_cpu", \t\t.pmus =3D pmu_metrics__test_soc_cpu, \t\t.num_pmus =3D ARRAY_SIZE(pmu_metrics__test_soc_cpu), \t} @@ -761,6 +763,7 @@ static const struct pmu_events_map pmu_events_map[] =3D= { \t\t.num_pmus =3D ARRAY_SIZE(pmu_events__common), \t}, \t.metric_table =3D { +\t\t.name =3D "common", \t\t.pmus =3D pmu_metrics__common, \t\t.num_pmus =3D ARRAY_SIZE(pmu_metrics__common), \t}, @@ -781,8 +784,10 @@ static const struct pmu_events_map pmu_events_map[] = =3D { event_size =3D '0' metric_tblname =3D file_name_to_table_name('pmu_metrics_', [],= row[2].replace('/', '_')) if metric_tblname in _metric_tables: + metric_name =3D f'"{metric_tblname.replace("pmu_metrics__", = "")}"' metric_size =3D f'ARRAY_SIZE({metric_tblname})' else: + metric_name =3D 'NULL' metric_tblname =3D 'NULL' metric_size =3D '0' if event_size =3D=3D '0' and metric_size =3D=3D '0': @@ -796,6 +801,7 @@ static const struct pmu_events_map pmu_events_map[] =3D= { \t\t.num_pmus =3D {event_size} \t}}, \t.metric_table =3D {{ +\t\t.name =3D {metric_name}, \t\t.pmus =3D {metric_tblname}, \t\t.num_pmus =3D {metric_size} \t}} @@ -807,12 +813,55 @@ static const struct pmu_events_map pmu_events_map[] = =3D { \t.arch =3D 0, \t.cpuid =3D 0, \t.event_table =3D { 0, 0 }, -\t.metric_table =3D { 0, 0 }, +\t.metric_table =3D { 0 }, } }; """) =20 =20 +def print_metric_table_functions() -> None: + _args.output_file.write(""" +const char *pmu_metrics_table__name(const struct pmu_metrics_table *table) +{ +\treturn table ? table->name : NULL; +} + +int pmu_metrics_table__iterate_tables(pmu_metrics_table_iter_t fn, void *d= ata) +{ +\tsize_t i; +\tint ret; + +\tfor (i =3D 0; pmu_events_map[i].cpuid; i++) { +\t\tsize_t j; +\t\tbool found =3D false; + +\t\tif (!pmu_events_map[i].metric_table.pmus) +\t\t\tcontinue; +\t\tfor (j =3D 0; j < i; j++) { +\t\t\tif (pmu_events_map[j].metric_table.pmus =3D=3D +\t\t\t pmu_events_map[i].metric_table.pmus) { +\t\t\t\tfound =3D true; +\t\t\t\tbreak; +\t\t\t} +\t\t} +\t\tif (found) +\t\t\tcontinue; +\t\tret =3D fn(&pmu_events_map[i].metric_table, data); +\t\tif (ret) +\t\t\treturn ret; +\t} +\tfor (i =3D 0; pmu_sys_event_tables[i].name; i++) { +\t\tif (!pmu_sys_event_tables[i].metric_table.pmus) +\t\t\tcontinue; +\t\tret =3D fn(&pmu_sys_event_tables[i].metric_table, data); +\t\tif (ret) +\t\t\treturn ret; +\t} +\treturn 0; +} +""") + + def print_system_mapping_table() -> None: """C struct mapping table array for tables from /sys directories.""" _args.output_file.write(""" @@ -835,6 +884,7 @@ static const struct pmu_sys_events pmu_sys_event_tables= [] =3D { if metric_tblname in _sys_metric_tables: _args.output_file.write(f""" \t\t.metric_table =3D {{ +\t\t\t.name =3D "{metric_tblname.replace('pmu_metrics__', '')}", \t\t\t.pmus =3D {metric_tblname}, \t\t\t.num_pmus =3D ARRAY_SIZE({metric_tblname}) \t\t}},""") @@ -848,6 +898,7 @@ static const struct pmu_sys_events pmu_sys_event_tables= [] =3D { continue _args.output_file.write(f"""\t{{ \t\t.metric_table =3D {{ +\t\t\t.name =3D "{tblname.replace('pmu_metrics__', '')}", \t\t\t.pmus =3D {tblname}, \t\t\t.num_pmus =3D ARRAY_SIZE({tblname}) \t\t}}, @@ -856,7 +907,7 @@ static const struct pmu_sys_events pmu_sys_event_tables= [] =3D { """) _args.output_file.write("""\t{ \t\t.event_table =3D { 0, 0 }, -\t\t.metric_table =3D { 0, 0 }, +\t\t.metric_table =3D { 0 }, \t}, }; =20 @@ -1486,6 +1537,7 @@ struct pmu_table_entry { print_mapping_table(archs) print_system_mapping_table() _args.output_file.write('/* clang-format on */\n') + print_metric_table_functions() print_metricgroups() _args.output_file.close() if _args.output_string_file: diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu= -events.h index d3b24014c6ff..cb55c9fbca43 100644 --- a/tools/perf/pmu-events/pmu-events.h +++ b/tools/perf/pmu-events/pmu-events.h @@ -91,6 +91,9 @@ typedef int (*pmu_metric_iter_fn)(const struct pmu_metric= *pm, const struct pmu_metrics_table *table, void *data); =20 +typedef int (*pmu_metrics_table_iter_t)(const struct pmu_metrics_table *ta= ble, + void *data); + int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu, pmu_event_iter_fn fn, @@ -112,6 +115,8 @@ size_t pmu_events_table__num_events(const struct pmu_ev= ents_table *table, =20 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *tab= le, pmu_metric_iter_fn fn, void *data); +const char *pmu_metrics_table__name(const struct pmu_metrics_table *table); +int pmu_metrics_table__iterate_tables(pmu_metrics_table_iter_t fn, void *d= ata); /* * Search for a table and entry matching with pmu__name_wildcard_match or = any * tables if pmu is NULL. Each matching metric has fn called on it. 0 impl= ies to --=20 2.54.0.929.g9b7fa37559-goog