Discussion:
[PATCH v2 2/7] perf jevents: Support test events folder
(too old to reply)
John Garry
2020-03-17 11:02:14 UTC
Permalink
With the goal of supporting pmu-events test case, introduce support for a
test events folder.

These test events can be used for testing generation of pmu-event tables
and alias creation for any arch.

When running the pmu-events test case, these test events will be used
as the platform-agnostic events, so aliases can be created per-PMU and
validated against known expected values.

To support the test events, add a "testcpu" entry in pmu_events_map[].
The pmu-events test will be able to lookup the events map for "testcpu",
to verify the generated tables against expected values.

The resultant generated pmu-events.c will now look like the following:

struct pmu_event pme_ampere_emag[] = {
{
.name = "ldrex_spec",
.event = "event=0x6c",
.desc = "Exclusive operation spe...",
.topic = "intrinsic",
.long_desc = "Exclusive operation ...",
},
...
};

struct pmu_event pme_test_cpu[] = {
{
.name = "uncore_hisi_ddrc.flux_wcmd",
.event = "event=0x2",
.desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
.topic = "uncore",
.long_desc = "DDRC write commands",
.pmu = "hisi_sccl,ddrc",
},
{
.name = "unc_cbo_xsnp_response.miss_eviction",
.event = "umask=0x81,event=0x22",
.desc = "Unit: uncore_cbox A cross-core snoop resulted ...",
.topic = "uncore",
.long_desc = "A cross-core snoop resulted from L3 ...",
.pmu = "uncore_cbox",
},
{
.name = "eist_trans",
.event = "umask=0x0,period=200000,event=0x3a",
.desc = "Number of Enhanced Intel SpeedStep(R) ...",
.topic = "other",
},
{
.name = 0,
},
};

struct pmu_events_map pmu_events_map[] = {
...
{
.cpuid = "0x00000000500f0000",
.version = "v1",
.type = "core",
.table = pme_ampere_emag
},
...
{
.cpuid = "testcpu",
.version = "v1",
.type = "core",
.table = pme_test_cpu,
},
{
.cpuid = 0,
.version = 0,
.type = 0,
.table = 0,
},
};

Signed-off-by: John Garry <***@huawei.com>
---
tools/perf/pmu-events/jevents.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index 27b4da80f751..3343ba27271b 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -764,6 +764,19 @@ static void print_mapping_table_suffix(FILE *outfp)
fprintf(outfp, "};\n");
}

+static void print_mapping_test_table(FILE *outfp)
+{
+ /*
+ * Print the terminating, NULL entry.
+ */
+ fprintf(outfp, "{\n");
+ fprintf(outfp, "\t.cpuid = \"testcpu\",\n");
+ fprintf(outfp, "\t.version = \"v1\",\n");
+ fprintf(outfp, "\t.type = \"core\",\n");
+ fprintf(outfp, "\t.table = pme_test_cpu,\n");
+ fprintf(outfp, "},\n");
+}
+
static int process_mapfile(FILE *outfp, char *fpath)
{
int n = 16384;
@@ -841,6 +854,7 @@ static int process_mapfile(FILE *outfp, char *fpath)
}

out:
+ print_mapping_test_table(outfp);
print_mapping_table_suffix(outfp);
fclose(mapfp);
free(line);
@@ -1161,6 +1175,22 @@ int main(int argc, char *argv[])
goto empty_map;
}

+ sprintf(ldirname, "%s/test", start_dirname);
+
+ rc = nftw(ldirname, process_one_file, maxfds, 0);
+ if (rc && verbose) {
+ pr_info("%s: Error walking file tree %s rc=%d for test\n",
+ prog, ldirname, rc);
+ goto empty_map;
+ } else if (rc < 0) {
+ /* Make build fail */
+ free_arch_std_events();
+ ret = 1;
+ goto out_free_mapfile;
+ } else if (rc) {
+ goto empty_map;
+ }
+
if (close_table)
print_events_table_suffix(eventsfp);
--
2.12.3
John Garry
2020-03-17 11:02:17 UTC
Permalink
Add a function to decide whether a PMU is a core PMU.

Signed-off-by: John Garry <***@huawei.com>
---
tools/perf/util/pmu.c | 5 +++++
tools/perf/util/pmu.h | 1 +
2 files changed, 6 insertions(+)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index c616a06a34a8..55129d09f19d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1400,6 +1400,11 @@ static void wordwrap(char *s, int start, int max, int corr)
}
}

+bool is_pmu_core(const char *name)
+{
+ return !strcmp(name, "cpu") || is_arm_pmu_core(name);
+}
+
void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
bool long_desc, bool details_flag, bool deprecated)
{
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 0b4a0efae38e..b756946ae78d 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -88,6 +88,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);

struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);

+bool is_pmu_core(const char *name);
void print_pmu_events(const char *event_glob, bool name_only, bool quiet,
bool long_desc, bool details_flag,
bool deprecated);
--
2.12.3
John Garry
2020-03-17 11:02:18 UTC
Permalink
The perf pmu-events test will want to use pmu_uncore_alias_match(), so
make it public.

