2023-07-05 08:37:49

by James Clark

[permalink] [raw]
Subject: [PATCH v2 0/2] perf test: Fix event parsing test on Arm

Changes since v1:

* num_entries() -> num_core_entries()

James Clark (2):
perf test: Fix event parsing test on Arm
perf test: Fix event parsing test when PERF_PMU_CAP_EXTENDED_HW_TYPE
isn't supported.

tools/perf/tests/parse-events.c | 100 ++++++++++++++++++++------------
1 file changed, 63 insertions(+), 37 deletions(-)

--
2.34.1



2023-07-05 08:54:20

by James Clark

[permalink] [raw]
Subject: [PATCH v2 2/2] perf test: Fix event parsing test when PERF_PMU_CAP_EXTENDED_HW_TYPE isn't supported.

Arm has multiple PMU types for heterogeneous systems, but doesn't
currently support PERF_PMU_CAP_EXTENDED_HW_TYPE. Make the tests
support both scenarios so that they pass on Arm, and will still pass
once PERF_PMU_CAP_EXTENDED_HW_TYPE support is added.

Fixes: 27c9fcfc1e14 ("perf test: Update parse-events expectations to test for multiple events")
Acked-by: Ian Rogers <[email protected]>
Signed-off-by: James Clark <[email protected]>
---
tools/perf/tests/parse-events.c | 86 +++++++++++++++++++--------------
1 file changed, 50 insertions(+), 36 deletions(-)

diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 21f79aa31233..b2f82847e4c3 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -20,6 +20,20 @@
#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)

+static int num_core_entries(void)
+{
+ /*
+ * If the kernel supports extended type, expect events to be
+ * opened once for each core PMU type. Otherwise fall back to the legacy
+ * behavior of opening only one event even though there are multiple
+ * PMUs
+ */
+ if (perf_pmus__supports_extended_type())
+ return perf_pmus__num_core_pmus();
+
+ return 1;
+}
+
static bool test_config(const struct evsel *evsel, __u64 expected_config)
{
__u32 type = evsel->core.attr.type;
@@ -339,7 +353,7 @@ static int test__checkevent_symbolic_name_modifier(struct evlist *evlist)
struct perf_evsel *evsel;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == perf_pmus__num_core_pmus());
+ evlist->core.nr_entries == num_core_entries());

perf_evlist__for_each_entry(&evlist->core, evsel) {
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
@@ -842,11 +856,11 @@ static int test__group1(struct evlist *evlist)
struct evsel *evsel, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (perf_pmus__num_core_pmus() * 2));
+ evlist->core.nr_entries == (num_core_entries() * 2));
TEST_ASSERT_VAL("wrong number of groups",
- evlist__nr_groups(evlist) == perf_pmus__num_core_pmus());
+ evlist__nr_groups(evlist) == num_core_entries());

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* instructions:k */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -885,7 +899,7 @@ static int test__group2(struct evlist *evlist)
struct evsel *evsel, *leader = NULL;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (2 * perf_pmus__num_core_pmus() + 1));
+ evlist->core.nr_entries == (2 * num_core_entries() + 1));
/*
* TODO: Currently the software event won't be grouped with the hardware
* event except for 1 PMU.
@@ -1051,11 +1065,11 @@ static int test__group4(struct evlist *evlist __maybe_unused)
struct evsel *evsel, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (perf_pmus__num_core_pmus() * 2));
+ evlist->core.nr_entries == (num_core_entries() * 2));
TEST_ASSERT_VAL("wrong number of groups",
- perf_pmus__num_core_pmus() == evlist__nr_groups(evlist));
+ num_core_entries() == evlist__nr_groups(evlist));

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles:u + p */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1096,11 +1110,11 @@ static int test__group5(struct evlist *evlist __maybe_unused)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (5 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (5 * num_core_entries()));
TEST_ASSERT_VAL("wrong number of groups",
- evlist__nr_groups(evlist) == (2 * perf_pmus__num_core_pmus()));
+ evlist__nr_groups(evlist) == (2 * num_core_entries()));

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles + G */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1131,7 +1145,7 @@ static int test__group5(struct evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1);
TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
}
- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles:G */
evsel = leader = evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1161,7 +1175,7 @@ static int test__group5(struct evlist *evlist __maybe_unused)
TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
TEST_ASSERT_VAL("wrong group_idx", evsel__group_idx(evsel) == 1);
}
- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles */
evsel = evsel__next(evsel);
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1182,11 +1196,11 @@ static int test__group_gh1(struct evlist *evlist)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (2 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (2 * num_core_entries()));
TEST_ASSERT_VAL("wrong number of groups",
- evlist__nr_groups(evlist) == perf_pmus__num_core_pmus());
+ evlist__nr_groups(evlist) == num_core_entries());

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles + :H group modifier */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1223,11 +1237,11 @@ static int test__group_gh2(struct evlist *evlist)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (2 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (2 * num_core_entries()));
TEST_ASSERT_VAL("wrong number of groups",
- evlist__nr_groups(evlist) == perf_pmus__num_core_pmus());
+ evlist__nr_groups(evlist) == num_core_entries());

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles + :G group modifier */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1264,11 +1278,11 @@ static int test__group_gh3(struct evlist *evlist)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (2 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (2 * num_core_entries()));
TEST_ASSERT_VAL("wrong number of groups",
- evlist__nr_groups(evlist) == perf_pmus__num_core_pmus());
+ evlist__nr_groups(evlist) == num_core_entries());

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles:G + :u group modifier */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1305,11 +1319,11 @@ static int test__group_gh4(struct evlist *evlist)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (2 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (2 * num_core_entries()));
TEST_ASSERT_VAL("wrong number of groups",
- evlist__nr_groups(evlist) == perf_pmus__num_core_pmus());
+ evlist__nr_groups(evlist) == num_core_entries());

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles:G + :uG group modifier */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1346,9 +1360,9 @@ static int test__leader_sample1(struct evlist *evlist)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (3 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (3 * num_core_entries()));

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles - sampling group leader */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1398,9 +1412,9 @@ static int test__leader_sample2(struct evlist *evlist __maybe_unused)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (2 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (2 * num_core_entries()));

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* instructions - sampling group leader */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1437,9 +1451,9 @@ static int test__checkevent_pinned_modifier(struct evlist *evlist)
struct evsel *evsel = NULL;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == perf_pmus__num_core_pmus());
+ evlist->core.nr_entries == num_core_entries());

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
evsel = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
@@ -1455,9 +1469,9 @@ static int test__pinned_group(struct evlist *evlist)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (3 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == (3 * num_core_entries()));

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles - group leader */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1500,9 +1514,9 @@ static int test__exclusive_group(struct evlist *evlist)
struct evsel *evsel = NULL, *leader;

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (3 * perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == 3 * num_core_entries());