Signed-off-by: John Garry <***@huawei.com>
---
tools/perf/util/pmu.c | 2 +-
tools/perf/util/pmu.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 55129d09f19d..616fbda7c3fc 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -698,7 +698,7 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
return map;
}

-static bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
+bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
{
char *tmp = NULL, *tok, *str;
bool res;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index b756946ae78d..5fb3f16828df 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -103,6 +103,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
struct pmu_events_map *map);

struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu);
+bool pmu_uncore_alias_match(const char *pmu_name, const char *name);

int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
--
2.12.3
John Garry
2020-03-17 11:02:13 UTC
Permalink
Add some test PMU events. The events are randomly chosen from x86 and
arm64 JSONs. The events include CPU and uncore events.

Signed-off-by: John Garry <***@huawei.com>
---
.../perf/pmu-events/arch/test/test_cpu/branch.json | 12 ++++++++++
.../perf/pmu-events/arch/test/test_cpu/other.json | 26 ++++++++++++++++++++++
.../perf/pmu-events/arch/test/test_cpu/uncore.json | 21 +++++++++++++++++
3 files changed, 59 insertions(+)
create mode 100644 tools/perf/pmu-events/arch/test/test_cpu/branch.json
create mode 100644 tools/perf/pmu-events/arch/test/test_cpu/other.json
create mode 100644 tools/perf/pmu-events/arch/test/test_cpu/uncore.json

diff --git a/tools/perf/pmu-events/arch/test/test_cpu/branch.json b/tools/perf/pmu-events/arch/test/test_cpu/branch.json
new file mode 100644
index 000000000000..93ddfd8053ca
--- /dev/null
+++ b/tools/perf/pmu-events/arch/test/test_cpu/branch.json
@@ -0,0 +1,12 @@
+[
+ {
+ "EventName": "bp_l1_btb_correct",
+ "EventCode": "0x8a",
+ "BriefDescription": "L1 BTB Correction."
+ },
+ {
+ "EventName": "bp_l2_btb_correct",
+ "EventCode": "0x8b",
+ "BriefDescription": "L2 BTB Correction."
+ }
+]
diff --git a/tools/perf/pmu-events/arch/test/test_cpu/other.json b/tools/perf/pmu-events/arch/test/test_cpu/other.json
new file mode 100644
index 000000000000..7d53d7ecd723
--- /dev/null
+++ b/tools/perf/pmu-events/arch/test/test_cpu/other.json
@@ -0,0 +1,26 @@
+[
+ {
+ "EventCode": "0x6",
+ "Counter": "0,1",
+ "UMask": "0x80",
+ "EventName": "SEGMENT_REG_LOADS.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of segment register loads."
+ },
+ {
+ "EventCode": "0x9",
+ "Counter": "0,1",
+ "UMask": "0x20",
+ "EventName": "DISPATCH_BLOCKED.ANY",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Memory cluster signals to block micro-op dispatch for any reason"
+ },
+ {
+ "EventCode": "0x3A",
+ "Counter": "0,1",
+ "UMask": "0x0",
+ "EventName": "EIST_TRANS",
+ "SampleAfterValue": "200000",
+ "BriefDescription": "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions"
+ }
+]
\ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/test/test_cpu/uncore.json b/tools/perf/pmu-events/arch/test/test_cpu/uncore.json
new file mode 100644
index 000000000000..d0a890cc814d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/test/test_cpu/uncore.json
@@ -0,0 +1,21 @@
+[
+ {
+ "EventCode": "0x02",
+ "EventName": "uncore_hisi_ddrc.flux_wcmd",
+ "BriefDescription": "DDRC write commands",
+ "PublicDescription": "DDRC write commands",
+ "Unit": "hisi_sccl,ddrc"
+ },
+ {
+ "Unit": "CBO",
+ "EventCode": "0x22",
+ "UMask": "0x81",
+ "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION",
+ "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+ "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+ "Counter": "0,1",
+ "CounterMask": "0",
+ "Invert": "0",
+ "EdgeDetect": "0"
+ }
+]
--
2.12.3
John Garry
2020-03-17 11:02:16 UTC
Permalink
Add a pmu-events test.

The initial test will verify that the test tables in generated pmu-events.c
match against known, expected values.

For known events added in pmu-events/arch/test, we need to add an entry
in test_cpu_aliases_events[] or test_uncore_events[].

A sample run is as follows for x86:

***@linux-3c19:~/linux> tools/perf/perf test -vv 10
10: PMU event aliases :
--- start ---
test child forked, pid 5316
testing event table bp_l1_btb_correct: pass
testing event table bp_l2_btb_correct: pass
testing event table segment_reg_loads.any: pass
testing event table dispatch_blocked.any: pass
testing event table eist_trans: pass
testing event table uncore_hisi_ddrc.flux_wcmd: pass
testing event table unc_cbo_xsnp_response.miss_eviction: pass
test child finished with 0
---- end ----
PMU event aliases: Ok