- for (int i = 0; i < perf_pmus__num_core_pmus(); i++) {
+ for (int i = 0; i < num_core_entries(); i++) {
/* cycles - group leader */
evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel));
TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
@@ -1574,7 +1588,7 @@ static int test__checkevent_precise_max_modifier(struct evlist *evlist)
struct evsel *evsel = evlist__first(evlist);

TEST_ASSERT_VAL("wrong number of entries",
- evlist->core.nr_entries == (1 + perf_pmus__num_core_pmus()));
+ evlist->core.nr_entries == 1 + num_core_entries());
TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type);
TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_SW_TASK_CLOCK));
return TEST_OK;
--
2.34.1


2023-07-05 08:59:46

by James Clark

[permalink] [raw]
Subject: [PATCH v2 1/2] perf test: Fix event parsing test on Arm

The test looks for a PMU from sysfs with type = PERF_TYPE_RAW when
opening a raw event. Arm doesn't have a real raw PMU, only core PMUs
with unique types other than raw.

Instead of looking for a matching PMU, just test that the event type
was parsed as raw and skip the PMU search on Arm. The raw event type
test should also apply to all platforms so add it outside of the ifdef.

Fixes: aefde50a446b ("perf test: Fix parse-events tests for >1 core PMU")
Acked-by: Ian Rogers <[email protected]>
Signed-off-by: James Clark <[email protected]>
---
tools/perf/tests/parse-events.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 133218e51ab4..21f79aa31233 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -108,10 +108,21 @@ static int test__checkevent_raw(struct evlist *evlist)
TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries);

perf_evlist__for_each_evsel(&evlist->core, evsel) {
- struct perf_pmu *pmu = NULL;
+ struct perf_pmu *pmu __maybe_unused = NULL;
bool type_matched = false;

TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, 0x1a));
+ TEST_ASSERT_VAL("event not parsed as raw type",
+ evsel->attr.type == PERF_TYPE_RAW);
+#if defined(__aarch64__)
+ /*
+ * Arm doesn't have a real raw type PMU in sysfs, so raw events
+ * would never match any PMU. However, RAW events on Arm will
+ * always successfully open on the first available core PMU
+ * so no need to test for a matching type here.
+ */
+ type_matched = raw_type_match = true;
+#else
while ((pmu = perf_pmus__scan(pmu)) != NULL) {
if (pmu->type == evsel->attr.type) {
TEST_ASSERT_VAL("PMU type expected once", !type_matched);
@@ -120,6 +131,7 @@ static int test__checkevent_raw(struct evlist *evlist)
raw_type_match = true;
}
}
+#endif
TEST_ASSERT_VAL("No PMU found for type", type_matched);
}
TEST_ASSERT_VAL("Raw PMU not matched", raw_type_match);
--
2.34.1


2023-07-06 06:02:42

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH v2 0/2] perf test: Fix event parsing test on Arm

On Wed, Jul 5, 2023 at 1:27 AM James Clark <[email protected]> wrote:
>
> Changes since v1:
>
> * num_entries() -> num_core_entries()
>
> James Clark (2):
> perf test: Fix event parsing test on Arm
> perf test: Fix event parsing test when PERF_PMU_CAP_EXTENDED_HW_TYPE
> isn't supported.

Applied to perf-tools-next, thanks!