Signed-off-by: John Garry <***@huawei.com>
---
tools/perf/tests/Build | 1 +
tools/perf/tests/builtin-test.c | 4 +
tools/perf/tests/pmu-events.c | 227 ++++++++++++++++++++++++++++++++++++++++
tools/perf/tests/tests.h | 1 +
4 files changed, 233 insertions(+)
create mode 100644 tools/perf/tests/pmu-events.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 1692529639b0..b3d1bf13ca07 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -14,6 +14,7 @@ perf-y += evsel-roundtrip-name.o
perf-y += evsel-tp-sched.o
perf-y += fdarray.o
perf-y += pmu.o
+perf-y += pmu-events.o
perf-y += hists_common.o
perf-y += hists_link.o
perf-y += hists_filter.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 5f05db75cdd8..5921af647c4a 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -73,6 +73,10 @@ static struct test generic_tests[] = {
.func = test__pmu,
},
{
+ .desc = "PMU events",
+ .func = test__pmu_events,
+ },
+ {
.desc = "DSO data read",
.func = test__dso_data,
},
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
new file mode 100644
index 000000000000..19a30807c880
--- /dev/null
+++ b/tools/perf/tests/pmu-events.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "parse-events.h"
+#include "pmu.h"
+#include "tests.h"
+#include <errno.h>
+#include <stdio.h>
+#include <linux/kernel.h>
+
+#include "debug.h"
+#include "../pmu-events/pmu-events.h"
+
+struct perf_pmu_test_event {
+ struct pmu_event event;
+};
+static struct perf_pmu_test_event test_cpu_events[] = {
+ {
+ .event = {
+ .name = "bp_l1_btb_correct",
+ .event = "event=0x8a",
+ .desc = "L1 BTB Correction",
+ .topic = "branch",
+ },
+ },
+ {
+ .event = {
+ .name = "bp_l2_btb_correct",
+ .event = "event=0x8b",
+ .desc = "L2 BTB Correction",
+ .topic = "branch",
+ },
+ },
+ {
+ .event = {
+ .name = "segment_reg_loads.any",
+ .event = "umask=0x80,period=200000,event=0x6",
+ .desc = "Number of segment register loads",
+ .topic = "other",
+ },
+ },
+ {
+ .event = {
+ .name = "dispatch_blocked.any",
+ .event = "umask=0x20,period=200000,event=0x9",
+ .desc = "Memory cluster signals to block micro-op dispatch for any reason",
+ .topic = "other",
+ },
+ },
+ {
+ .event = {
+ .name = "eist_trans",
+ .event = "umask=0x0,period=200000,event=0x3a",
+ .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
+ .topic = "other",
+ },
+ },
+ { /* sentinel */
+ }
+};
+
+static struct perf_pmu_test_event test_uncore_events[] = {
+ {
+ .event = {
+ .name = "uncore_hisi_ddrc.flux_wcmd",
+ .event = "event=0x2",
+ .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
+ .topic = "uncore",
+ .long_desc = "DDRC write commands",
+ .pmu = "hisi_sccl,ddrc",
+ },
+ },
+ {
+ .event = {
+ .name = "unc_cbo_xsnp_response.miss_eviction",
+ .event = "umask=0x81,event=0x22",
+ .desc = "Unit: uncore_cbox A cross-core snoop resulted from L3 Eviction which misses in some processor core",
+ .topic = "uncore",
+ .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
+ .pmu = "uncore_cbox",
+ },
+ },
+ { /* sentinel */
+ }
+};
+
+const int total_test_events_size = ARRAY_SIZE(test_uncore_events);
+
+static bool is_same(const char *reference, const char *test)
+{
+ if (!reference && !test)
+ return true;
+
+ if (reference && !test)
+ return false;
+
+ if (!reference && test)
+ return false;
+
+ return !strcmp(reference, test);
+}
+
+static struct pmu_events_map *__test_pmu_get_events_map(void)
+{
+ struct pmu_events_map *map;
+
+ for (map = &pmu_events_map[0]; map->cpuid; map++) {
+ if (!strcmp(map->cpuid, "testcpu"))
+ return map;
+ }
+
+ pr_err("could not find test events map\n");
+
+ return NULL;
+}
+
+/* Verify generated events from pmu-events.c is as expected */
+static int __test_pmu_event_table(void)
+{
+ struct pmu_events_map *map = __test_pmu_get_events_map();
+ struct pmu_event *table;
+ int map_events = 0, expected_events;
+
+ /* ignore 2x sentinels */
+ expected_events = ARRAY_SIZE(test_cpu_events) +
+ ARRAY_SIZE(test_uncore_events) - 2;
+
+ if (!map)
+ return -1;
+
+ for (table = map->table; table->name; table++) {
+ struct perf_pmu_test_event *test;
+ struct pmu_event *te;
+ bool found = false;
+
+ if (table->pmu)
+ test = &test_uncore_events[0];
+ else
+ test = &test_cpu_events[0];
+
+ te = &test->event;
+
+ for (; te->name; test++, te = &test->event) {
+ if (strcmp(table->name, te->name))
+ continue;
+ found = true;
+ map_events++;
+
+ if (!is_same(table->desc, te->desc)) {
+ pr_debug2("testing event table %s: mismatched desc, %s vs %s\n",
+ table->name, table->desc, te->desc);
+ return -1;
+ }
+
+ if (!is_same(table->topic, te->topic)) {
+ pr_debug2("testing event table %s: mismatched topic, %s vs %s\n",
+ table->name, table->topic,
+ te->topic);
+ return -1;
+ }
+
+ if (!is_same(table->long_desc, te->long_desc)) {
+ pr_debug2("testing event table %s: mismatched long_desc, %s vs %s\n",
+ table->name, table->long_desc,
+ te->long_desc);
+ return -1;
+ }
+
+ if (!is_same(table->unit, te->unit)) {
+ pr_debug2("testing event table %s: mismatched unit, %s vs %s\n",
+ table->name, table->unit,
+ te->unit);
+ return -1;
+ }
+
+ if (!is_same(table->perpkg, te->perpkg)) {
+ pr_debug2("testing event table %s: mismatched perpkg, %s vs %s\n",
+ table->name, table->perpkg,
+ te->perpkg);
+ return -1;
+ }
+
+ if (!is_same(table->metric_expr, te->metric_expr)) {
+ pr_debug2("testing event table %s: mismatched metric_expr, %s vs %s\n",
+ table->name, table->metric_expr,
+ te->metric_expr);
+ return -1;
+ }
+
+ if (!is_same(table->metric_name, te->metric_name)) {
+ pr_debug2("testing event table %s: mismatched metric_name, %s vs %s\n",
+ table->name, table->metric_name,
+ te->metric_name);
+ return -1;
+ }
+
+ if (!is_same(table->deprecated, te->deprecated)) {
+ pr_debug2("testing event table %s: mismatched deprecated, %s vs %s\n",
+ table->name, table->deprecated,
+ te->deprecated);
+ return -1;
+ }
+
+ pr_debug("testing event table %s: pass\n", table->name);
+ }
+
+ if (!found) {
+ pr_err("testing event table: could not find event %s\n",
+ table->name);
+ return -1;
+ }
+ }
+
+ if (map_events != expected_events) {
+ pr_err("testing event table: found %d, but expected %d\n",
+ map_events, expected_events);
+ return -1;
+ }
+
+ return 0;
+}
+int test__pmu_events(struct test *test __maybe_unused,
+ int subtest __maybe_unused)
+{
+ if (__test_pmu_event_table())
+ return -1;
+
+ return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 9a160fef47c9..61a1ab032080 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -49,6 +49,7 @@ int test__perf_evsel__roundtrip_name_test(struct test *test, int subtest);
int test__perf_evsel__tp_sched_test(struct test *test, int subtest);
int test__syscall_openat_tp_fields(struct test *test, int subtest);
int test__pmu(struct test *test, int subtest);
+int test__pmu_events(struct test *test, int subtest);
int test__attr(struct test *test, int subtest);
int test__dso_data(struct test *test, int subtest);
int test__dso_data_cache(struct test *test, int subtest);
--
2.12.3
John Garry
2020-03-17 11:02:19 UTC
Permalink
Add creating event aliases to the pmu-events test.

So currently we verify that the generated pmu-events.c is as expected for
some test events. Now test that we generate aliases as expected for those
events during normal operation.

For that, we cycle through each HW PMU in the system, and use the test
events to create aliases, and verify those against known, expected values.

For core PMUs, we should create an alias for every event in
test_cpu_events[].

However, for uncore PMUs, they need to be matched by the pmu_event.pmu
member, so use test_uncore_events[]; so check the match beforehand with
pmu_uncore_alias_match().

A sample run is as follows for my x86 machine:

***@linux-3c19:~/linux> tools/perf/perf test -vv 10
10: PMU events :
--- start ---

...

testing PMU uncore_arb aliases: no events to match
testing PMU cstate_pkg aliases: no events to match
skipping testing PMU breakpoint
testing aliases PMU uncore_cbox_1: matched event unc_cbo_xsnp_response.miss_eviction
testing PMU uncore_cbox_1 aliases: pass
testing PMU power aliases: no events to match
testing aliases PMU cpu: matched event bp_l1_btb_correct
testing aliases PMU cpu: matched event bp_l2_btb_correct
testing aliases PMU cpu: matched event segment_reg_loads.any
testing aliases PMU cpu: matched event dispatch_blocked.any
testing aliases PMU cpu: matched event eist_trans
testing PMU cpu aliases: pass
testing PMU intel_pt aliases: no events to match
skipping testing PMU software
skipping testing PMU intel_bts
testing PMU uncore_imc aliases: no events to match
testing aliases PMU uncore_cbox_0: matched event unc_cbo_xsnp_response.miss_eviction
testing PMU uncore_cbox_0 aliases: pass
testing PMU cstate_core aliases: no events to match
skipping testing PMU tracepoint
testing PMU msr aliases: no events to match
test child finished with 0

Signed-off-by: John Garry <***@huawei.com>
---
tools/perf/tests/pmu-events.c | 148 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 147 insertions(+), 1 deletion(-)

diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 19a30807c880..1a0660e5ee97 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -5,13 +5,24 @@
#include <errno.h>
#include <stdio.h>
#include <linux/kernel.h>
-
+#include <linux/zalloc.h>
#include "debug.h"
#include "../pmu-events/pmu-events.h"

struct perf_pmu_test_event {
struct pmu_event event;
+
+ /* extra events for aliases */
+ const char *alias_str;
+
+ /*
+ * Note: For when PublicDescription does not exist in the JSON, we
+ * will have no long_desc in pmu_event.long_desc, but long_desc may
+ * be set in the alias.
+ */
+ const char *alias_long_desc;
};
+
static struct perf_pmu_test_event test_cpu_events[] = {
{
.event = {
@@ -20,6 +31,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L1 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8a",
+ .alias_long_desc = "L1 BTB Correction",
},
{
.event = {
@@ -28,6 +41,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L2 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8b",
+ .alias_long_desc = "L2 BTB Correction",
},
{
.event = {
@@ -36,6 +51,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "Number of segment register loads",
.topic = "other",
},
+ .alias_str = "umask=0x80,(null)=0x30d40,event=0x6",
+ .alias_long_desc = "Number of segment register loads",
},
{
.event = {
@@ -44,6 +61,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "Memory cluster signals to block micro-op dispatch for any reason",
.topic = "other",
},
+ .alias_str = "umask=0x20,(null)=0x30d40,event=0x9",
+ .alias_long_desc = "Memory cluster signals to block micro-op dispatch for any reason",
},
{
.event = {
@@ -52,6 +71,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
.topic = "other",
},
+ .alias_str = "umask=0,(null)=0x30d40,event=0x3a",
+ .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
},
{ /* sentinel */
}
@@ -67,6 +88,8 @@ static struct perf_pmu_test_event test_uncore_events[] = {
.long_desc = "DDRC write commands",
.pmu = "hisi_sccl,ddrc",
},
+ .alias_str = "event=0x2",
+ .alias_long_desc = "DDRC write commands",
},
{
.event = {
@@ -77,6 +100,8 @@ static struct perf_pmu_test_event test_uncore_events[] = {
.long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
.pmu = "uncore_cbox",
},
+ .alias_str = "umask=0x81,event=0x22",
+ .alias_long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
},
{ /* sentinel */
}
@@ -217,11 +242,132 @@ static int __test_pmu_event_table(void)

return 0;
}
+
+static struct perf_pmu_alias *find_alias(const char *test_event, struct list_head *aliases)
+{
+ struct perf_pmu_alias *alias;
+
+ list_for_each_entry(alias, aliases, list)
+ if (!strcmp(test_event, alias->name))
+ return alias;
+
+ return NULL;
+}
+
+/* Verify aliases are as expected */
+static int __test__pmu_event_aliases(char *pmu_name, int *count)
+{
+ struct perf_pmu_test_event *test;
+ struct pmu_event *te;
+ struct perf_pmu *pmu;
+ LIST_HEAD(aliases);
+ int res = 0;
+ bool use_uncore_table;
+ struct pmu_events_map *map = __test_pmu_get_events_map();
+
+ if (!map)
+ return -1;
+
+ if (is_pmu_core(pmu_name)) {
+ test = &test_cpu_events[0];
+ use_uncore_table = false;
+ } else {
+ test = &test_uncore_events[0];
+ use_uncore_table = true;
+ }
+
+ pmu = zalloc(sizeof(*pmu));
+ if (!pmu)
+ return -1;
+
+ pmu->name = pmu_name;
+
+ pmu_add_cpu_aliases_map(&aliases, pmu, map);
+
+ for (te = &test->event; te->name; test++, te = &test->event) {
+ struct perf_pmu_alias *alias = find_alias(te->name, &aliases);
+
+ if (!alias) {
+ bool uncore_match = pmu_uncore_alias_match(pmu_name,
+ te->pmu);
+
+ if (use_uncore_table && !uncore_match) {
+ pr_debug3("testing aliases PMU %s: skip matching alias %s\n",
+ pmu_name, te->name);
+ continue;
+ }
+
+ pr_debug2("testing aliases PMU %s: no alias, alias_table->name=%s\n",
+ pmu_name, te->name);
+ res = -1;
+ break;
+ }
+
+ if (!is_same(alias->desc, te->desc)) {
+ pr_debug2("testing aliases PMU %s: mismatched desc, %s vs %s\n",
+ pmu_name, alias->desc, te->desc);
+ res = -1;
+ break;
+ }
+
+ if (!is_same(alias->long_desc, test->alias_long_desc)) {
+ pr_debug2("testing aliases PMU %s: mismatched long_desc, %s vs %s\n",
+ pmu_name, alias->long_desc,
+ test->alias_long_desc);
+ res = -1;
+ break;
+ }
+
+ if (!is_same(alias->str, test->alias_str)) {
+ pr_debug2("testing aliases PMU %s: mismatched str, %s vs %s\n",
+ pmu_name, alias->str, test->alias_str);
+ res = -1;
+ break;
+ }
+
+ if (!is_same(alias->topic, te->topic)) {
+ pr_debug2("testing aliases PMU %s: mismatched topic, %s vs %s\n",
+ pmu_name, alias->topic, te->topic);
+ res = -1;
+ break;
+ }
+
+ (*count)++;
+ pr_debug2("testing aliases PMU %s: matched event %s\n",
+ pmu_name, alias->name);
+ }
+
+ free(pmu);
+ return res;
+}
+
int test__pmu_events(struct test *test __maybe_unused,
int subtest __maybe_unused)
{
+ struct perf_pmu *pmu = NULL;
+
if (__test_pmu_event_table())
return -1;

+ while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+ int count = 0;
+
+ if (list_empty(&pmu->format)) {
+ pr_debug2("skipping testing PMU %s\n", pmu->name);
+ continue;
+ }
+
+ if (__test__pmu_event_aliases(pmu->name, &count)) {
+ pr_debug("testing PMU %s aliases: failed\n", pmu->name);
+ return -1;
+ }
+
+ if (count == 0)
+ pr_debug3("testing PMU %s aliases: no events to match\n",
+ pmu->name);
+ else
+ pr_debug("testing PMU %s aliases: pass\n", pmu->name);
+ }
+
return 0;
}
--
2.12.3
Jiri Olsa
2020-03-17 16:20:43 UTC
Permalink
On Tue, Mar 17, 2020 at 07:02:19PM +0800, John Garry wrote:

SNIP
Post by John Garry
struct perf_pmu_test_event {
struct pmu_event event;
+
+ /* extra events for aliases */
+ const char *alias_str;
+
+ /*
+ * Note: For when PublicDescription does not exist in the JSON, we
+ * will have no long_desc in pmu_event.long_desc, but long_desc may
+ * be set in the alias.
+ */
+ const char *alias_long_desc;
};
+
static struct perf_pmu_test_event test_cpu_events[] = {
{
.event = {
@@ -20,6 +31,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L1 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8a",
+ .alias_long_desc = "L1 BTB Correction",
},
{
.event = {
@@ -28,6 +41,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L2 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8b",
+ .alias_long_desc = "L2 BTB Correction",
},
{
.event = {
@@ -36,6 +51,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "Number of segment register loads",
.topic = "other",
},
+ .alias_str = "umask=0x80,(null)=0x30d40,event=0x6",
ah so we are using other pmus because of the format definitions

why is there the '(null)' in there?

jirka
John Garry
2020-03-17 16:41:04 UTC
Permalink
Post by Jiri Olsa
SNIP
Post by John Garry
struct perf_pmu_test_event {
struct pmu_event event;
+
+ /* extra events for aliases */
+ const char *alias_str;
+
+ /*
+ * Note: For when PublicDescription does not exist in the JSON, we
+ * will have no long_desc in pmu_event.long_desc, but long_desc may
+ * be set in the alias.
+ */
+ const char *alias_long_desc;
};
+
static struct perf_pmu_test_event test_cpu_events[] = {
{
.event = {
@@ -20,6 +31,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L1 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8a",
+ .alias_long_desc = "L1 BTB Correction",
},
{
.event = {
@@ -28,6 +41,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L2 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8b",
+ .alias_long_desc = "L2 BTB Correction",
},
{
.event = {
@@ -36,6 +51,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "Number of segment register loads",
.topic = "other",
},
+ .alias_str = "umask=0x80,(null)=0x30d40,event=0x6",
ah so we are using other pmus because of the format definitions
Hi jirka,
Post by Jiri Olsa
why is there the '(null)' in there?
Well this is just coming from the generated alias string in the pmu
code, and it does not seem to be handling "period" argument properly. It
needs to be checked.
Thanks,
John
Jiri Olsa
2020-03-17 17:07:30 UTC
Permalink
Post by John Garry
Post by Jiri Olsa
SNIP
Post by John Garry
struct perf_pmu_test_event {
struct pmu_event event;
+
+ /* extra events for aliases */
+ const char *alias_str;
+
+ /*
+ * Note: For when PublicDescription does not exist in the JSON, we
+ * will have no long_desc in pmu_event.long_desc, but long_desc may
+ * be set in the alias.
+ */
+ const char *alias_long_desc;
};
+
static struct perf_pmu_test_event test_cpu_events[] = {
{
.event = {
@@ -20,6 +31,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L1 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8a",
+ .alias_long_desc = "L1 BTB Correction",
},
{
.event = {
@@ -28,6 +41,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "L2 BTB Correction",
.topic = "branch",
},
+ .alias_str = "event=0x8b",
+ .alias_long_desc = "L2 BTB Correction",
},
{
.event = {
@@ -36,6 +51,8 @@ static struct perf_pmu_test_event test_cpu_events[] = {
.desc = "Number of segment register loads",
.topic = "other",
},
+ .alias_str = "umask=0x80,(null)=0x30d40,event=0x6",
ah so we are using other pmus because of the format definitions
Hi jirka,
Post by Jiri Olsa
why is there the '(null)' in there?
Well this is just coming from the generated alias string in the pmu code,
and it does not seem to be handling "period" argument properly. It needs to
be checked.
nice, it found first issue already ;-)

jirka
John Garry
2020-03-17 11:02:15 UTC
Permalink
Create pmu_add_cpu_aliases_map() from pmu_add_cpu_aliases(), so the caller
can pass the map; the pmu-events test would use this since there would
be no CPUID matching to a mapfile there.

Signed-off-by: John Garry <***@huawei.com>
---
tools/perf/util/pmu.c | 21 +++++++++++++--------
tools/perf/util/pmu.h | 3 +++
2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 8b99fd312aae..c616a06a34a8 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -21,7 +21,6 @@
#include "pmu.h"
#include "parse-events.h"
#include "header.h"
-#include "pmu-events/pmu-events.h"
#include "string2.h"
#include "strbuf.h"
#include "fncache.h"
@@ -744,16 +743,11 @@ static bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
* to the current running CPU. Then, add all PMU events from that table
* as aliases.
*/
-static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
+void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
+ struct pmu_events_map *map)
{
int i;
- struct pmu_events_map *map;
const char *name = pmu->name;
-
- map = perf_pmu__find_map(pmu);
- if (!map)
- return;
-
/*
* Found a matching PMU events table. Create aliases
*/
@@ -788,6 +782,17 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
}
}

+static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
+{
+ struct pmu_events_map *map;
+
+ map = perf_pmu__find_map(pmu);
+ if (!map)
+ return;
+
+ pmu_add_cpu_aliases_map(head, pmu, map);
+}
+
struct perf_event_attr * __weak
perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
{
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6737e3d5d568..0b4a0efae38e 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -7,6 +7,7 @@
#include <linux/perf_event.h>
#include <stdbool.h>
#include "parse-events.h"
+#include "pmu-events/pmu-events.h"

struct perf_evsel_config_term;

@@ -97,6 +98,8 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
int perf_pmu__test(void);

struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
+void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
+ struct pmu_events_map *map);

struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu);
--
2.12.3
Jiri Olsa
2020-03-17 16:20:52 UTC
Permalink
Post by John Garry
With the goal of supporting pmu-events test case, introduce support for a
test events folder.
These test events can be used for testing generation of pmu-event tables
and alias creation for any arch.
When running the pmu-events test case, these test events will be used
as the platform-agnostic events, so aliases can be created per-PMU and
validated against known expected values.
To support the test events, add a "testcpu" entry in pmu_events_map[].
The pmu-events test will be able to lookup the events map for "testcpu",
to verify the generated tables against expected values.
can't compile this one:

HOSTCC pmu-events/jevents.o
pmu-events/jevents.c: In function ‘main’:
pmu-events/jevents.c:1195:3: error: ‘ret’ undeclared (first use in this function)
1195 | ret = 1;
| ^~~
pmu-events/jevents.c:1195:3: note: each undeclared identifier is reported only once for each function it appears in
pmu-events/jevents.c:1196:3: error: label ‘out_free_mapfile’ used but not defined
1196 | goto out_free_mapfile;
| ^~~~
mv: cannot stat 'pmu-events/.jevents.o.tmp': No such file or directory
make[3]: *** [/home/jolsa/kernel/linux-perf/tools/build/Makefile.build:97: pmu-events/jevents.o] Error 1
make[2]: *** [Makefile.perf:619: pmu-events/jevents-in.o] Error 2
make[1]: *** [Makefile.perf:225: sub-make] Error 2
make: *** [Makefile:70: all] Error 2


jirka
John Garry
2020-03-17 16:25:32 UTC
Permalink
Post by Jiri Olsa
Post by John Garry
With the goal of supporting pmu-events test case, introduce support for a
test events folder.
These test events can be used for testing generation of pmu-event tables
and alias creation for any arch.
When running the pmu-events test case, these test events will be used
as the platform-agnostic events, so aliases can be created per-PMU and
validated against known expected values.
To support the test events, add a "testcpu" entry in pmu_events_map[].
The pmu-events test will be able to lookup the events map for "testcpu",
to verify the generated tables against expected values.
HOSTCC pmu-events/jevents.o
pmu-events/jevents.c:1195:3: error: ‘ret’ undeclared (first use in this function)
1195 | ret = 1;
| ^~~
pmu-events/jevents.c:1195:3: note: each undeclared identifier is reported only once for each function it appears in
pmu-events/jevents.c:1196:3: error: label ‘out_free_mapfile’ used but not defined
1196 | goto out_free_mapfile;
| ^~~~
mv: cannot stat 'pmu-events/.jevents.o.tmp': No such file or directory
make[3]: *** [/home/jolsa/kernel/linux-perf/tools/build/Makefile.build:97: pmu-events/jevents.o] Error 1
make[2]: *** [Makefile.perf:619: pmu-events/jevents-in.o] Error 2
make[1]: *** [Makefile.perf:225: sub-make] Error 2
make: *** [Makefile:70: all] Error 2
Hi jirka,

What baseline are you using? I used v5.6-rc6. The patches are here:

https://github.com/hisilicon/kernel-dev/commits/private-topic-perf-5.6-pmu-events-test-upstream-v2

thanks,
John
Jiri Olsa
2020-03-17 17:06:45 UTC
Permalink
Post by John Garry
Post by Jiri Olsa
Post by John Garry
With the goal of supporting pmu-events test case, introduce support for a
test events folder.
These test events can be used for testing generation of pmu-event tables
and alias creation for any arch.
When running the pmu-events test case, these test events will be used
as the platform-agnostic events, so aliases can be created per-PMU and
validated against known expected values.
To support the test events, add a "testcpu" entry in pmu_events_map[].
The pmu-events test will be able to lookup the events map for "testcpu",
to verify the generated tables against expected values.
HOSTCC pmu-events/jevents.o
pmu-events/jevents.c:1195:3: error: ‘ret’ undeclared (first use in this function)
1195 | ret = 1;
| ^~~
pmu-events/jevents.c:1195:3: note: each undeclared identifier is reported only once for each function it appears in
pmu-events/jevents.c:1196:3: error: label ‘out_free_mapfile’ used but not defined
1196 | goto out_free_mapfile;
| ^~~~
mv: cannot stat 'pmu-events/.jevents.o.tmp': No such file or directory
make[3]: *** [/home/jolsa/kernel/linux-perf/tools/build/Makefile.build:97: pmu-events/jevents.o] Error 1
make[2]: *** [Makefile.perf:619: pmu-events/jevents-in.o] Error 2
make[1]: *** [Makefile.perf:225: sub-make] Error 2
make: *** [Makefile:70: all] Error 2
Hi jirka,
I applied your patches on Arnaldo's perf/core
Post by John Garry
https://github.com/hisilicon/kernel-dev/commits/private-topic-perf-5.6-pmu-events-test-upstream-v2
ok, will check

jirka
John Garry
2020-03-17 17:42:46 UTC
Permalink
Post by Jiri Olsa
Post by John Garry
Post by Jiri Olsa
Post by John Garry
With the goal of supporting pmu-events test case, introduce support for a
test events folder.
These test events can be used for testing generation of pmu-event tables
and alias creation for any arch.
When running the pmu-events test case, these test events will be used
as the platform-agnostic events, so aliases can be created per-PMU and
validated against known expected values.
To support the test events, add a "testcpu" entry in pmu_events_map[].
The pmu-events test will be able to lookup the events map for "testcpu",
to verify the generated tables against expected values.
HOSTCC pmu-events/jevents.o
pmu-events/jevents.c:1195:3: error: ‘ret’ undeclared (first use in this function)
1195 | ret = 1;
| ^~~
pmu-events/jevents.c:1195:3: note: each undeclared identifier is reported only once for each function it appears in
pmu-events/jevents.c:1196:3: error: label ‘out_free_mapfile’ used but not defined
1196 | goto out_free_mapfile;
| ^~~~
mv: cannot stat 'pmu-events/.jevents.o.tmp': No such file or directory
make[3]: *** [/home/jolsa/kernel/linux-perf/tools/build/Makefile.build:97: pmu-events/jevents.o] Error 1
make[2]: *** [Makefile.perf:619: pmu-events/jevents-in.o] Error 2
make[1]: *** [Makefile.perf:225: sub-make] Error 2
make: *** [Makefile:70: all] Error 2
Hi jirka,
I applied your patches on Arnaldo's perf/core
My recent fix on jevents.c does not seem to be on that branch, but it is
on perf/urgent and also included in v5.6-rc6

Thanks,
John
Post by Jiri Olsa
Post by John Garry
https://github.com/hisilicon/kernel-dev/commits/private-topic-perf-5.6-pmu-events-test-upstream-v2
ok, will check
jirka
.
Arnaldo Carvalho de Melo
2020-03-17 20:41:15 UTC
Permalink
Post by Jiri Olsa
Post by John Garry
Post by Jiri Olsa
Post by John Garry
With the goal of supporting pmu-events test case, introduce support for a
test events folder.
These test events can be used for testing generation of pmu-event tables
and alias creation for any arch.
When running the pmu-events test case, these test events will be used
as the platform-agnostic events, so aliases can be created per-PMU and
validated against known expected values.
To support the test events, add a "testcpu" entry in pmu_events_map[].
The pmu-events test will be able to lookup the events map for "testcpu",
to verify the generated tables against expected values.
HOSTCC pmu-events/jevents.o
pmu-events/jevents.c:1195:3: error: ‘ret’ undeclared (first use in this function)
1195 | ret = 1;
| ^~~
pmu-events/jevents.c:1195:3: note: each undeclared identifier is reported only once for each function it appears in
pmu-events/jevents.c:1196:3: error: label ‘out_free_mapfile’ used but not defined
1196 | goto out_free_mapfile;
| ^~~~
mv: cannot stat 'pmu-events/.jevents.o.tmp': No such file or directory
make[3]: *** [/home/jolsa/kernel/linux-perf/tools/build/Makefile.build:97: pmu-events/jevents.o] Error 1
make[2]: *** [Makefile.perf:619: pmu-events/jevents-in.o] Error 2
make[1]: *** [Makefile.perf:225: sub-make] Error 2
make: *** [Makefile:70: all] Error 2
Hi jirka,
I applied your patches on Arnaldo's perf/core
My recent fix on jevents.c does not seem to be on that branch, but it is on
perf/urgent and also included in v5.6-rc6
I'll merge perf/urgent into perf/core soon,

- Arnaldo
Thanks,
John
Post by Jiri Olsa
Post by John Garry
https://github.com/hisilicon/kernel-dev/commits/private-topic-perf-5.6-pmu-events-test-upstream-v2
ok, will check
jirka
.
--
- Arnaldo
Loading...