linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/18] Lazily load PMU data
@ 2023-08-24  4:13 Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 01/18] perf pmu: Make the loading of formats lazy Ian Rogers
                   ` (18 more replies)
  0 siblings, 19 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Lazily load PMU data both from sysfs and json files. Reorganize
json data to be more PMU oriented to facilitate this, for
example, json data is now sorted into arrays for their PMU.

In refactoring the code some changes were made to get rid of maximum
encoding sizes for events (256 bytes), with input files being directly
passed to the lex generated code. There is also a small event parse
error message improvement.

Some results from an Intel tigerlake laptop running Debian:

Binary size reduction of 5.3% or 552,864 bytes because the PMU
name no longer appears in the string or desc field.

stat -e cpu/cycles/ minor faults reduced from 1733 to 1667, open calls reduced
from 171 to 94.

stat default minor faults reduced from 1805 to 1717, open calls reduced
from 654 to 343.

Average PMU scanning reduced from 4720.641usec to 2927.293usec.
Average core PMU scanning reduced from 1004.658usec to 232.668usec
(4.3x faster).

v2: Add error path for failing strdup when allocating a format,
    suggested by Arnaldo. Rebased on top of tmp.perf-tools-next
    removing 8 patches. Added "perf jevents: Don't append Unit to
    desc" to save yet more encoding json event space.

Ian Rogers (18):
  perf pmu: Make the loading of formats lazy
  perf pmu: Abstract alias/event struct
  perf pmu-events: Add extra underscore to function names
  perf jevents: Group events by PMU
  perf parse-events: Improve error message for double setting
  perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  perf pmu-events: Reduce processed events by passing PMU
  perf pmu-events: Add pmu_events_table__find_event
  perf pmu: Parse sysfs events directly from a file
  perf pmu: Prefer passing pmu to aliases list
  perf pmu: Merge json events with sysfs at load time
  perf pmu: Cache json events table
  perf pmu: Lazily add json events
  perf pmu: Scan type early to fail an invalid PMU quickly
  perf pmu: Be lazy about loading event info files from sysfs
  perf pmu: Lazily load sysfs aliases
  perf jevents: Sort strings in the big C string to reduce faults
  perf jevents: Don't append Unit to desc

 tools/perf/arch/x86/util/intel-pt.c      |   2 +-
 tools/perf/bench/pmu-scan.c              |   8 +-
 tools/perf/builtin-list.c                |  13 +-
 tools/perf/pmu-events/empty-pmu-events.c |  49 +-
 tools/perf/pmu-events/jevents.py         | 312 +++++++--
 tools/perf/pmu-events/pmu-events.h       |  15 +-
 tools/perf/tests/parse-events.c          |   2 +-
 tools/perf/tests/pmu-events.c            | 148 +++--
 tools/perf/tests/pmu.c                   |   2 +-
 tools/perf/util/metricgroup.c            |  10 +-
 tools/perf/util/parse-events.c           |  87 ++-
 tools/perf/util/parse-events.h           |   3 +-
 tools/perf/util/pmu.c                    | 806 +++++++++++++++--------
 tools/perf/util/pmu.h                    |  96 ++-
 tools/perf/util/pmu.y                    |  20 +-
 tools/perf/util/pmus.c                   | 230 +++----
 tools/perf/util/s390-sample-raw.c        |  50 +-
 17 files changed, 1141 insertions(+), 712 deletions(-)

-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v2 01/18] perf pmu: Make the loading of formats lazy
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 02/18] perf pmu: Abstract alias/event struct Ian Rogers
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

The sysfs format files are loaded eagerly in a PMU. Add a flag so that
we create the format but only load the contents when necessary.

Reduce the size of the value in struct perf_pmu_format and avoid holes
so there is no additional space requirement.

For "perf stat -e cycles true" this reduces the number of openat calls
from 648 to 573 (about 12%). The benchmark pmu scan speed is improved
by roughly 5%.

Before: $ perf bench internals pmu-scan
Computing performance of sysfs PMU event scan for 100 times
  Average core PMU scanning took: 1061.100 usec (+- 9.965 usec)
  Average PMU scanning took: 4725.300 usec (+- 260.599 usec)

After: $ perf bench internals pmu-scan
Computing performance of sysfs PMU event scan for 100 times
  Average core PMU scanning took: 989.170 usec (+- 6.873 usec)
  Average PMU scanning took: 4520.960 usec (+- 251.272 usec)

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/tests/pmu.c |   2 +-
 tools/perf/util/pmu.c  | 144 +++++++++++++++++++++++++++--------------
 tools/perf/util/pmu.h  |   5 +-
 tools/perf/util/pmu.y  |  20 ++----
 4 files changed, 106 insertions(+), 65 deletions(-)

diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 2c1c349a42e2..c204ed1f1a8b 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -171,7 +171,7 @@ static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe
 	}
 
 	pmu->name = strdup("perf-pmu-test");
-	ret = perf_pmu__format_parse(pmu, fd);
+	ret = perf_pmu__format_parse(pmu, fd, /*eager_load=*/true);
 	if (ret)
 		goto out;
 
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 42f3249994ab..3cfd3e58da23 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -40,6 +40,10 @@ struct perf_pmu perf_pmu__fake;
  * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set.
  */
 struct perf_pmu_format {
+	/** @list: Element on list within struct perf_pmu. */
+	struct list_head list;
+	/** @bits: Which config bits are set by this format value. */
+	DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
 	/** @name: The modifier/file name. */
 	char *name;
 	/**
@@ -47,18 +51,79 @@ struct perf_pmu_format {
 	 * are from PERF_PMU_FORMAT_VALUE_CONFIG to
 	 * PERF_PMU_FORMAT_VALUE_CONFIG_END.
 	 */
-	int value;
-	/** @bits: Which config bits are set by this format value. */
-	DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
-	/** @list: Element on list within struct perf_pmu. */
-	struct list_head list;
+	u16 value;
+	/** @loaded: Has the contents been loaded/parsed. */
+	bool loaded;
 };
 
+static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name)
+{
+	struct perf_pmu_format *format;
+
+	format = zalloc(sizeof(*format));
+	if (!format)
+		return NULL;
+
+	format->name = strdup(name);
+	if (!format->name) {
+		free(format);
+		return NULL;
+	}
+	list_add_tail(&format->list, list);
+	return format;
+}
+
+/* Called at the end of parsing a format. */
+void perf_pmu_format__set_value(void *vformat, int config, unsigned long *bits)
+{
+	struct perf_pmu_format *format = vformat;
+
+	format->value = config;
+	memcpy(format->bits, bits, sizeof(format->bits));
+}
+
+static void __perf_pmu_format__load(struct perf_pmu_format *format, FILE *file)
+{
+	void *scanner;
+	int ret;
+
+	ret = perf_pmu_lex_init(&scanner);
+	if (ret)
+		return;
+
+	perf_pmu_set_in(file, scanner);
+	ret = perf_pmu_parse(format, scanner);
+	perf_pmu_lex_destroy(scanner);
+	format->loaded = true;
+}
+
+static void perf_pmu_format__load(struct perf_pmu *pmu, struct perf_pmu_format *format)
+{
+	char path[PATH_MAX];
+	FILE *file = NULL;
+
+	if (format->loaded)
+		return;
+
+	if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, "format"))
+		return;
+
+	assert(strlen(path) + strlen(format->name) + 2 < sizeof(path));
+	strcat(path, "/");
+	strcat(path, format->name);
+
+	file = fopen(path, "r");
+	if (!file)
+		return;
+	__perf_pmu_format__load(format, file);
+	fclose(file);
+}
+
 /*
  * Parse & process all the sysfs attributes located under
  * the directory specified in 'dir' parameter.
  */
-int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd)
+int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load)
 {
 	struct dirent *evt_ent;
 	DIR *format_dir;
@@ -68,37 +133,35 @@ int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd)
 	if (!format_dir)
 		return -EINVAL;
 
-	while (!ret && (evt_ent = readdir(format_dir))) {
+	while ((evt_ent = readdir(format_dir)) != NULL) {
+		struct perf_pmu_format *format;
 		char *name = evt_ent->d_name;
-		int fd;
-		void *scanner;
-		FILE *file;
 
 		if (!strcmp(name, ".") || !strcmp(name, ".."))
 			continue;
 
-
-		ret = -EINVAL;
-		fd = openat(dirfd, name, O_RDONLY);
-		if (fd < 0)
-			break;
-
-		file = fdopen(fd, "r");
-		if (!file) {
-			close(fd);
+		format = perf_pmu__new_format(&pmu->format, name);
+		if (!format) {
+			ret = -ENOMEM;
 			break;
 		}
 
-		ret = perf_pmu_lex_init(&scanner);
-		if (ret) {
+		if (eager_load) {
+			FILE *file;
+			int fd = openat(dirfd, name, O_RDONLY);
+
+			if (fd < 0) {
+				ret = -errno;
+				break;
+			}
+			file = fdopen(fd, "r");
+			if (!file) {
+				close(fd);
+				break;
+			}
+			__perf_pmu_format__load(format, file);
 			fclose(file);
-			break;
 		}
-
-		perf_pmu_set_in(file, scanner);
-		ret = perf_pmu_parse(&pmu->format, name, scanner);
-		perf_pmu_lex_destroy(scanner);
-		fclose(file);
 	}
 
 	closedir(format_dir);
@@ -119,7 +182,7 @@ static int pmu_format(struct perf_pmu *pmu, int dirfd, const char *name)
 		return 0;
 
 	/* it'll close the fd */
-	if (perf_pmu__format_parse(pmu, fd))
+	if (perf_pmu__format_parse(pmu, fd, /*eager_load=*/false))
 		return -1;
 
 	return 0;
@@ -962,13 +1025,15 @@ void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu)
 	if (pmu == &perf_pmu__fake)
 		return;
 
-	list_for_each_entry(format, &pmu->format, list)
+	list_for_each_entry(format, &pmu->format, list) {
+		perf_pmu_format__load(pmu, format);
 		if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) {
 			pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'"
 				   "which is not supported by this version of perf!\n",
 				   pmu->name, format->name, format->value);
 			return;
 		}
+	}
 }
 
 bool evsel__is_aux_event(const struct evsel *evsel)
@@ -1041,6 +1106,7 @@ int perf_pmu__format_type(struct perf_pmu *pmu, const char *name)
 	if (!format)
 		return -1;
 
+	perf_pmu_format__load(pmu, format);
 	return format->value;
 }
 
@@ -1177,7 +1243,7 @@ static int pmu_config_term(struct perf_pmu *pmu,
 		free(pmu_term);
 		return -EINVAL;
 	}
-
+	perf_pmu_format__load(pmu, format);
 	switch (format->value) {
 	case PERF_PMU_FORMAT_VALUE_CONFIG:
 		vp = &attr->config;
@@ -1403,24 +1469,6 @@ struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, const char *ev
 
 	return NULL;
 }
-
-int perf_pmu__new_format(struct list_head *list, char *name,
-			 int config, unsigned long *bits)
-{
-	struct perf_pmu_format *format;
-
-	format = zalloc(sizeof(*format));
-	if (!format)
-		return -ENOMEM;
-
-	format->name = strdup(name);
-	format->value = config;
-	memcpy(format->bits, bits, sizeof(format->bits));
-
-	list_add_tail(&format->list, list);
-	return 0;
-}
-
 static void perf_pmu__del_formats(struct list_head *formats)
 {
 	struct perf_pmu_format *fmt, *tmp;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index c4268053c979..675c9b97f7bf 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -227,9 +227,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
 			  struct perf_pmu_info *info);
 struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, const char *event);
 
-int perf_pmu__new_format(struct list_head *list, char *name,
-			 int config, unsigned long *bits);
-int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd);
+int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load);
+void perf_pmu_format__set_value(void *format, int config, unsigned long *bits);
 bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
 
 bool is_pmu_core(const char *name);
diff --git a/tools/perf/util/pmu.y b/tools/perf/util/pmu.y
index d861a5bfa3bd..600c8c158c8e 100644
--- a/tools/perf/util/pmu.y
+++ b/tools/perf/util/pmu.y
@@ -1,6 +1,5 @@
 %define api.pure full
-%parse-param {struct list_head *format}
-%parse-param {char *name}
+%parse-param {void *format}
 %parse-param {void *scanner}
 %lex-param {void* scanner}
 
@@ -21,7 +20,7 @@ do { \
                 YYABORT; \
 } while (0)
 
-static void perf_pmu_error(struct list_head *list, char *name, void *scanner, char const *msg);
+static void perf_pmu_error(void *format, void *scanner, const char *msg);
 
 static void perf_pmu__set_format(unsigned long *bits, long from, long to)
 {
@@ -59,16 +58,12 @@ format_term
 format_term:
 PP_CONFIG ':' bits
 {
-	ABORT_ON(perf_pmu__new_format(format, name,
-				      PERF_PMU_FORMAT_VALUE_CONFIG,
-				      $3));
+	perf_pmu_format__set_value(format, PERF_PMU_FORMAT_VALUE_CONFIG, $3);
 }
 |
 PP_CONFIG PP_VALUE ':' bits
 {
-	ABORT_ON(perf_pmu__new_format(format, name,
-				      $2,
-				      $4));
+	perf_pmu_format__set_value(format, $2, $4);
 }
 
 bits:
@@ -95,9 +90,8 @@ PP_VALUE
 
 %%
 
-static void perf_pmu_error(struct list_head *list __maybe_unused,
-		    char *name __maybe_unused,
-		    void *scanner __maybe_unused,
-		    char const *msg __maybe_unused)
+static void perf_pmu_error(void *format __maybe_unused,
+			   void *scanner __maybe_unused,
+			   const char *msg __maybe_unused)
 {
 }
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 02/18] perf pmu: Abstract alias/event struct
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 01/18] perf pmu: Make the loading of formats lazy Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 03/18] perf pmu-events: Add extra underscore to function names Ian Rogers
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

In order to be able to lazily compute aliases/events for a PMU, move
the struct perf_pmu_alias into pmu.c. Add perf_pmu__find_event and
perf_pmu__for_each_event that take a callback that is called for the
found event or for each event. The layout of struct pmu and the
event/alias list is unchanged but the API is altered so that aliases
are no longer directly accessed, allowing for later changes.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/bench/pmu-scan.c    |   8 +-
 tools/perf/tests/pmu-events.c  | 101 +++++++--------
 tools/perf/util/parse-events.c |  67 ++++------
 tools/perf/util/pmu.c          | 212 +++++++++++++++++++++++++++---
 tools/perf/util/pmu.h          |  71 +++-------
 tools/perf/util/pmus.c         | 230 +++++++++++----------------------
 6 files changed, 366 insertions(+), 323 deletions(-)

diff --git a/tools/perf/bench/pmu-scan.c b/tools/perf/bench/pmu-scan.c
index c7d207f8e13c..9e4d36486f62 100644
--- a/tools/perf/bench/pmu-scan.c
+++ b/tools/perf/bench/pmu-scan.c
@@ -57,9 +57,7 @@ static int save_result(void)
 		r->is_core = pmu->is_core;
 		r->nr_caps = pmu->nr_caps;
 
-		r->nr_aliases = 0;
-		list_for_each(list, &pmu->aliases)
-			r->nr_aliases++;
+		r->nr_aliases = perf_pmu__num_events(pmu);
 
 		r->nr_formats = 0;
 		list_for_each(list, &pmu->format)
@@ -98,9 +96,7 @@ static int check_result(bool core_only)
 			return -1;
 		}
 
-		nr = 0;
-		list_for_each(list, &pmu->aliases)
-			nr++;
+		nr = perf_pmu__num_events(pmu);
 		if (nr != r->nr_aliases) {
 			pr_err("Unmatched number of event aliases in %s: expect %d vs got %d\n",
 				pmu->name, r->nr_aliases, nr);
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 05d6e6e21c6f..dc87e66fb118 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -341,7 +341,7 @@ static int compare_pmu_events(const struct pmu_event *e1, const struct pmu_event
 	return 0;
 }
 
-static int compare_alias_to_test_event(struct perf_pmu_alias *alias,
+static int compare_alias_to_test_event(struct pmu_event_info *alias,
 				struct perf_pmu_test_event const *test_event,
 				char const *pmu_name)
 {
@@ -496,6 +496,23 @@ static int test__pmu_event_table(struct test_suite *test __maybe_unused,
 	return 0;
 }
 
+struct test_core_pmu_event_aliases_cb_args {
+	struct perf_pmu_test_event const *test_event;
+	int *count;
+};
+
+static int test_core_pmu_event_aliases_cb(void *state, struct pmu_event_info *alias)
+{
+	struct test_core_pmu_event_aliases_cb_args *args = state;
+
+	if (compare_alias_to_test_event(alias, args->test_event, alias->pmu->name))
+		return -1;
+	(*args->count)++;
+	pr_debug2("testing aliases core PMU %s: matched event %s\n",
+		alias->pmu_name, alias->name);
+	return 0;
+}
+
 /* Verify aliases are as expected */
 static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
 {
@@ -522,25 +539,19 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
 	pmu_add_cpu_aliases_table(pmu, table);
 
 	for (; *test_event_table; test_event_table++) {
-		struct perf_pmu_test_event const *test_event = *test_event_table;
-		struct pmu_event const *event = &test_event->event;
-		struct perf_pmu_alias *alias = perf_pmu__find_alias(pmu, event->name);
-
-		if (!alias) {
-			pr_debug("testing aliases core PMU %s: no alias, alias_table->name=%s\n",
-				  pmu_name, event->name);
-			res = -1;
-			break;
-		}
-
-		if (compare_alias_to_test_event(alias, test_event, pmu_name)) {
-			res = -1;
-			break;
-		}
-
-		(*count)++;
-		pr_debug2("testing aliases core PMU %s: matched event %s\n",
-			  pmu_name, alias->name);
+		struct perf_pmu_test_event test_event = **test_event_table;
+		struct pmu_event const *event = &test_event.event;
+		struct test_core_pmu_event_aliases_cb_args args = {
+			.test_event = &test_event,
+			.count = count,
+		};
+		int err;
+
+		test_event.event.pmu = pmu_name;
+		err = perf_pmu__find_event(pmu, event->name, &args,
+					   test_core_pmu_event_aliases_cb);
+		if (err)
+			res = err;
 	}
 	perf_pmu__delete(pmu);
 
@@ -553,7 +564,6 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 	struct perf_pmu_test_event const **table;
 	struct perf_pmu *pmu = &test_pmu->pmu;
 	const char *pmu_name = pmu->name;
-	struct perf_pmu_alias *a, *tmp, *alias;
 	const struct pmu_events_table *events_table;
 	int res = 0;
 
@@ -564,8 +574,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 	pmu_add_sys_aliases(pmu);
 
 	/* Count how many aliases we generated */
-	list_for_each_entry(alias, &pmu->aliases, list)
-		alias_count++;
+	alias_count = perf_pmu__num_events(pmu);
 
 	/* Count how many aliases we expect from the known table */
 	for (table = &test_pmu->aliases[0]; *table; table++)
@@ -574,33 +583,25 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 	if (alias_count != to_match_count) {
 		pr_debug("testing aliases uncore PMU %s: mismatch expected aliases (%d) vs found (%d)\n",
 			 pmu_name, to_match_count, alias_count);
-		res = -1;
-		goto out;
+		return -1;
 	}
 
-	list_for_each_entry(alias, &pmu->aliases, list) {
-		bool matched = false;
-
-		for (table = &test_pmu->aliases[0]; *table; table++) {
-			struct perf_pmu_test_event const *test_event = *table;
-			struct pmu_event const *event = &test_event->event;
-
-			if (!strcmp(event->name, alias->name)) {
-				if (compare_alias_to_test_event(alias,
-							test_event,
-							pmu_name)) {
-					continue;
-				}
-				matched = true;
-				matched_count++;
-			}
-		}
-
-		if (matched == false) {
+	for (table = &test_pmu->aliases[0]; *table; table++) {
+		struct perf_pmu_test_event test_event = **table;
+		struct pmu_event const *event = &test_event.event;
+		int err;
+		struct test_core_pmu_event_aliases_cb_args args = {
+			.test_event = &test_event,
+			.count = &matched_count,
+		};
+
+		err = perf_pmu__find_event(pmu, event->name, &args,
+					   test_core_pmu_event_aliases_cb);
+		if (err) {
+			res = err;
 			pr_debug("testing aliases uncore PMU %s: could not match alias %s\n",
-				 pmu_name, alias->name);
-			res = -1;
-			goto out;
+				 pmu_name, event->name);
+			return -1;
 		}
 	}
 
@@ -609,12 +610,6 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 			 pmu_name, matched_count, alias_count);
 		res = -1;
 	}
-
-out:
-	list_for_each_entry_safe(a, tmp, &pmu->aliases, list) {
-		list_del(&a->list);
-		perf_pmu_free_alias(a);
-	}
 	return res;
 }
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7d9d687d9191..7cad82a9f578 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -193,38 +193,31 @@ static void fix_raw(struct list_head *config_terms, struct perf_pmu *pmu)
 	struct parse_events_term *term;
 
 	list_for_each_entry(term, config_terms, list) {
-		struct perf_pmu_alias *alias;
-		bool matched = false;
+		u64 num;
 
 		if (term->type_term != PARSE_EVENTS__TERM_TYPE_RAW)
 			continue;
 
-		list_for_each_entry(alias, &pmu->aliases, list) {
-			if (!strcmp(alias->name, term->val.str)) {
-				free(term->config);
-				term->config = term->val.str;
-				term->type_val = PARSE_EVENTS__TERM_TYPE_NUM;
-				term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
-				term->val.num = 1;
-				term->no_value = true;
-				matched = true;
-				break;
-			}
-		}
-		if (!matched) {
-			u64 num;
-
+		if (perf_pmu__have_event(pmu, term->val.str)) {
 			free(term->config);
-			term->config = strdup("config");
-			errno = 0;
-			num = strtoull(term->val.str + 1, NULL, 16);
-			assert(errno == 0);
-			free(term->val.str);
+			term->config = term->val.str;
 			term->type_val = PARSE_EVENTS__TERM_TYPE_NUM;
-			term->type_term = PARSE_EVENTS__TERM_TYPE_CONFIG;
-			term->val.num = num;
-			term->no_value = false;
+			term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
+			term->val.num = 1;
+			term->no_value = true;
+			continue;
 		}
+
+		free(term->config);
+		term->config = strdup("config");
+		errno = 0;
+		num = strtoull(term->val.str + 1, NULL, 16);
+		assert(errno == 0);
+		free(term->val.str);
+		term->type_val = PARSE_EVENTS__TERM_TYPE_NUM;
+		term->type_term = PARSE_EVENTS__TERM_TYPE_CONFIG;
+		term->val.num = num;
+		term->no_value = false;
 	}
 }
 
@@ -1458,28 +1451,22 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
 	INIT_LIST_HEAD(list);
 
 	while ((pmu = perf_pmus__scan(pmu)) != NULL) {
-		struct perf_pmu_alias *alias;
 		bool auto_merge_stats;
 
 		if (parse_events__filter_pmu(parse_state, pmu))
 			continue;
 
-		auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
+		if (!perf_pmu__have_event(pmu, str))
+			continue;
 
-		list_for_each_entry(alias, &pmu->aliases, list) {
-			if (!strcasecmp(alias->name, str)) {
-				parse_events_copy_term_list(head, &orig_head);
-				if (!parse_events_add_pmu(parse_state, list,
-							  pmu->name, orig_head,
-							  auto_merge_stats, loc)) {
-					pr_debug("%s -> %s/%s/\n", str,
-						 pmu->name, alias->str);
-					parse_state->wild_card_pmus = true;
-					ok++;
-				}
-				parse_events_terms__delete(orig_head);
-			}
+		auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
+		parse_events_copy_term_list(head, &orig_head);
+		if (!parse_events_add_pmu(parse_state, list, pmu->name,
+					  orig_head, auto_merge_stats, loc)) {
+			pr_debug("%s -> %s/%s/\n", str, pmu->name, str);
+			ok++;
 		}
+		parse_events_terms__delete(orig_head);
 	}
 
 	if (parse_state->fake_pmu) {
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 3cfd3e58da23..268aaebfa70c 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -31,6 +31,61 @@
 
 struct perf_pmu perf_pmu__fake;
 
+#define UNIT_MAX_LEN	31 /* max length for event unit name */
+
+/**
+ * struct perf_pmu_alias - An event either read from sysfs or builtin in
+ * pmu-events.c, created by parsing the pmu-events json files.
+ */
+struct perf_pmu_alias {
+	/** @name: Name of the event like "mem-loads". */
+	char *name;
+	/** @desc: Optional short description of the event. */
+	char *desc;
+	/** @long_desc: Optional long description. */
+	char *long_desc;
+	/**
+	 * @topic: Optional topic such as cache or pipeline, particularly for
+	 * json events.
+	 */
+	char *topic;
+	/**
+	 * @str: Comma separated parameter list like
+	 * "event=0xcd,umask=0x1,ldlat=0x3".
+	 */
+	char *str;
+	/** @terms: Owned list of the original parsed parameters. */
+	struct list_head terms;
+	/** @list: List element of struct perf_pmu aliases. */
+	struct list_head list;
+	/** @unit: Units for the event, such as bytes or cache lines. */
+	char unit[UNIT_MAX_LEN+1];
+	/** @scale: Value to scale read counter values by. */
+	double scale;
+	/**
+	 * @per_pkg: Does the file
+	 * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.per-pkg or
+	 * equivalent json value exist and have the value 1.
+	 */
+	bool per_pkg;
+	/**
+	 * @snapshot: Does the file
+	 * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.snapshot
+	 * exist and have the value 1.
+	 */
+	bool snapshot;
+	/**
+	 * @deprecated: Is the event hidden and so not shown in perf list by
+	 * default.
+	 */
+	bool deprecated;
+	/**
+	 * @pmu_name: The name copied from the json struct pmu_event. This can
+	 * differ from the PMU name as it won't have suffixes.
+	 */
+	char *pmu_name;
+};
+
 /**
  * struct perf_pmu_format - Values from a format file read from
  * <sysfs>/devices/cpu/format/ held in struct perf_pmu.
@@ -355,7 +410,7 @@ static void perf_pmu_update_alias(struct perf_pmu_alias *old,
 }
 
 /* Delete an alias entry. */
-void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
+static void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
 {
 	zfree(&newalias->name);
 	zfree(&newalias->desc);
@@ -1349,10 +1404,20 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 	return perf_pmu__config_terms(pmu, attr, head_terms, zero, err);
 }
 
+static struct perf_pmu_alias *perf_pmu__find_alias(const struct perf_pmu *pmu, const char *str)
+{
+	struct perf_pmu_alias *alias;
+
+	list_for_each_entry(alias, &pmu->aliases, list) {
+		if (!strcasecmp(alias->name, str))
+			return alias;
+	}
+	return NULL;
+}
+
 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 					     struct parse_events_term *term)
 {
-	struct perf_pmu_alias *alias;
 	char *name;
 
 	if (parse_events__is_hardcoded_term(term))
@@ -1364,6 +1429,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 		if (pmu_find_format(&pmu->format, term->config))
 			return NULL;
 		name = term->config;
+
 	} else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
 		if (strcasecmp(term->config, "event"))
 			return NULL;
@@ -1372,11 +1438,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 		return NULL;
 	}
 
-	list_for_each_entry(alias, &pmu->aliases, list) {
-		if (!strcasecmp(alias->name, name))
-			return alias;
-	}
-	return NULL;
+	return perf_pmu__find_alias(pmu, name);
 }
 
 
@@ -1459,16 +1521,33 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
 	return 0;
 }
 
-struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, const char *event)
+struct find_event_args {
+	const char *event;
+	void *state;
+	pmu_event_callback cb;
+};
+
+static int find_event_callback(void *state, struct pmu_event_info *info)
 {
-	struct perf_pmu_alias *alias;
+	struct find_event_args *args = state;
 
-	list_for_each_entry(alias, &pmu->aliases, list)
-		if (!strcmp(event, alias->name))
-			return alias;
+	if (!strcmp(args->event, info->name))
+		return args->cb(args->state, info);
 
-	return NULL;
+	return 0;
 }
+
+int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb)
+{
+	struct find_event_args args = {
+		.event = event,
+		.state = state,
+		.cb = cb,
+	};
+
+	return perf_pmu__for_each_event(pmu, &args, find_event_callback);
+}
+
 static void perf_pmu__del_formats(struct list_head *formats)
 {
 	struct perf_pmu_format *fmt, *tmp;
@@ -1508,13 +1587,110 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu)
 
 bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name)
 {
-	struct perf_pmu_alias *alias;
+	return perf_pmu__find_alias(pmu, name) != NULL;
+}
 
-	list_for_each_entry(alias, &pmu->aliases, list) {
-		if (!strcmp(alias->name, name))
-			return true;
+size_t perf_pmu__num_events(const struct perf_pmu *pmu)
+{
+	struct list_head *list;
+	size_t nr = 0;
+
+	list_for_each(list, &pmu->aliases)
+		nr++;
+
+	return pmu->selectable ? nr + 1 : nr;
+}
+
+static int sub_non_neg(int a, int b)
+{
+	if (b > a)
+		return 0;
+	return a - b;
+}
+
+static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
+			  const struct perf_pmu_alias *alias)
+{
+	struct parse_events_term *term;
+	int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
+
+	list_for_each_entry(term, &alias->terms, list) {
+		if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
+			used += snprintf(buf + used, sub_non_neg(len, used),
+					",%s=%s", term->config,
+					term->val.str);
 	}
-	return false;
+
+	if (sub_non_neg(len, used) > 0) {
+		buf[used] = '/';
+		used++;
+	}
+	if (sub_non_neg(len, used) > 0) {
+		buf[used] = '\0';
+		used++;
+	} else
+		buf[len - 1] = '\0';
+
+	return buf;
+}
+
+int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb)
+{
+	char buf[1024];
+	struct perf_pmu_alias *event;
+	struct pmu_event_info info = {
+		.pmu = pmu,
+	};
+	int ret = 0;
+
+	list_for_each_entry(event, &pmu->aliases, list) {
+		size_t buf_used;
+
+		info.pmu_name = event->pmu_name ?: pmu->name;
+		info.alias = NULL;
+		if (event->desc) {
+			info.name = event->name;
+			buf_used = 0;
+		} else {
+			info.name = format_alias(buf, sizeof(buf), pmu, event);
+			if (pmu->is_core) {
+				info.alias = info.name;
+				info.name = event->name;
+			}
+			buf_used = strlen(buf) + 1;
+		}
+		info.scale_unit = NULL;
+		if (strlen(event->unit) || event->scale != 1.0) {
+			info.scale_unit = buf + buf_used;
+			buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
+					"%G%s", event->scale, event->unit) + 1;
+		}
+		info.desc = event->desc;
+		info.long_desc = event->long_desc;
+		info.encoding_desc = buf + buf_used;
+		buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
+				"%s/%s/", info.pmu_name, event->str) + 1;
+		info.topic = event->topic;
+		info.str = event->str;
+		info.deprecated = event->deprecated;
+		ret = cb(state, &info);
+		if (ret)
+			return ret;
+	}
+	if (pmu->selectable) {
+		info.name = buf;
+		snprintf(buf, sizeof(buf), "%s//", pmu->name);
+		info.alias = NULL;
+		info.scale_unit = NULL;
+		info.desc = NULL;
+		info.long_desc = NULL;
+		info.encoding_desc = NULL;
+		info.topic = NULL;
+		info.pmu_name = pmu->name;
+		info.deprecated = false;
+		ret = cb(state, &info);
+	}
+	return ret;
 }
 
 bool perf_pmu__is_software(const struct perf_pmu *pmu)
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 675c9b97f7bf..f37e3d75094f 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -158,61 +158,22 @@ struct perf_pmu_info {
 	bool snapshot;
 };
 
-#define UNIT_MAX_LEN	31 /* max length for event unit name */
-
-/**
- * struct perf_pmu_alias - An event either read from sysfs or builtin in
- * pmu-events.c, created by parsing the pmu-events json files.
- */
-struct perf_pmu_alias {
-	/** @name: Name of the event like "mem-loads". */
-	char *name;
-	/** @desc: Optional short description of the event. */
-	char *desc;
-	/** @long_desc: Optional long description. */
-	char *long_desc;
-	/**
-	 * @topic: Optional topic such as cache or pipeline, particularly for
-	 * json events.
-	 */
-	char *topic;
-	/**
-	 * @str: Comma separated parameter list like
-	 * "event=0xcd,umask=0x1,ldlat=0x3".
-	 */
-	char *str;
-	/** @terms: Owned list of the original parsed parameters. */
-	struct list_head terms;
-	/** @list: List element of struct perf_pmu aliases. */
-	struct list_head list;
-	/** @unit: Units for the event, such as bytes or cache lines. */
-	char unit[UNIT_MAX_LEN+1];
-	/** @scale: Value to scale read counter values by. */
-	double scale;
-	/**
-	 * @per_pkg: Does the file
-	 * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.per-pkg or
-	 * equivalent json value exist and have the value 1.
-	 */
-	bool per_pkg;
-	/**
-	 * @snapshot: Does the file
-	 * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.snapshot
-	 * exist and have the value 1.
-	 */
-	bool snapshot;
-	/**
-	 * @deprecated: Is the event hidden and so not shown in perf list by
-	 * default.
-	 */
+struct pmu_event_info {
+	const struct perf_pmu *pmu;
+	const char *name;
+	const char* alias;
+	const char *scale_unit;
+	const char *desc;
+	const char *long_desc;
+	const char *encoding_desc;
+	const char *topic;
+	const char *pmu_name;
+	const char *str;
 	bool deprecated;
-	/**
-	 * @pmu_name: The name copied from the json struct pmu_event. This can
-	 * differ from the PMU name as it won't have suffixes.
-	 */
-	char *pmu_name;
 };
 
+typedef int (*pmu_event_callback)(void *state, struct pmu_event_info *info);
+
 void pmu_add_sys_aliases(struct perf_pmu *pmu);
 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 		     struct list_head *head_terms,
@@ -225,7 +186,7 @@ __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name);
 int perf_pmu__format_type(struct perf_pmu *pmu, const char *name);
 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
 			  struct perf_pmu_info *info);
-struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, const char *event);
+int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb);
 
 int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load);
 void perf_pmu_format__set_value(void *format, int config, unsigned long *bits);
@@ -235,6 +196,9 @@ bool is_pmu_core(const char *name);
 bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);
 bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu);
 bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name);
+size_t perf_pmu__num_events(const struct perf_pmu *pmu);
+int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb);
+
 /**
  * perf_pmu_is_software - is the PMU a software PMU as in it uses the
  *                        perf_sw_context in the kernel?
@@ -259,7 +223,6 @@ void pmu_add_cpu_aliases_table(struct perf_pmu *pmu,
 char *perf_pmu__getcpuid(struct perf_pmu *pmu);
 const struct pmu_events_table *pmu_events_table__find(void);
 const struct pmu_metrics_table *pmu_metrics_table__find(void);
-void perf_pmu_free_alias(struct perf_pmu_alias *alias);
 
 int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
 
diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c
index c58ba9fb6a36..4dd5912617ff 100644
--- a/tools/perf/util/pmus.c
+++ b/tools/perf/util/pmus.c
@@ -258,219 +258,145 @@ int __weak perf_pmus__num_mem_pmus(void)
 struct sevent {
 	/** PMU for event. */
 	const struct perf_pmu *pmu;
-	/**
-	 * Optional event for name, desc, etc. If not present then this is a
-	 * selectable PMU and the event name is shown as "//".
-	 */
-	const struct perf_pmu_alias *event;
-	/** Is the PMU for the CPU? */
-	bool is_cpu;
+	const char *name;
+	const char* alias;
+	const char *scale_unit;
+	const char *desc;
+	const char *long_desc;
+	const char *encoding_desc;
+	const char *topic;
+	const char *pmu_name;
+	bool deprecated;
 };
 
 static int cmp_sevent(const void *a, const void *b)
 {
 	const struct sevent *as = a;
 	const struct sevent *bs = b;
-	const char *a_pmu_name = NULL, *b_pmu_name = NULL;
-	const char *a_name = "//", *a_desc = NULL, *a_topic = "";
-	const char *b_name = "//", *b_desc = NULL, *b_topic = "";
+	bool a_iscpu, b_iscpu;
 	int ret;
 
-	if (as->event) {
-		a_name = as->event->name;
-		a_desc = as->event->desc;
-		a_topic = as->event->topic ?: "";
-		a_pmu_name = as->event->pmu_name;
-	}
-	if (bs->event) {
-		b_name = bs->event->name;
-		b_desc = bs->event->desc;
-		b_topic = bs->event->topic ?: "";
-		b_pmu_name = bs->event->pmu_name;
-	}
 	/* Put extra events last. */
-	if (!!a_desc != !!b_desc)
-		return !!a_desc - !!b_desc;
+	if (!!as->desc != !!bs->desc)
+		return !!as->desc - !!bs->desc;
 
 	/* Order by topics. */
-	ret = strcmp(a_topic, b_topic);
+	ret = strcmp(as->topic ?: "", bs->topic ?: "");
 	if (ret)
 		return ret;
 
 	/* Order CPU core events to be first */
-	if (as->is_cpu != bs->is_cpu)
-		return as->is_cpu ? -1 : 1;
+	a_iscpu = as->pmu ? as->pmu->is_core : true;
+	b_iscpu = bs->pmu ? bs->pmu->is_core : true;
+	if (a_iscpu != b_iscpu)
+		return a_iscpu ? -1 : 1;
 
 	/* Order by PMU name. */
 	if (as->pmu != bs->pmu) {
-		a_pmu_name = a_pmu_name ?: (as->pmu->name ?: "");
-		b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: "");
-		ret = strcmp(a_pmu_name, b_pmu_name);
+		ret = strcmp(as->pmu_name ?: "", bs->pmu_name ?: "");
 		if (ret)
 			return ret;
 	}
 
 	/* Order by event name. */
-	return strcmp(a_name, b_name);
+	return strcmp(as->name, bs->name);
 }
 
-static bool pmu_alias_is_duplicate(struct sevent *alias_a,
-				   struct sevent *alias_b)
+static bool pmu_alias_is_duplicate(struct sevent *a, struct sevent *b)
 {
-	const char *a_pmu_name = NULL, *b_pmu_name = NULL;
-	const char *a_name = "//", *b_name = "//";
-
-
-	if (alias_a->event) {
-		a_name = alias_a->event->name;
-		a_pmu_name = alias_a->event->pmu_name;
-	}
-	if (alias_b->event) {
-		b_name = alias_b->event->name;
-		b_pmu_name = alias_b->event->pmu_name;
-	}
-
 	/* Different names -> never duplicates */
-	if (strcmp(a_name, b_name))
+	if (strcmp(a->name ?: "//", b->name ?: "//"))
 		return false;
 
 	/* Don't remove duplicates for different PMUs */
-	a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: "");
-	b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: "");
-	return strcmp(a_pmu_name, b_pmu_name) == 0;
+	return strcmp(a->pmu_name, b->pmu_name) == 0;
 }
 
-static int sub_non_neg(int a, int b)
-{
-	if (b > a)
-		return 0;
-	return a - b;
-}
+struct events_callback_state {
+	struct sevent *aliases;
+	size_t aliases_len;
+	size_t index;
+};
 
-static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
-			  const struct perf_pmu_alias *alias)
+static int perf_pmus__print_pmu_events__callback(void *vstate,
+						struct pmu_event_info *info)
 {
-	struct parse_events_term *term;
-	int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
-
-	list_for_each_entry(term, &alias->terms, list) {
-		if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
-			used += snprintf(buf + used, sub_non_neg(len, used),
-					",%s=%s", term->config,
-					term->val.str);
-	}
+	struct events_callback_state *state = vstate;
+	struct sevent *s;
 
-	if (sub_non_neg(len, used) > 0) {
-		buf[used] = '/';
-		used++;
+	if (state->index >= state->aliases_len) {
+		pr_err("Unexpected event %s/%s/\n", info->pmu->name, info->name);
+		return 1;
 	}
-	if (sub_non_neg(len, used) > 0) {
-		buf[used] = '\0';
-		used++;
-	} else
-		buf[len - 1] = '\0';
-
-	return buf;
+	s = &state->aliases[state->index];
+	s->pmu = info->pmu;
+#define COPY_STR(str) s->str = info->str ? strdup(info->str) : NULL
+	COPY_STR(name);
+	COPY_STR(alias);
+	COPY_STR(scale_unit);
+	COPY_STR(desc);
+	COPY_STR(long_desc);
+	COPY_STR(encoding_desc);
+	COPY_STR(topic);
+	COPY_STR(pmu_name);
+#undef COPY_STR
+	s->deprecated = info->deprecated;
+	state->index++;
+	return 0;
 }
 
 void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state)
 {
 	struct perf_pmu *pmu;
-	struct perf_pmu_alias *event;
-	char buf[1024];
 	int printed = 0;
-	int len, j;
+	int len;
 	struct sevent *aliases;
+	struct events_callback_state state;
 
 	pmu = NULL;
 	len = 0;
-	while ((pmu = perf_pmus__scan(pmu)) != NULL) {
-		list_for_each_entry(event, &pmu->aliases, list)
-			len++;
-		if (pmu->selectable)
-			len++;
-	}
+	while ((pmu = perf_pmus__scan(pmu)) != NULL)
+		len += perf_pmu__num_events(pmu);
+
 	aliases = zalloc(sizeof(struct sevent) * len);
 	if (!aliases) {
 		pr_err("FATAL: not enough memory to print PMU events\n");
 		return;
 	}
 	pmu = NULL;
-	j = 0;
+	state = (struct events_callback_state) {
+		.aliases = aliases,
+		.aliases_len = len,
+		.index = 0,
+	};
 	while ((pmu = perf_pmus__scan(pmu)) != NULL) {
-		bool is_cpu = pmu->is_core;
-
-		list_for_each_entry(event, &pmu->aliases, list) {
-			aliases[j].event = event;
-			aliases[j].pmu = pmu;
-			aliases[j].is_cpu = is_cpu;
-			j++;
-		}
-		if (pmu->selectable) {
-			aliases[j].event = NULL;
-			aliases[j].pmu = pmu;
-			aliases[j].is_cpu = is_cpu;
-			j++;
-		}
+		perf_pmu__for_each_event(pmu, &state, perf_pmus__print_pmu_events__callback);
 	}
-	len = j;
 	qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
-	for (j = 0; j < len; j++) {
-		const char *name, *alias = NULL, *scale_unit = NULL,
-			*desc = NULL, *long_desc = NULL,
-			*encoding_desc = NULL, *topic = NULL,
-			*pmu_name = NULL;
-		bool deprecated = false;
-		size_t buf_used;
-
+	for (int j = 0; j < len; j++) {
 		/* Skip duplicates */
 		if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1]))
 			continue;
 
-		if (!aliases[j].event) {
-			/* A selectable event. */
-			pmu_name = aliases[j].pmu->name;
-			buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1;
-			name = buf;
-		} else {
-			if (aliases[j].event->desc) {
-				name = aliases[j].event->name;
-				buf_used = 0;
-			} else {
-				name = format_alias(buf, sizeof(buf), aliases[j].pmu,
-						    aliases[j].event);
-				if (aliases[j].is_cpu) {
-					alias = name;
-					name = aliases[j].event->name;
-				}
-				buf_used = strlen(buf) + 1;
-			}
-			pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: "");
-			if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) {
-				scale_unit = buf + buf_used;
-				buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
-						"%G%s", aliases[j].event->scale,
-						aliases[j].event->unit) + 1;
-			}
-			desc = aliases[j].event->desc;
-			long_desc = aliases[j].event->long_desc;
-			topic = aliases[j].event->topic;
-			encoding_desc = buf + buf_used;
-			buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
-					"%s/%s/", pmu_name, aliases[j].event->str) + 1;
-			deprecated = aliases[j].event->deprecated;
-		}
 		print_cb->print_event(print_state,
-				pmu_name,
-				topic,
-				name,
-				alias,
-				scale_unit,
-				deprecated,
+				aliases[j].pmu_name,
+				aliases[j].topic,
+				aliases[j].name,
+				aliases[j].alias,
+				aliases[j].scale_unit,
+				aliases[j].deprecated,
 				"Kernel PMU event",
-				desc,
-				long_desc,
-				encoding_desc);
+				aliases[j].desc,
+				aliases[j].long_desc,
+				aliases[j].encoding_desc);
+		zfree(&aliases[j].name);
+		zfree(&aliases[j].alias);
+		zfree(&aliases[j].scale_unit);
+		zfree(&aliases[j].desc);
+		zfree(&aliases[j].long_desc);
+		zfree(&aliases[j].encoding_desc);
+		zfree(&aliases[j].topic);
+		zfree(&aliases[j].pmu_name);
 	}
 	if (printed && pager_in_use())
 		printf("\n");
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 03/18] perf pmu-events: Add extra underscore to function names
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 01/18] perf pmu: Make the loading of formats lazy Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 02/18] perf pmu: Abstract alias/event struct Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 04/18] perf jevents: Group events by PMU Ian Rogers
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Add extra underscore before "for" of pmu_events_table_for_each_event
and pmu_metrics_table_for_each_metric.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/empty-pmu-events.c | 10 +++++-----
 tools/perf/pmu-events/jevents.py         | 12 ++++++------
 tools/perf/pmu-events/pmu-events.h       |  4 ++--
 tools/perf/tests/pmu-events.c            |  4 ++--
 tools/perf/util/metricgroup.c            | 10 +++++-----
 tools/perf/util/pmu.c                    |  2 +-
 tools/perf/util/s390-sample-raw.c        |  2 +-
 7 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index a630c617e879..807f2e55c17c 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -266,7 +266,7 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = {
 	},
 };
 
-int pmu_events_table_for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn,
+int pmu_events_table__for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn,
 				    void *data)
 {
 	for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
@@ -278,7 +278,7 @@ int pmu_events_table_for_each_event(const struct pmu_events_table *table, pmu_ev
 	return 0;
 }
 
-int pmu_metrics_table_for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
+int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				      void *data)
 {
 	for (const struct pmu_metric *pm = &table->entries[0]; pm->metric_expr; pm++) {
@@ -371,7 +371,7 @@ const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const
 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
 {
 	for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->arch; tables++) {
-		int ret = pmu_events_table_for_each_event(&tables->event_table, fn, data);
+		int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data);
 
 		if (ret)
 			return ret;
@@ -384,7 +384,7 @@ int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data)
 	for (const struct pmu_events_map *tables = &pmu_events_map[0];
 	     tables->arch;
 	     tables++) {
-		int ret = pmu_metrics_table_for_each_metric(&tables->metric_table, fn, data);
+		int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
 
 		if (ret)
 			return ret;
@@ -408,7 +408,7 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
 	for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
 	     tables->name;
 	     tables++) {
-		int ret = pmu_events_table_for_each_event(&tables->table, fn, data);
+		int ret = pmu_events_table__for_each_event(&tables->table, fn, data);
 
 		if (ret)
 			return ret;
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index 98cccc3fcbbd..aae5334099b1 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -753,7 +753,7 @@ static void decompress_metric(int offset, struct pmu_metric *pm)
       _args.output_file.write('\twhile (*p++);')
   _args.output_file.write("""}
 
-int pmu_events_table_for_each_event(const struct pmu_events_table *table,
+int pmu_events_table__for_each_event(const struct pmu_events_table *table,
                                     pmu_event_iter_fn fn,
                                     void *data)
 {
@@ -771,7 +771,7 @@ int pmu_events_table_for_each_event(const struct pmu_events_table *table,
         return 0;
 }
 
-int pmu_metrics_table_for_each_metric(const struct pmu_metrics_table *table,
+int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
                                      pmu_metric_iter_fn fn,
                                      void *data)
 {
@@ -870,7 +870,7 @@ int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
         for (const struct pmu_events_map *tables = &pmu_events_map[0];
              tables->arch;
              tables++) {
-                int ret = pmu_events_table_for_each_event(&tables->event_table, fn, data);
+                int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data);
 
                 if (ret)
                         return ret;
@@ -883,7 +883,7 @@ int pmu_for_each_core_metric(pmu_metric_iter_fn fn, void *data)
         for (const struct pmu_events_map *tables = &pmu_events_map[0];
              tables->arch;
              tables++) {
-                int ret = pmu_metrics_table_for_each_metric(&tables->metric_table, fn, data);
+                int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
 
                 if (ret)
                         return ret;
@@ -907,7 +907,7 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
         for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
              tables->name;
              tables++) {
-                int ret = pmu_events_table_for_each_event(&tables->event_table, fn, data);
+                int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data);
 
                 if (ret)
                         return ret;
@@ -920,7 +920,7 @@ int pmu_for_each_sys_metric(pmu_metric_iter_fn fn, void *data)
         for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
              tables->name;
              tables++) {
-                int ret = pmu_metrics_table_for_each_metric(&tables->metric_table, fn, data);
+                int ret = pmu_metrics_table__for_each_metric(&tables->metric_table, fn, data);
 
                 if (ret)
                         return ret;
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index caf59f23cd64..6557381b7de1 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -77,9 +77,9 @@ typedef int (*pmu_metric_iter_fn)(const struct pmu_metric *pm,
 				  const struct pmu_metrics_table *table,
 				  void *data);
 
-int pmu_events_table_for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn,
+int pmu_events_table__for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn,
 				    void *data);
-int pmu_metrics_table_for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
+int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				     void *data);
 
 const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu);
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index dc87e66fb118..5f541eadc088 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -477,12 +477,12 @@ static int test__pmu_event_table(struct test_suite *test __maybe_unused,
 	if (!table || !sys_event_table)
 		return -1;
 
-	err = pmu_events_table_for_each_event(table, test__pmu_event_table_core_callback,
+	err = pmu_events_table__for_each_event(table, test__pmu_event_table_core_callback,
 					      &map_events);
 	if (err)
 		return err;
 
-	err = pmu_events_table_for_each_event(sys_event_table, test__pmu_event_table_sys_callback,
+	err = pmu_events_table__for_each_event(sys_event_table, test__pmu_event_table_sys_callback,
 					      &map_events);
 	if (err)
 		return err;
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index a6a5ed44a679..6231044a491e 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -527,7 +527,7 @@ void metricgroup__print(const struct print_callbacks *print_cb, void *print_stat
 	groups.node_delete = mep_delete;
 	table = pmu_metrics_table__find();
 	if (table) {
-		pmu_metrics_table_for_each_metric(table,
+		pmu_metrics_table__for_each_metric(table,
 						 metricgroup__add_to_mep_groups_callback,
 						 &groups);
 	}
@@ -1069,7 +1069,7 @@ static bool metricgroup__find_metric(const char *pmu,
 		.pm = pm,
 	};
 
-	return pmu_metrics_table_for_each_metric(table, metricgroup__find_metric_callback, &data)
+	return pmu_metrics_table__for_each_metric(table, metricgroup__find_metric_callback, &data)
 		? true : false;
 }
 
@@ -1255,7 +1255,7 @@ static int metricgroup__add_metric(const char *pmu, const char *metric_name, con
 		 * Iterate over all metrics seeing if metric matches either the
 		 * name or group. When it does add the metric to the list.
 		 */
-		ret = pmu_metrics_table_for_each_metric(table, metricgroup__add_metric_callback,
+		ret = pmu_metrics_table__for_each_metric(table, metricgroup__add_metric_callback,
 						       &data);
 		if (ret)
 			goto out;
@@ -1740,7 +1740,7 @@ bool metricgroup__has_metric(const char *pmu, const char *metric)
 	if (!table)
 		return false;
 
-	return pmu_metrics_table_for_each_metric(table, metricgroup__has_metric_callback, &data)
+	return pmu_metrics_table__for_each_metric(table, metricgroup__has_metric_callback, &data)
 		? true : false;
 }
 
@@ -1770,7 +1770,7 @@ unsigned int metricgroups__topdown_max_level(void)
 	if (!table)
 		return false;
 
-	pmu_metrics_table_for_each_metric(table, metricgroup__topdown_max_level_callback,
+	pmu_metrics_table__for_each_metric(table, metricgroup__topdown_max_level_callback,
 					  &max_level);
 	return max_level;
 }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 268aaebfa70c..d91367155e29 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -896,7 +896,7 @@ void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_tab
 		.pmu = pmu,
 	};
 
-	pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data);
+	pmu_events_table__for_each_event(table, pmu_add_cpu_aliases_map_callback, &data);
 	free(data.default_pmu_name);
 }
 
diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c
index c10b891dbad6..91330c874170 100644
--- a/tools/perf/util/s390-sample-raw.c
+++ b/tools/perf/util/s390-sample-raw.c
@@ -168,7 +168,7 @@ static const char *get_counter_name(int set, int nr, const struct pmu_events_tab
 	if (!table)
 		return NULL;
 
-	pmu_events_table_for_each_event(table, get_counter_name_callback, &data);
+	pmu_events_table__for_each_event(table, get_counter_name_callback, &data);
 	return data.result;
 }
 
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 04/18] perf jevents: Group events by PMU
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (2 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 03/18] perf pmu-events: Add extra underscore to function names Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-29 15:28   ` James Clark
  2023-08-24  4:13 ` [PATCH v2 05/18] perf parse-events: Improve error message for double setting Ian Rogers
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Prior to this change a cpuid would map to a list of events where the
PMU would be encoded alongside the event information. This change
breaks apart each group of events so that there is a group per PMU. A
new table is added with the PMU's name and the list of events, the
original table now holding an array of these per PMU tables.

These changes are to make it easier to get per PMU information about
events, rather than the current approach of scanning all events. The
perf binary size with BPF skeletons on x86 is reduced by about 1%. The
unidentified PMU is now always expanded to "cpu".

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++--------
 tools/perf/tests/pmu-events.c    |  30 +++--
 2 files changed, 154 insertions(+), 57 deletions(-)

diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index aae5334099b1..1ad20140114c 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -42,7 +42,7 @@ _metricgroups = {}
 # Order specific JsonEvent attributes will be visited.
 _json_event_attributes = [
     # cmp_sevent related attributes.
-    'name', 'pmu', 'topic', 'desc',
+    'name', 'topic', 'desc',
     # Seems useful, put it early.
     'event',
     # Short things in alphabetical order.
@@ -53,7 +53,7 @@ _json_event_attributes = [
 
 # Attributes that are in pmu_metric rather than pmu_event.
 _json_metric_attributes = [
-    'pmu', 'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
+    'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
     'desc', 'long_desc', 'unit', 'compat', 'metricgroup_no_group',
     'default_metricgroup_name', 'aggr_mode', 'event_grouping'
 ]
@@ -252,7 +252,7 @@ class JsonEvent:
     def unit_to_pmu(unit: str) -> Optional[str]:
       """Convert a JSON Unit to Linux PMU name."""
       if not unit:
-        return None
+        return 'cpu'
       # Comment brought over from jevents.c:
       # it's not realistic to keep adding these, we need something more scalable ...
       table = {
@@ -343,10 +343,13 @@ class JsonEvent:
       self.desc += extra_desc
     if self.long_desc and extra_desc:
       self.long_desc += extra_desc
-    if self.pmu:
-      if self.desc and not self.desc.endswith('. '):
-        self.desc += '. '
-      self.desc = (self.desc if self.desc else '') + ('Unit: ' + self.pmu + ' ')
+    if self.pmu and self.pmu != 'cpu':
+      if not self.desc:
+        self.desc = 'Unit: ' + self.pmu
+      else:
+        if not self.desc.endswith('. '):
+          self.desc += '. '
+      self.desc += 'Unit: ' + self.pmu
     if arch_std:
       if arch_std.lower() in _arch_std_events:
         event = _arch_std_events[arch_std.lower()].event
@@ -437,13 +440,13 @@ def add_events_table_entries(item: os.DirEntry, topic: str) -> None:
 def print_pending_events() -> None:
   """Optionally close events table."""
 
-  def event_cmp_key(j: JsonEvent) -> Tuple[bool, str, str, str, str]:
+  def event_cmp_key(j: JsonEvent) -> Tuple[str, str, bool, str, str]:
     def fix_none(s: Optional[str]) -> str:
       if s is None:
         return ''
       return s
 
-    return (j.desc is not None, fix_none(j.topic), fix_none(j.name), fix_none(j.pmu),
+    return (fix_none(j.pmu).replace(',','_'), fix_none(j.name), j.desc is not None, fix_none(j.topic),
             fix_none(j.metric_name))
 
   global _pending_events
@@ -458,13 +461,36 @@ def print_pending_events() -> None:
     global event_tables
     _event_tables.append(_pending_events_tblname)
 
-  _args.output_file.write(
-      f'static const struct compact_pmu_event {_pending_events_tblname}[] = {{\n')
-
+  first = True
+  last_pmu = None
+  pmus = set()
   for event in sorted(_pending_events, key=event_cmp_key):
+    if event.pmu != last_pmu:
+      if not first:
+        _args.output_file.write('};\n')
+      pmu_name = event.pmu.replace(',', '_')
+      _args.output_file.write(
+          f'static const struct compact_pmu_event {_pending_events_tblname}_{pmu_name}[] = {{\n')
+      first = False
+      last_pmu = event.pmu
+      pmus.add((event.pmu, pmu_name))
+
     _args.output_file.write(event.to_c_string(metric=False))
   _pending_events = []
 
+  _args.output_file.write(f"""
+}};
+
+const struct pmu_table_entry {_pending_events_tblname}[] = {{
+""")
+  for (pmu, tbl_pmu) in sorted(pmus):
+    pmu_name = f"{pmu}\\000"
+    _args.output_file.write(f"""{{
+     .entries = {_pending_events_tblname}_{tbl_pmu},
+     .num_entries = ARRAY_SIZE({_pending_events_tblname}_{tbl_pmu}),
+     .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
+}},
+""")
   _args.output_file.write('};\n\n')
 
 def print_pending_metrics() -> None:
@@ -490,13 +516,36 @@ def print_pending_metrics() -> None:
     global metric_tables
     _metric_tables.append(_pending_metrics_tblname)
 
-  _args.output_file.write(
-      f'static const struct compact_pmu_event {_pending_metrics_tblname}[] = {{\n')
-
+  first = True
+  last_pmu = None
+  pmus = set()
   for metric in sorted(_pending_metrics, key=metric_cmp_key):
+    if metric.pmu != last_pmu:
+      if not first:
+        _args.output_file.write('};\n')
+      pmu_name = metric.pmu.replace(',', '_')
+      _args.output_file.write(
+          f'static const struct compact_pmu_event {_pending_metrics_tblname}_{pmu_name}[] = {{\n')
+      first = False
+      last_pmu = metric.pmu
+      pmus.add((metric.pmu, pmu_name))
+
     _args.output_file.write(metric.to_c_string(metric=True))
   _pending_metrics = []
 
+  _args.output_file.write(f"""
+}};
+
+const struct pmu_table_entry {_pending_metrics_tblname}[] = {{
+""")
+  for (pmu, tbl_pmu) in sorted(pmus):
+    pmu_name = f"{pmu}\\000"
+    _args.output_file.write(f"""{{
+     .entries = {_pending_metrics_tblname}_{tbl_pmu},
+     .num_entries = ARRAY_SIZE({_pending_metrics_tblname}_{tbl_pmu}),
+     .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
+}},
+""")
   _args.output_file.write('};\n\n')
 
 def get_topic(topic: str) -> str:
@@ -532,6 +581,8 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
 
   topic = get_topic(item.name)
   for event in read_json_events(item.path, topic):
+    pmu_name = f"{event.pmu}\\000"
+    _bcs.add(pmu_name)
     if event.name:
       _bcs.add(event.build_c_string(metric=False))
     if event.metric_name:
@@ -577,14 +628,14 @@ def print_mapping_table(archs: Sequence[str]) -> None:
   _args.output_file.write("""
 /* Struct used to make the PMU event table implementation opaque to callers. */
 struct pmu_events_table {
-        const struct compact_pmu_event *entries;
-        size_t length;
+        const struct pmu_table_entry *pmus;
+        uint32_t num_pmus;
 };
 
 /* Struct used to make the PMU metric table implementation opaque to callers. */
 struct pmu_metrics_table {
-        const struct compact_pmu_event *entries;
-        size_t length;
+        const struct pmu_table_entry *pmus;
+        uint32_t num_pmus;
 };
 
 /*
@@ -614,12 +665,12 @@ const struct pmu_events_map pmu_events_map[] = {
 \t.arch = "testarch",
 \t.cpuid = "testcpu",
 \t.event_table = {
-\t\t.entries = pmu_events__test_soc_cpu,
-\t\t.length = ARRAY_SIZE(pmu_events__test_soc_cpu),
+\t\t.pmus = pmu_events__test_soc_cpu,
+\t\t.num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
 \t},
 \t.metric_table = {
-\t\t.entries = pmu_metrics__test_soc_cpu,
-\t\t.length = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
+\t\t.pmus = pmu_metrics__test_soc_cpu,
+\t\t.num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
 \t}
 },
 """)
@@ -649,12 +700,12 @@ const struct pmu_events_map pmu_events_map[] = {
 \t.arch = "{arch}",
 \t.cpuid = "{cpuid}",
 \t.event_table = {{
-\t\t.entries = {event_tblname},
-\t\t.length = {event_size}
+\t\t.pmus = {event_tblname},
+\t\t.num_pmus = {event_size}
 \t}},
 \t.metric_table = {{
-\t\t.entries = {metric_tblname},
-\t\t.length = {metric_size}
+\t\t.pmus = {metric_tblname},
+\t\t.num_pmus = {metric_size}
 \t}}
 }},
 """)
@@ -685,15 +736,15 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = {
   for tblname in _sys_event_tables:
     _args.output_file.write(f"""\t{{
 \t\t.event_table = {{
-\t\t\t.entries = {tblname},
-\t\t\t.length = ARRAY_SIZE({tblname})
+\t\t\t.pmus = {tblname},
+\t\t\t.num_pmus = ARRAY_SIZE({tblname})
 \t\t}},""")
     metric_tblname = _sys_event_table_to_metric_table_mapping[tblname]
     if metric_tblname in _sys_metric_tables:
       _args.output_file.write(f"""
 \t\t.metric_table = {{
-\t\t\t.entries = {metric_tblname},
-\t\t\t.length = ARRAY_SIZE({metric_tblname})
+\t\t\t.pmus = {metric_tblname},
+\t\t\t.num_pmus = ARRAY_SIZE({metric_tblname})
 \t\t}},""")
       printed_metric_tables.append(metric_tblname)
     _args.output_file.write(f"""
@@ -753,18 +804,56 @@ static void decompress_metric(int offset, struct pmu_metric *pm)
       _args.output_file.write('\twhile (*p++);')
   _args.output_file.write("""}
 
+static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
+                                                const struct pmu_table_entry *pmu,
+                                                pmu_event_iter_fn fn,
+                                                void *data)
+{
+        int ret;
+        struct pmu_event pe = {
+                .pmu = &big_c_string[pmu->pmu_name.offset],
+        };
+
+        for (uint32_t i = 0; i < pmu->num_entries; i++) {
+                decompress_event(pmu->entries[i].offset, &pe);
+                if (!pe.name)
+                        continue;
+                ret = fn(&pe, table, data);
+                if (ret)
+                        return ret;
+        }
+        return 0;
+ }
+
 int pmu_events_table__for_each_event(const struct pmu_events_table *table,
                                     pmu_event_iter_fn fn,
                                     void *data)
 {
-        for (size_t i = 0; i < table->length; i++) {
-                struct pmu_event pe;
-                int ret;
+        for (size_t i = 0; i < table->num_pmus; i++) {
+                int ret = pmu_events_table__for_each_event_pmu(table, &table->pmus[i],
+                                                               fn, data);
 
-                decompress_event(table->entries[i].offset, &pe);
-                if (!pe.name)
+                if (ret)
+                        return ret;
+        }
+        return 0;
+}
+
+static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
+                                                const struct pmu_table_entry *pmu,
+                                                pmu_metric_iter_fn fn,
+                                                void *data)
+{
+        int ret;
+        struct pmu_metric pm = {
+                .pmu = &big_c_string[pmu->pmu_name.offset],
+        };
+
+        for (uint32_t i = 0; i < pmu->num_entries; i++) {
+                decompress_metric(pmu->entries[i].offset, &pm);
+                if (!pm.metric_expr)
                         continue;
-                ret = fn(&pe, table, data);
+                ret = fn(&pm, table, data);
                 if (ret)
                         return ret;
         }
@@ -775,14 +864,10 @@ int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
                                      pmu_metric_iter_fn fn,
                                      void *data)
 {
-        for (size_t i = 0; i < table->length; i++) {
-                struct pmu_metric pm;
-                int ret;
+        for (size_t i = 0; i < table->num_pmus; i++) {
+                int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
+                                                                 fn, data);
 
-                decompress_metric(table->entries[i].offset, &pm);
-                if (!pm.metric_expr)
-                        continue;
-                ret = fn(&pm, table, data);
                 if (ret)
                         return ret;
         }
@@ -1010,7 +1095,13 @@ such as "arm/cortex-a34".''',
 #include <stddef.h>
 
 struct compact_pmu_event {
-  int offset;
+        int offset;
+};
+
+struct pmu_table_entry {
+        const struct compact_pmu_event *entries;
+        uint32_t num_entries;
+        struct compact_pmu_event pmu_name;
 };
 
 """)
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 5f541eadc088..0b6efabc3d20 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -44,6 +44,7 @@ struct perf_pmu_test_pmu {
 
 static const struct perf_pmu_test_event bp_l1_btb_correct = {
 	.event = {
+		.pmu = "cpu",
 		.name = "bp_l1_btb_correct",
 		.event = "event=0x8a",
 		.desc = "L1 BTB Correction",
@@ -55,6 +56,7 @@ static const struct perf_pmu_test_event bp_l1_btb_correct = {
 
 static const struct perf_pmu_test_event bp_l2_btb_correct = {
 	.event = {
+		.pmu = "cpu",
 		.name = "bp_l2_btb_correct",
 		.event = "event=0x8b",
 		.desc = "L2 BTB Correction",
@@ -66,6 +68,7 @@ static const struct perf_pmu_test_event bp_l2_btb_correct = {
 
 static const struct perf_pmu_test_event segment_reg_loads_any = {
 	.event = {
+		.pmu = "cpu",
 		.name = "segment_reg_loads.any",
 		.event = "event=0x6,period=200000,umask=0x80",
 		.desc = "Number of segment register loads",
@@ -77,6 +80,7 @@ static const struct perf_pmu_test_event segment_reg_loads_any = {
 
 static const struct perf_pmu_test_event dispatch_blocked_any = {
 	.event = {
+		.pmu = "cpu",
 		.name = "dispatch_blocked.any",
 		.event = "event=0x9,period=200000,umask=0x20",
 		.desc = "Memory cluster signals to block micro-op dispatch for any reason",
@@ -88,6 +92,7 @@ static const struct perf_pmu_test_event dispatch_blocked_any = {
 
 static const struct perf_pmu_test_event eist_trans = {
 	.event = {
+		.pmu = "cpu",
 		.name = "eist_trans",
 		.event = "event=0x3a,period=200000,umask=0x0",
 		.desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
@@ -99,6 +104,7 @@ static const struct perf_pmu_test_event eist_trans = {
 
 static const struct perf_pmu_test_event l3_cache_rd = {
 	.event = {
+		.pmu = "cpu",
 		.name = "l3_cache_rd",
 		.event = "event=0x40",
 		.desc = "L3 cache access, read",
@@ -123,7 +129,7 @@ static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = {
 	.event = {
 		.name = "uncore_hisi_ddrc.flux_wcmd",
 		.event = "event=0x2",
-		.desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
+		.desc = "DDRC write commands. Unit: hisi_sccl,ddrc",
 		.topic = "uncore",
 		.long_desc = "DDRC write commands",
 		.pmu = "hisi_sccl,ddrc",
@@ -137,7 +143,7 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = {
 	.event = {
 		.name = "unc_cbo_xsnp_response.miss_eviction",
 		.event = "event=0x22,umask=0x81",
-		.desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
+		.desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox",
 		.topic = "uncore",
 		.long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
 		.pmu = "uncore_cbox",
@@ -151,7 +157,7 @@ static const struct perf_pmu_test_event uncore_hyphen = {
 	.event = {
 		.name = "event-hyphen",
 		.event = "event=0xe0,umask=0x00",
-		.desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
+		.desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox",
 		.topic = "uncore",
 		.long_desc = "UNC_CBO_HYPHEN",
 		.pmu = "uncore_cbox",
@@ -165,7 +171,7 @@ static const struct perf_pmu_test_event uncore_two_hyph = {
 	.event = {
 		.name = "event-two-hyph",
 		.event = "event=0xc0,umask=0x00",
-		.desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
+		.desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox",
 		.topic = "uncore",
 		.long_desc = "UNC_CBO_TWO_HYPH",
 		.pmu = "uncore_cbox",
@@ -179,7 +185,7 @@ static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = {
 	.event = {
 		.name = "uncore_hisi_l3c.rd_hit_cpipe",
 		.event = "event=0x7",
-		.desc = "Total read hits. Unit: hisi_sccl,l3c ",
+		.desc = "Total read hits. Unit: hisi_sccl,l3c",
 		.topic = "uncore",
 		.long_desc = "Total read hits",
 		.pmu = "hisi_sccl,l3c",
@@ -193,7 +199,7 @@ static const struct perf_pmu_test_event uncore_imc_free_running_cache_miss = {
 	.event = {
 		.name = "uncore_imc_free_running.cache_miss",
 		.event = "event=0x12",
-		.desc = "Total cache misses. Unit: uncore_imc_free_running ",
+		.desc = "Total cache misses. Unit: uncore_imc_free_running",
 		.topic = "uncore",
 		.long_desc = "Total cache misses",
 		.pmu = "uncore_imc_free_running",
@@ -207,7 +213,7 @@ static const struct perf_pmu_test_event uncore_imc_cache_hits = {
 	.event = {
 		.name = "uncore_imc.cache_hits",
 		.event = "event=0x34",
-		.desc = "Total cache hits. Unit: uncore_imc ",
+		.desc = "Total cache hits. Unit: uncore_imc",
 		.topic = "uncore",
 		.long_desc = "Total cache hits",
 		.pmu = "uncore_imc",
@@ -232,13 +238,13 @@ static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = {
 	.event = {
 		.name = "sys_ddr_pmu.write_cycles",
 		.event = "event=0x2b",
-		.desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
+		.desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu",
 		.topic = "uncore",
 		.pmu = "uncore_sys_ddr_pmu",
 		.compat = "v8",
 	},
 	.alias_str = "event=0x2b",
-	.alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
+	.alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu",
 	.matching_pmu = "uncore_sys_ddr_pmu",
 };
 
@@ -246,13 +252,13 @@ static const struct perf_pmu_test_event sys_ccn_pmu_read_cycles = {
 	.event = {
 		.name = "sys_ccn_pmu.read_cycles",
 		.event = "config=0x2c",
-		.desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
+		.desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu",
 		.topic = "uncore",
 		.pmu = "uncore_sys_ccn_pmu",
 		.compat = "0x01",
 	},
 	.alias_str = "config=0x2c",
-	.alias_long_desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
+	.alias_long_desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu",
 	.matching_pmu = "uncore_sys_ccn_pmu",
 };
 
@@ -403,7 +409,7 @@ static int test__pmu_event_table_core_callback(const struct pmu_event *pe,
 	struct perf_pmu_test_event const **test_event_table;
 	bool found = false;
 
-	if (pe->pmu)
+	if (strcmp(pe->pmu, "cpu"))
 		test_event_table = &uncore_events[0];
 	else
 		test_event_table = &core_events[0];
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 05/18] perf parse-events: Improve error message for double setting
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (3 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 04/18] perf jevents: Group events by PMU Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs Ian Rogers
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Double setting information for an event would produce an error
message associated with the PMU rather than the term that was
double setting. Improve the error message to be on the term.

Before:
```
$ perf stat -e 'cpu/inst_retired.any,inst_retired.any/' true
event syntax error: 'cpu/inst_retired.any,inst_retired.any/'
                     \___ Bad event or PMU

Unabled to find PMU or event on a PMU of 'cpu'
Run 'perf list' for a list of valid events
```

After:
```
$ perf stat -e 'cpu/inst_retired.any,inst_retired.any/' true
event syntax error: '..etired.any,inst_retired.any/'
                                  \___ Bad event or PMU

Unabled to find PMU or event on a PMU of 'cpu'

Initial error:
event syntax error: '..etired.any,inst_retired.any/'
                                  \___ Attempt to set event's scale twice
Run 'perf list' for a list of valid events
```

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/parse-events.c |  2 +-
 tools/perf/util/pmu.c          | 34 +++++++++++++++++++++++++++-------
 tools/perf/util/pmu.h          |  2 +-
 3 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7cad82a9f578..781747bedc3e 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1348,7 +1348,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 		return evsel ? 0 : -ENOMEM;
 	}
 
-	if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info))
+	if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info, err))
 		return -EINVAL;
 
 	if (verbose > 1) {
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index d91367155e29..0c82bbeea7d6 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1443,17 +1443,33 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 
 
 static int check_info_data(struct perf_pmu_alias *alias,
-			   struct perf_pmu_info *info)
+			   struct perf_pmu_info *info,
+			   struct parse_events_error *err,
+			   int column)
 {
 	/*
 	 * Only one term in event definition can
 	 * define unit, scale and snapshot, fail
 	 * if there's more than one.
 	 */
-	if ((info->unit && alias->unit[0]) ||
-	    (info->scale && alias->scale) ||
-	    (info->snapshot && alias->snapshot))
+	if (info->unit && alias->unit[0]) {
+		parse_events_error__handle(err, column,
+					strdup("Attempt to set event's unit twice"),
+					NULL);
+		return -EINVAL;
+	}
+	if (info->scale && alias->scale) {
+		parse_events_error__handle(err, column,
+					strdup("Attempt to set event's scale twice"),
+					NULL);
+		return -EINVAL;
+	}
+	if (info->snapshot && alias->snapshot) {
+		parse_events_error__handle(err, column,
+					strdup("Attempt to set event snapshot twice"),
+					NULL);
 		return -EINVAL;
+	}
 
 	if (alias->unit[0])
 		info->unit = alias->unit;
@@ -1472,7 +1488,7 @@ static int check_info_data(struct perf_pmu_alias *alias,
  * defined for the alias
  */
 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
-			  struct perf_pmu_info *info)
+			  struct perf_pmu_info *info, struct parse_events_error *err)
 {
 	struct parse_events_term *term, *h;
 	struct perf_pmu_alias *alias;
@@ -1493,10 +1509,14 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
 		if (!alias)
 			continue;
 		ret = pmu_alias_terms(alias, &term->list);
-		if (ret)
+		if (ret) {
+			parse_events_error__handle(err, term->err_term,
+						strdup("Failure to duplicate terms"),
+						NULL);
 			return ret;
+		}
 
-		ret = check_info_data(alias, info);
+		ret = check_info_data(alias, info, err, term->err_term);
 		if (ret)
 			return ret;
 
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index f37e3d75094f..03211de345c1 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -185,7 +185,7 @@ int perf_pmu__config_terms(struct perf_pmu *pmu,
 __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name);
 int perf_pmu__format_type(struct perf_pmu *pmu, const char *name);
 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
-			  struct perf_pmu_info *info);
+			  struct perf_pmu_info *info, struct parse_events_error *err);
 int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb);
 
 int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load);
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (4 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 05/18] perf parse-events: Improve error message for double setting Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24 13:59   ` Arnaldo Carvalho de Melo
  2023-08-24  4:13 ` [PATCH v2 07/18] perf pmu-events: Reduce processed events by passing PMU Ian Rogers
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Rather than scanning all PMUs for a counter name, scan the PMU
associated with the evsel of the sample. This is done to remove a
dependence on pmu-events.h.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/s390-sample-raw.c | 50 ++++++++++++++++---------------
 1 file changed, 26 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c
index 91330c874170..dc1ed3e95d4d 100644
--- a/tools/perf/util/s390-sample-raw.c
+++ b/tools/perf/util/s390-sample-raw.c
@@ -27,7 +27,7 @@
 #include "color.h"
 #include "sample-raw.h"
 #include "s390-cpumcf-kernel.h"
-#include "pmu-events/pmu-events.h"
+#include "util/pmu.h"
 #include "util/sample.h"
 
 static size_t ctrset_size(struct cf_ctrset_entry *set)
@@ -132,56 +132,57 @@ static int get_counterset_start(int setnr)
 
 struct get_counter_name_data {
 	int wanted;
-	const char *result;
+	char *result;
 };
 
-static int get_counter_name_callback(const struct pmu_event *evp,
-				     const struct pmu_events_table *table __maybe_unused,
-				     void *vdata)
+static int get_counter_name_callback(void *vdata, struct pmu_event_info *info)
 {
 	struct get_counter_name_data *data = vdata;
 	int rc, event_nr;
+	const char *event_str;
 
-	if (evp->name == NULL || evp->event == NULL)
+	if (info->str == NULL)
 		return 0;
-	rc = sscanf(evp->event, "event=%x", &event_nr);
+
+	event_str = strstr(info->str, "event=");
+	if (!event_str)
+		return 0;
+
+	rc = sscanf(event_str, "event=%x", &event_nr);
 	if (rc == 1 && event_nr == data->wanted) {
-		data->result = evp->name;
+		data->result = strdup(info->name);
 		return 1; /* Terminate the search. */
 	}
 	return 0;
 }
 
-/* Scan the PMU table and extract the logical name of a counter from the
- * PMU events table. Input is the counter set and counter number with in the
- * set. Construct the event number and use this as key. If they match return
- * the name of this counter.
+/* Scan the PMU and extract the logical name of a counter from the event. Input
+ * is the counter set and counter number with in the set. Construct the event
+ * number and use this as key. If they match return the name of this counter.
  * If no match is found a NULL pointer is returned.
  */
-static const char *get_counter_name(int set, int nr, const struct pmu_events_table *table)
+static char *get_counter_name(int set, int nr, struct perf_pmu *pmu)
 {
 	struct get_counter_name_data data = {
 		.wanted = get_counterset_start(set) + nr,
 		.result = NULL,
 	};
 
-	if (!table)
+	if (!pmu)
 		return NULL;
 
-	pmu_events_table__for_each_event(table, get_counter_name_callback, &data);
+	perf_pmu__for_each_event(pmu, &data, get_counter_name_callback);
 	return data.result;
 }
 
-static void s390_cpumcfdg_dump(struct perf_sample *sample)
+static void s390_cpumcfdg_dump(struct perf_pmu *pmu, struct perf_sample *sample)
 {
 	size_t i, len = sample->raw_size, offset = 0;
 	unsigned char *buf = sample->raw_data;
 	const char *color = PERF_COLOR_BLUE;
 	struct cf_ctrset_entry *cep, ce;
-	const struct pmu_events_table *table;
 	u64 *p;
 
-	table = pmu_events_table__find();
 	while (offset < len) {
 		cep = (struct cf_ctrset_entry *)(buf + offset);
 
@@ -199,11 +200,12 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample)
 		color_fprintf(stdout, color, "    [%#08zx] Counterset:%d"
 			      " Counters:%d\n", offset, ce.set, ce.ctr);
 		for (i = 0, p = (u64 *)(cep + 1); i < ce.ctr; ++i, ++p) {
-			const char *ev_name = get_counter_name(ce.set, i, table);
+			char *ev_name = get_counter_name(ce.set, i, pmu);
 
 			color_fprintf(stdout, color,
 				      "\tCounter:%03d %s Value:%#018lx\n", i,
 				      ev_name ?: "<unknown>", be64_to_cpu(*p));
+			free(ev_name);
 		}
 		offset += ctrset_size(&ce);
 	}
@@ -216,14 +218,14 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample)
  */
 void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, struct perf_sample *sample)
 {
-	struct evsel *ev_bc000;
+	struct evsel *evsel;
 
 	if (event->header.type != PERF_RECORD_SAMPLE)
 		return;
 
-	ev_bc000 = evlist__event2evsel(evlist, event);
-	if (ev_bc000 == NULL ||
-	    ev_bc000->core.attr.config != PERF_EVENT_CPUM_CF_DIAG)
+	evsel = evlist__event2evsel(evlist, event);
+	if (evsel == NULL ||
+	    evsel->core.attr.config != PERF_EVENT_CPUM_CF_DIAG)
 		return;
 
 	/* Display raw data on screen */
@@ -231,5 +233,5 @@ void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, str
 		pr_err("Invalid counter set data encountered\n");
 		return;
 	}
-	s390_cpumcfdg_dump(sample);
+	s390_cpumcfdg_dump(evsel->pmu, sample);
 }
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 07/18] perf pmu-events: Reduce processed events by passing PMU
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (5 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 08/18] perf pmu-events: Add pmu_events_table__find_event Ian Rogers
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Pass the PMU to pmu_events_table__for_each_event so that entries that
don't match don't need to be processed by callback. If a NULL PMU is
passed then all PMUs are processed. perf bench internals pmu-scan
"Average PMU scanning" performance is reduced by about 5% on an Intel
tigerlake.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/empty-pmu-events.c | 15 ++++++----
 tools/perf/pmu-events/jevents.py         | 18 ++++++++----
 tools/perf/pmu-events/pmu-events.h       |  4 ++-
 tools/perf/tests/pmu-events.c            |  6 ++--
 tools/perf/util/pmu.c                    | 35 +++++++-----------------
 tools/perf/util/pmu.h                    |  1 +
 6 files changed, 41 insertions(+), 38 deletions(-)

diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 807f2e55c17c..2d6f748280ac 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -266,12 +266,16 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = {
 	},
 };
 
-int pmu_events_table__for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn,
-				    void *data)
+int pmu_events_table__for_each_event(const struct pmu_events_table *table, struct perf_pmu *pmu,
+				     pmu_event_iter_fn fn, void *data)
 {
 	for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
-		int ret = fn(pe, table, data);
+		int ret;
 
+                if (pmu && !pmu__name_match(pmu, pe->pmu))
+                        continue;
+
+		ret = fn(pe, table, data);
 		if (ret)
 			return ret;
 	}
@@ -371,7 +375,8 @@ const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const
 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
 {
 	for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->arch; tables++) {
-		int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data);
+		int ret = pmu_events_table__for_each_event(&tables->event_table,
+							   /*pmu=*/ NULL, fn, data);
 
 		if (ret)
 			return ret;
@@ -408,7 +413,7 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
 	for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
 	     tables->name;
 	     tables++) {
-		int ret = pmu_events_table__for_each_event(&tables->table, fn, data);
+		int ret = pmu_events_table__for_each_event(&tables->table, /*pmu=*/ NULL, fn, data);
 
 		if (ret)
 			return ret;
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index 1ad20140114c..396af53e0e45 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -826,14 +826,20 @@ static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *t
  }
 
 int pmu_events_table__for_each_event(const struct pmu_events_table *table,
+                                    struct perf_pmu *pmu,
                                     pmu_event_iter_fn fn,
                                     void *data)
 {
         for (size_t i = 0; i < table->num_pmus; i++) {
-                int ret = pmu_events_table__for_each_event_pmu(table, &table->pmus[i],
-                                                               fn, data);
+                const struct pmu_table_entry *table_pmu = &table->pmus[i];
+                const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
+                int ret;
 
-                if (ret)
+                if (pmu && !pmu__name_match(pmu, pmu_name))
+                        continue;
+
+                ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data);
+                if (pmu || ret)
                         return ret;
         }
         return 0;
@@ -955,7 +961,8 @@ int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data)
         for (const struct pmu_events_map *tables = &pmu_events_map[0];
              tables->arch;
              tables++) {
-                int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data);
+                int ret = pmu_events_table__for_each_event(&tables->event_table,
+                                                           /*pmu=*/ NULL, fn, data);
 
                 if (ret)
                         return ret;
@@ -992,7 +999,8 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data)
         for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0];
              tables->name;
              tables++) {
-                int ret = pmu_events_table__for_each_event(&tables->event_table, fn, data);
+                int ret = pmu_events_table__for_each_event(&tables->event_table,
+                                                           /*pmu=*/ NULL, fn, data);
 
                 if (ret)
                         return ret;
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index 6557381b7de1..c0303ba42e97 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -77,7 +77,9 @@ typedef int (*pmu_metric_iter_fn)(const struct pmu_metric *pm,
 				  const struct pmu_metrics_table *table,
 				  void *data);
 
-int pmu_events_table__for_each_event(const struct pmu_events_table *table, pmu_event_iter_fn fn,
+int pmu_events_table__for_each_event(const struct pmu_events_table *table,
+				    struct perf_pmu *pmu,
+				    pmu_event_iter_fn fn,
 				    void *data);
 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				     void *data);
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 0b6efabc3d20..92d1f6f0e666 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -483,12 +483,14 @@ static int test__pmu_event_table(struct test_suite *test __maybe_unused,
 	if (!table || !sys_event_table)
 		return -1;
 
-	err = pmu_events_table__for_each_event(table, test__pmu_event_table_core_callback,
+	err = pmu_events_table__for_each_event(table, /*pmu=*/ NULL,
+					      test__pmu_event_table_core_callback,
 					      &map_events);
 	if (err)
 		return err;
 
-	err = pmu_events_table__for_each_event(sys_event_table, test__pmu_event_table_sys_callback,
+	err = pmu_events_table__for_each_event(sys_event_table, /*pmu=*/ NULL,
+					      test__pmu_event_table_sys_callback,
 					      &map_events);
 	if (err)
 		return err;
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 0c82bbeea7d6..9ba9ac3d3d96 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -859,28 +859,14 @@ static bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
 	return res;
 }
 
-struct pmu_add_cpu_aliases_map_data {
-	/* List being added to. */
-	struct list_head *head;
-	/* If a pmu_event lacks a given PMU the default used. */
-	char *default_pmu_name;
-	/* The PMU that we're searching for events for. */
-	struct perf_pmu *pmu;
-};
-
 static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
 					const struct pmu_events_table *table __maybe_unused,
 					void *vdata)
 {
-	struct pmu_add_cpu_aliases_map_data *data = vdata;
-	const char *pname = pe->pmu ?: data->default_pmu_name;
+	struct list_head *head = vdata;
 
-	if (!strcmp(pname, data->pmu->name) ||
-	    (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->pmu->name))) {
-		/* need type casts to override 'const' */
-		__perf_pmu__new_alias(data->head, -1, (char *)pe->name, (char *)pe->desc,
-				      (char *)pe->event, pe);
-	}
+	/* need type casts to override 'const' */
+	__perf_pmu__new_alias(head, -1, (char *)pe->name, (char *)pe->desc, (char *)pe->event, pe);
 	return 0;
 }
 
@@ -890,14 +876,7 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
  */
 void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table)
 {
-	struct pmu_add_cpu_aliases_map_data data = {
-		.head = &pmu->aliases,
-		.default_pmu_name = perf_pmus__default_pmu_name(),
-		.pmu = pmu,
-	};
-
-	pmu_events_table__for_each_event(table, pmu_add_cpu_aliases_map_callback, &data);
-	free(data.default_pmu_name);
+	pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, &pmu->aliases);
 }
 
 static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
@@ -1713,6 +1692,12 @@ int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_
 	return ret;
 }
 
+bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name)
+{
+	return !strcmp(pmu->name, pmu_name) ||
+		(pmu->is_uncore && pmu_uncore_alias_match(pmu_name, pmu->name));
+}
+
 bool perf_pmu__is_software(const struct perf_pmu *pmu)
 {
 	if (pmu->is_core || pmu->is_uncore || pmu->auxtrace)
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 03211de345c1..2b1730152bc0 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -198,6 +198,7 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu);
 bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name);
 size_t perf_pmu__num_events(const struct perf_pmu *pmu);
 int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb);
+bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name);
 
 /**
  * perf_pmu_is_software - is the PMU a software PMU as in it uses the
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 08/18] perf pmu-events: Add pmu_events_table__find_event
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (6 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 07/18] perf pmu-events: Reduce processed events by passing PMU Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 09/18] perf pmu: Parse sysfs events directly from a file Ian Rogers
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

jevents stores events sorted by name. Add a find function that will
binary search event names avoiding the need to linearly search through
events. Add a test in tests/pmu-events.c. If the PMU or event aren't
found -1000 is returned. If the event is found but no callback
function given, 0 is returned. This allows the find function also act
as a test for existence.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/empty-pmu-events.c | 16 ++++++
 tools/perf/pmu-events/jevents.py         | 64 ++++++++++++++++++++++++
 tools/perf/pmu-events/pmu-events.h       |  5 ++
 tools/perf/tests/pmu-events.c            |  5 ++
 4 files changed, 90 insertions(+)

diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index 2d6f748280ac..ef18d403f25f 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -282,6 +282,22 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, struc
 	return 0;
 }
 
+int pmu_events_table__find_event(const struct pmu_events_table *table,
+                                 struct perf_pmu *pmu,
+                                 const char *name,
+                                 pmu_event_iter_fn fn,
+                                 void *data)
+{
+	for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
+                if (pmu && !pmu__name_match(pmu, pe->pmu))
+                        continue;
+
+		if (!strcasecmp(pe->name, name))
+			return fn(pe, table, data);
+	}
+        return -1000;
+}
+
 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				      void *data)
 {
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index 396af53e0e45..991fcf6cca64 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -825,6 +825,49 @@ static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *t
         return 0;
  }
 
+static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table,
+                                            const struct pmu_table_entry *pmu,
+                                            const char *name,
+                                            pmu_event_iter_fn fn,
+                                            void *data)
+{
+        struct pmu_event pe = {
+                .pmu = &big_c_string[pmu->pmu_name.offset],
+        };
+        int low = 0, high = pmu->num_entries - 1;
+
+        while (low <= high) {
+                int cmp, mid = (low + high) / 2;
+
+                decompress_event(pmu->entries[mid].offset, &pe);
+
+                if (!pe.name && !name)
+                        goto do_call;
+
+                if (!pe.name && name) {
+                        low = mid + 1;
+                        continue;
+                }
+                if (pe.name && !name) {
+                        high = mid - 1;
+                        continue;
+                }
+
+                cmp = strcasecmp(pe.name, name);
+                if (cmp < 0) {
+                        low = mid + 1;
+                        continue;
+                }
+                if (cmp > 0) {
+                        high = mid - 1;
+                        continue;
+                }
+  do_call:
+                return fn ? fn(&pe, table, data) : 0;
+        }
+        return -1000;
+}
+
 int pmu_events_table__for_each_event(const struct pmu_events_table *table,
                                     struct perf_pmu *pmu,
                                     pmu_event_iter_fn fn,
@@ -845,6 +888,27 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table,
         return 0;
 }
 
+int pmu_events_table__find_event(const struct pmu_events_table *table,
+                                 struct perf_pmu *pmu,
+                                 const char *name,
+                                 pmu_event_iter_fn fn,
+                                 void *data)
+{
+        for (size_t i = 0; i < table->num_pmus; i++) {
+                const struct pmu_table_entry *table_pmu = &table->pmus[i];
+                const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
+                int ret;
+
+                if (!pmu__name_match(pmu, pmu_name))
+                        continue;
+
+                ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
+                if (ret != -1000)
+                        return ret;
+        }
+        return -1000;
+}
+
 static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
                                                 const struct pmu_table_entry *pmu,
                                                 pmu_metric_iter_fn fn,
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index c0303ba42e97..9882b7125761 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -81,6 +81,11 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table,
 				    struct perf_pmu *pmu,
 				    pmu_event_iter_fn fn,
 				    void *data);
+int pmu_events_table__find_event(const struct pmu_events_table *table,
+                                 struct perf_pmu *pmu,
+                                 const char *name,
+                                 pmu_event_iter_fn fn,
+				 void *data);
 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				     void *data);
 
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 92d1f6f0e666..34f0de182fa9 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -546,6 +546,11 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
 
 	pmu_add_cpu_aliases_table(pmu, table);
 
+	res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
+	if (res != 0) {
+		pr_debug("Missing test event in test architecture");
+		return res;
+	}
 	for (; *test_event_table; test_event_table++) {
 		struct perf_pmu_test_event test_event = **test_event_table;
 		struct pmu_event const *event = &test_event.event;
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 09/18] perf pmu: Parse sysfs events directly from a file
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (7 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 08/18] perf pmu-events: Add pmu_events_table__find_event Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 10/18] perf pmu: Prefer passing pmu to aliases list Ian Rogers
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Rather than read a sysfs events file into a 256 byte char buffer, pass
the FILE* directly to the lex/yacc parser. This avoids there being a
maximum events file size. While changing the API, constify some
arguments to remove unnecessary casts. Allocating the read buffer
decreases the performance of pmu-scan by around 3%.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/arch/x86/util/intel-pt.c |  2 +-
 tools/perf/tests/parse-events.c     |  2 +-
 tools/perf/util/parse-events.c      | 18 +++++++----
 tools/perf/util/parse-events.h      |  3 +-
 tools/perf/util/pmu.c               | 48 ++++++++++-------------------
 5 files changed, 33 insertions(+), 40 deletions(-)

diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 27944c15ac14..31807791589e 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -74,7 +74,7 @@ static int intel_pt_parse_terms_with_default(struct perf_pmu *pmu,
 
 	INIT_LIST_HEAD(terms);
 
-	err = parse_events_terms(terms, str);
+	err = parse_events_terms(terms, str, /*input=*/ NULL);
 	if (err)
 		goto out_free;
 
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 658fb9599d95..d86076d575ed 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -2472,7 +2472,7 @@ static int test_term(const struct terms_test *t)
 
 	INIT_LIST_HEAD(&terms);
 
-	ret = parse_events_terms(&terms, t->str);
+	ret = parse_events_terms(&terms, t->str, /*input=*/ NULL);
 	if (ret) {
 		pr_debug("failed to parse terms '%s', err %d\n",
 			 t->str , ret);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 781747bedc3e..c71e135d7335 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1715,6 +1715,7 @@ int parse_events_name(struct list_head *list, const char *name)
 }
 
 static int parse_events__scanner(const char *str,
+				 FILE *input,
 				 struct parse_events_state *parse_state)
 {
 	YY_BUFFER_STATE buffer;
@@ -1725,7 +1726,10 @@ static int parse_events__scanner(const char *str,
 	if (ret)
 		return ret;
 
-	buffer = parse_events__scan_string(str, scanner);
+	if (str)
+		buffer = parse_events__scan_string(str, scanner);
+	else
+	        parse_events_set_in(input, scanner);
 
 #ifdef PARSER_DEBUG
 	parse_events_debug = 1;
@@ -1733,8 +1737,10 @@ static int parse_events__scanner(const char *str,
 #endif
 	ret = parse_events_parse(parse_state, scanner);
 
-	parse_events__flush_buffer(buffer, scanner);
-	parse_events__delete_buffer(buffer, scanner);
+	if (str) {
+		parse_events__flush_buffer(buffer, scanner);
+		parse_events__delete_buffer(buffer, scanner);
+	}
 	parse_events_lex_destroy(scanner);
 	return ret;
 }
@@ -1742,7 +1748,7 @@ static int parse_events__scanner(const char *str,
 /*
  * parse event config string, return a list of event terms.
  */
-int parse_events_terms(struct list_head *terms, const char *str)
+int parse_events_terms(struct list_head *terms, const char *str, FILE *input)
 {
 	struct parse_events_state parse_state = {
 		.terms  = NULL,
@@ -1750,7 +1756,7 @@ int parse_events_terms(struct list_head *terms, const char *str)
 	};
 	int ret;
 
-	ret = parse_events__scanner(str, &parse_state);
+	ret = parse_events__scanner(str, input, &parse_state);
 
 	if (!ret) {
 		list_splice(parse_state.terms, terms);
@@ -2001,7 +2007,7 @@ int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filte
 	};
 	int ret, ret2;
 
-	ret = parse_events__scanner(str, &parse_state);
+	ret = parse_events__scanner(str, /*input=*/ NULL, &parse_state);
 
 	if (!ret && list_empty(&parse_state.list)) {
 		WARN_ONCE(true, "WARNING: event parser found nothing\n");
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 411f69b2ac3a..c7f779420723 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -9,6 +9,7 @@
 #include <stdbool.h>
 #include <linux/types.h>
 #include <linux/perf_event.h>
+#include <stdio.h>
 #include <string.h>
 
 struct evsel;
@@ -42,7 +43,7 @@ static inline int parse_events(struct evlist *evlist, const char *str,
 
 int parse_event(struct evlist *evlist, const char *str);
 
-int parse_events_terms(struct list_head *terms, const char *str);
+int parse_events_terms(struct list_head *terms, const char *str, FILE *input);
 int parse_filter(const struct option *opt, const char *str, int unset);
 int exclude_perf(const struct option *opt, const char *arg, int unset);
 
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 9ba9ac3d3d96..263c63eabc2e 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -280,7 +280,7 @@ int perf_pmu__convert_scale(const char *scale, char **end, double *sval)
 	return ret;
 }
 
-static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, char *name)
+static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, const char *name)
 {
 	struct stat st;
 	ssize_t sret;
@@ -312,7 +312,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, char *
 	return ret;
 }
 
-static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, char *name)
+static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, const char *name)
 {
 	char path[PATH_MAX];
 	ssize_t sret;
@@ -343,7 +343,7 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, char *n
 }
 
 static int
-perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, char *name)
+perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, const char *name)
 {
 	char path[PATH_MAX];
 	int fd;
@@ -361,7 +361,7 @@ perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, char *name)
 }
 
 static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
-				    int dirfd, char *name)
+				    int dirfd, const char *name)
 {
 	char path[PATH_MAX];
 	int fd;
@@ -454,8 +454,9 @@ static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias,
 	return false;
 }
 
-static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name,
-				 char *desc, char *val, const struct pmu_event *pe)
+static int perf_pmu__new_alias(struct list_head *list, int dirfd, const char *name,
+				const char *desc, const char *val, FILE *val_fd,
+				const struct pmu_event *pe)
 {
 	struct parse_events_term *term;
 	struct perf_pmu_alias *alias;
@@ -484,7 +485,7 @@ static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name,
 	alias->snapshot = false;
 	alias->deprecated = deprecated;
 
-	ret = parse_events_terms(&alias->terms, val);
+	ret = parse_events_terms(&alias->terms, val, val_fd);
 	if (ret) {
 		pr_err("Cannot parse alias %s: %d\n", val, ret);
 		free(alias);
@@ -541,23 +542,6 @@ static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name,
 	return 0;
 }
 
-static int perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, FILE *file)
-{
-	char buf[256];
-	int ret;
-
-	ret = fread(buf, 1, sizeof(buf), file);
-	if (ret == 0)
-		return -EINVAL;
-
-	buf[ret] = 0;
-
-	/* Remove trailing newline from sysfs file */
-	strim(buf);
-
-	return __perf_pmu__new_alias(list, dirfd, name, NULL, buf, NULL);
-}
-
 static inline bool pmu_alias_info_file(char *name)
 {
 	size_t len;
@@ -613,7 +597,8 @@ static int pmu_aliases_parse(int dirfd, struct list_head *head)
 			continue;
 		}
 
-		if (perf_pmu__new_alias(head, dirfd, name, file) < 0)
+		if (perf_pmu__new_alias(head, dirfd, name, /*desc=*/ NULL,
+					/*val=*/ NULL, file, /*pe=*/ NULL) < 0)
 			pr_debug("Cannot set up %s\n", name);
 		fclose(file);
 	}
@@ -866,7 +851,7 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
 	struct list_head *head = vdata;
 
 	/* need type casts to override 'const' */
-	__perf_pmu__new_alias(head, -1, (char *)pe->name, (char *)pe->desc, (char *)pe->event, pe);
+	perf_pmu__new_alias(head, -1, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
 	return 0;
 }
 
@@ -907,11 +892,12 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
 
 	if (!strcmp(pmu->id, pe->compat) &&
 	    pmu_uncore_alias_match(pe->pmu, pmu->name)) {
-		__perf_pmu__new_alias(idata->head, -1,
-				      (char *)pe->name,
-				      (char *)pe->desc,
-				      (char *)pe->event,
-				      pe);
+		perf_pmu__new_alias(idata->head, -1,
+				pe->name,
+				pe->desc,
+				pe->event,
+				/*val_fd=*/ NULL,
+				pe);
 	}
 
 	return 0;
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 10/18] perf pmu: Prefer passing pmu to aliases list
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (8 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 09/18] perf pmu: Parse sysfs events directly from a file Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 11/18] perf pmu: Merge json events with sysfs at load time Ian Rogers
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

The aliases list is part of the PMU. Rather than pass the aliases
list, pass the full PMU simplifying some callbacks.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/pmu.c | 44 ++++++++++++++++---------------------------
 1 file changed, 16 insertions(+), 28 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 263c63eabc2e..c37d98a11861 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -435,12 +435,12 @@ static void perf_pmu__del_aliases(struct perf_pmu *pmu)
 /* Merge an alias, search in alias list. If this name is already
  * present merge both of them to combine all information.
  */
-static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias,
-				 struct list_head *alist)
+static bool perf_pmu_merge_alias(struct perf_pmu *pmu,
+				 struct perf_pmu_alias *newalias)
 {
 	struct perf_pmu_alias *a;
 
-	list_for_each_entry(a, alist, list) {
+	list_for_each_entry(a, &pmu->aliases, list) {
 		if (!strcasecmp(newalias->name, a->name)) {
 			if (newalias->pmu_name && a->pmu_name &&
 			    !strcasecmp(newalias->pmu_name, a->pmu_name)) {
@@ -454,7 +454,7 @@ static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias,
 	return false;
 }
 
-static int perf_pmu__new_alias(struct list_head *list, int dirfd, const char *name,
+static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name,
 				const char *desc, const char *val, FILE *val_fd,
 				const struct pmu_event *pe)
 {
@@ -536,8 +536,8 @@ static int perf_pmu__new_alias(struct list_head *list, int dirfd, const char *na
 	alias->str = strdup(newval);
 	alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL;
 
-	if (!perf_pmu_merge_alias(alias, list))
-		list_add_tail(&alias->list, list);
+	if (!perf_pmu_merge_alias(pmu, alias))
+		list_add_tail(&alias->list, &pmu->aliases);
 
 	return 0;
 }
@@ -563,7 +563,7 @@ static inline bool pmu_alias_info_file(char *name)
  * Process all the sysfs attributes located under the directory
  * specified in 'dir' parameter.
  */
-static int pmu_aliases_parse(int dirfd, struct list_head *head)
+static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
 {
 	struct dirent *evt_ent;
 	DIR *event_dir;
@@ -597,7 +597,7 @@ static int pmu_aliases_parse(int dirfd, struct list_head *head)
 			continue;
 		}
 
-		if (perf_pmu__new_alias(head, dirfd, name, /*desc=*/ NULL,
+		if (perf_pmu__new_alias(pmu, dirfd, name, /*desc=*/ NULL,
 					/*val=*/ NULL, file, /*pe=*/ NULL) < 0)
 			pr_debug("Cannot set up %s\n", name);
 		fclose(file);
@@ -620,7 +620,7 @@ static int pmu_aliases(struct perf_pmu *pmu, int dirfd, const char *name)
 		return 0;
 
 	/* it'll close the fd */
-	if (pmu_aliases_parse(fd, &pmu->aliases))
+	if (pmu_aliases_parse(pmu, fd))
 		return -1;
 
 	return 0;
@@ -848,10 +848,9 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
 					const struct pmu_events_table *table __maybe_unused,
 					void *vdata)
 {
-	struct list_head *head = vdata;
+	struct perf_pmu *pmu = vdata;
 
-	/* need type casts to override 'const' */
-	perf_pmu__new_alias(head, -1, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
+	perf_pmu__new_alias(pmu, -1, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
 	return 0;
 }
 
@@ -861,7 +860,7 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
  */
 void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table)
 {
-	pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, &pmu->aliases);
+	pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, pmu);
 }
 
 static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
@@ -875,24 +874,18 @@ static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
 	pmu_add_cpu_aliases_table(pmu, table);
 }
 
-struct pmu_sys_event_iter_data {
-	struct list_head *head;
-	struct perf_pmu *pmu;
-};
-
 static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
 				       const struct pmu_events_table *table __maybe_unused,
-				       void *data)
+				       void *vdata)
 {
-	struct pmu_sys_event_iter_data *idata = data;
-	struct perf_pmu *pmu = idata->pmu;
+	struct perf_pmu *pmu = vdata;
 
 	if (!pe->compat || !pe->pmu)
 		return 0;
 
 	if (!strcmp(pmu->id, pe->compat) &&
 	    pmu_uncore_alias_match(pe->pmu, pmu->name)) {
-		perf_pmu__new_alias(idata->head, -1,
+		perf_pmu__new_alias(pmu, -1,
 				pe->name,
 				pe->desc,
 				pe->event,
@@ -905,15 +898,10 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
 
 void pmu_add_sys_aliases(struct perf_pmu *pmu)
 {
-	struct pmu_sys_event_iter_data idata = {
-		.head = &pmu->aliases,
-		.pmu = pmu,
-	};
-
 	if (!pmu->id)
 		return;
 
-	pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, &idata);
+	pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, pmu);
 }
 
 struct perf_event_attr * __weak
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 11/18] perf pmu: Merge json events with sysfs at load time
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (9 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 10/18] perf pmu: Prefer passing pmu to aliases list Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 12/18] perf pmu: Cache json events table Ian Rogers
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Rather than load all sysfs events then parsing all json events and
merging with ones that already exist. When a sysfs event is loaded,
look for a corresponding json event and merge immediately.

To simplify the logic, early exit the perf_pmu__new_alias function if
an alias is attempted to be added twice - as merging has already been
explicitly handled.

Fix the copying of terms to a merged alias and some ENOMEM paths.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/pmu.c | 177 +++++++++++++++++++++---------------------
 1 file changed, 88 insertions(+), 89 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index c37d98a11861..bc2dd8f94bcf 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -377,38 +377,6 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
 	return 0;
 }
 
-static void perf_pmu_assign_str(char *name, const char *field, char **old_str,
-				char **new_str)
-{
-	if (!*old_str)
-		goto set_new;
-
-	if (*new_str) {	/* Have new string, check with old */
-		if (strcasecmp(*old_str, *new_str))
-			pr_debug("alias %s differs in field '%s'\n",
-				 name, field);
-		zfree(old_str);
-	} else		/* Nothing new --> keep old string */
-		return;
-set_new:
-	*old_str = *new_str;
-	*new_str = NULL;
-}
-
-static void perf_pmu_update_alias(struct perf_pmu_alias *old,
-				  struct perf_pmu_alias *newalias)
-{
-	perf_pmu_assign_str(old->name, "desc", &old->desc, &newalias->desc);
-	perf_pmu_assign_str(old->name, "long_desc", &old->long_desc,
-			    &newalias->long_desc);
-	perf_pmu_assign_str(old->name, "topic", &old->topic, &newalias->topic);
-	perf_pmu_assign_str(old->name, "value", &old->str, &newalias->str);
-	old->scale = newalias->scale;
-	old->per_pkg = newalias->per_pkg;
-	old->snapshot = newalias->snapshot;
-	memcpy(old->unit, newalias->unit, sizeof(old->unit));
-}
-
 /* Delete an alias entry. */
 static void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
 {
@@ -432,26 +400,58 @@ static void perf_pmu__del_aliases(struct perf_pmu *pmu)
 	}
 }
 
-/* Merge an alias, search in alias list. If this name is already
- * present merge both of them to combine all information.
- */
-static bool perf_pmu_merge_alias(struct perf_pmu *pmu,
-				 struct perf_pmu_alias *newalias)
+static struct perf_pmu_alias *perf_pmu__find_alias(const struct perf_pmu *pmu, const char *name)
 {
-	struct perf_pmu_alias *a;
+	struct perf_pmu_alias *alias;
 
-	list_for_each_entry(a, &pmu->aliases, list) {
-		if (!strcasecmp(newalias->name, a->name)) {
-			if (newalias->pmu_name && a->pmu_name &&
-			    !strcasecmp(newalias->pmu_name, a->pmu_name)) {
-				continue;
-			}
-			perf_pmu_update_alias(a, newalias);
-			perf_pmu_free_alias(newalias);
-			return true;
-		}
+	list_for_each_entry(alias, &pmu->aliases, list) {
+		if (!strcasecmp(alias->name, name))
+			return alias;
 	}
-	return false;
+	return NULL;
+}
+
+static bool assign_str(const char *name, const char *field, char **old_str,
+				const char *new_str)
+{
+	if (!*old_str && new_str) {
+		*old_str = strdup(new_str);
+		return true;
+	}
+
+	if (!new_str || !strcasecmp(*old_str, new_str))
+		return false; /* Nothing to update. */
+
+	pr_debug("alias %s differs in field '%s' ('%s' != '%s')\n",
+		name, field, *old_str, new_str);
+	zfree(old_str);
+	*old_str = strdup(new_str);
+	return true;
+}
+
+static int update_alias(const struct pmu_event *pe,
+			const struct pmu_events_table *table __maybe_unused,
+			void *vdata)
+{
+	struct perf_pmu_alias *alias = vdata;
+	int ret = 0;
+
+	assign_str(pe->name, "desc", &alias->desc, pe->desc);
+	assign_str(pe->name, "long_desc", &alias->long_desc, pe->long_desc);
+	assign_str(pe->name, "topic", &alias->topic, pe->topic);
+	alias->per_pkg = pe->perpkg;
+	if (assign_str(pe->name, "value", &alias->str, pe->event)) {
+		parse_events_terms__purge(&alias->terms);
+		ret = parse_events_terms(&alias->terms, pe->event, /*input=*/NULL);
+	}
+	if (!ret && pe->unit) {
+		char *unit;
+
+		ret = perf_pmu__convert_scale(pe->unit, &unit, &alias->scale);
+		if (!ret)
+			snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
+	}
+	return ret;
 }
 
 static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name,
@@ -465,6 +465,11 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 	const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL;
 	bool deprecated = false, perpkg = false;
 
+	if (perf_pmu__find_alias(pmu, name)) {
+		/* Alias was already created/loaded. */
+		return 0;
+	}
+
 	if (pe) {
 		long_desc = pe->long_desc;
 		topic = pe->topic;
@@ -492,27 +497,6 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 		return ret;
 	}
 
-	/* Scan event and remove leading zeroes, spaces, newlines, some
-	 * platforms have terms specified as
-	 * event=0x0091 (read from files ../<PMU>/events/<FILE>
-	 * and terms specified as event=0x91 (read from JSON files).
-	 *
-	 * Rebuild string to make alias->str member comparable.
-	 */
-	memset(newval, 0, sizeof(newval));
-	ret = 0;
-	list_for_each_entry(term, &alias->terms, list) {
-		if (ret)
-			ret += scnprintf(newval + ret, sizeof(newval) - ret,
-					 ",");
-		if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
-			ret += scnprintf(newval + ret, sizeof(newval) - ret,
-					 "%s=%#x", term->config, term->val.num);
-		else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
-			ret += scnprintf(newval + ret, sizeof(newval) - ret,
-					 "%s=%s", term->config, term->val.str);
-	}
-
 	alias->name = strdup(name);
 	if (dirfd >= 0) {
 		/*
@@ -528,17 +512,43 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 	alias->long_desc = long_desc ? strdup(long_desc) :
 				desc ? strdup(desc) : NULL;
 	alias->topic = topic ? strdup(topic) : NULL;
+	alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL;
 	if (unit) {
-		if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0)
+		if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) {
+			perf_pmu_free_alias(alias);
 			return -1;
+		}
 		snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
 	}
-	alias->str = strdup(newval);
-	alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL;
+	if (!pe) {
+		/* Update an event from sysfs with json data. */
+		const struct pmu_events_table *table = perf_pmu__find_events_table(pmu);
 
-	if (!perf_pmu_merge_alias(pmu, alias))
-		list_add_tail(&alias->list, &pmu->aliases);
+		if (table)
+			pmu_events_table__find_event(table, pmu, name, update_alias, alias);
+	}
 
+	/* Scan event and remove leading zeroes, spaces, newlines, some
+	 * platforms have terms specified as
+	 * event=0x0091 (read from files ../<PMU>/events/<FILE>
+	 * and terms specified as event=0x91 (read from JSON files).
+	 *
+	 * Rebuild string to make alias->str member comparable.
+	 */
+	ret = 0;
+	list_for_each_entry(term, &alias->terms, list) {
+		if (ret)
+			ret += scnprintf(newval + ret, sizeof(newval) - ret,
+					 ",");
+		if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
+			ret += scnprintf(newval + ret, sizeof(newval) - ret,
+					 "%s=%#x", term->config, term->val.num);
+		else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
+			ret += scnprintf(newval + ret, sizeof(newval) - ret,
+					 "%s=%s", term->config, term->val.str);
+	}
+	alias->str = strdup(newval);
+	list_add_tail(&alias->list, &pmu->aliases);
 	return 0;
 }
 
@@ -944,6 +954,9 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 	INIT_LIST_HEAD(&pmu->format);
 	INIT_LIST_HEAD(&pmu->aliases);
 	INIT_LIST_HEAD(&pmu->caps);
+	pmu->name = strdup(name);
+	if (!pmu->name)
+		goto err;
 	/*
 	 * The pmu data we store & need consists of the pmu
 	 * type value and format definitions. Load both right
@@ -962,9 +975,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 	}
 	pmu->is_core = is_pmu_core(name);
 	pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core);
-	pmu->name = strdup(name);
-	if (!pmu->name)
-		goto err;
 
 	/* Read type, and ensure that type value is successfully assigned (return 1) */
 	if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1)
@@ -1357,17 +1367,6 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 	return perf_pmu__config_terms(pmu, attr, head_terms, zero, err);
 }
 
-static struct perf_pmu_alias *perf_pmu__find_alias(const struct perf_pmu *pmu, const char *str)
-{
-	struct perf_pmu_alias *alias;
-
-	list_for_each_entry(alias, &pmu->aliases, list) {
-		if (!strcasecmp(alias->name, str))
-			return alias;
-	}
-	return NULL;
-}
-
 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 					     struct parse_events_term *term)
 {
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 12/18] perf pmu: Cache json events table
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (10 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 11/18] perf pmu: Merge json events with sysfs at load time Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 13/18] perf pmu: Lazily add json events Ian Rogers
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Cache the json events table so that finding it isn't done per
event/alias. Change the events table find so that when the PMU is
given, if the PMU has no json events return null. Update usage to
always use the PMU variable.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/jevents.py | 14 ++++++++++++--
 tools/perf/tests/pmu-events.c    |  2 ++
 tools/perf/util/pmu.c            | 16 +++++++---------
 tools/perf/util/pmu.h            |  4 ++++
 4 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index 991fcf6cca64..f07864fabd54 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -948,7 +948,7 @@ const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu)
 {
         const struct pmu_events_table *table = NULL;
         char *cpuid = perf_pmu__getcpuid(pmu);
-        int i;
+        size_t i;
 
         /* on some platforms which uses cpus map, cpuid can be NULL for
          * PMUs other than CORE PMUs.
@@ -968,7 +968,17 @@ const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu)
                 }
         }
         free(cpuid);
-        return table;
+        if (!pmu)
+                return table;
+
+        for (i = 0; i < table->num_pmus; i++) {
+                const struct pmu_table_entry *table_pmu = &table->pmus[i];
+                const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
+
+                if (pmu__name_match(pmu, pmu_name))
+                        return table;
+        }
+        return NULL;
 }
 
 const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu)
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 34f0de182fa9..4fcb84fd1f65 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -544,6 +544,7 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
 	INIT_LIST_HEAD(&pmu->list);
 	pmu->name = strdup(pmu_name);
 
+	pmu->events_table = table;
 	pmu_add_cpu_aliases_table(pmu, table);
 
 	res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
@@ -583,6 +584,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 	events_table = find_core_events_table("testarch", "testcpu");
 	if (!events_table)
 		return -1;
+	pmu->events_table = events_table;
 	pmu_add_cpu_aliases_table(pmu, events_table);
 	pmu_add_sys_aliases(pmu);
 
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index bc2dd8f94bcf..685903c1970b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -522,10 +522,10 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 	}
 	if (!pe) {
 		/* Update an event from sysfs with json data. */
-		const struct pmu_events_table *table = perf_pmu__find_events_table(pmu);
-
-		if (table)
-			pmu_events_table__find_event(table, pmu, name, update_alias, alias);
+		if (pmu->events_table) {
+			pmu_events_table__find_event(pmu->events_table, pmu, name,
+						     update_alias, alias);
+		}
 	}
 
 	/* Scan event and remove leading zeroes, spaces, newlines, some
@@ -875,13 +875,10 @@ void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_tab
 
 static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
 {
-	const struct pmu_events_table *table;
-
-	table = perf_pmu__find_events_table(pmu);
-	if (!table)
+	if (!pmu->events_table)
 		return;
 
-	pmu_add_cpu_aliases_table(pmu, table);
+	pmu_add_cpu_aliases_table(pmu, pmu->events_table);
 }
 
 static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
@@ -992,6 +989,7 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 	if (pmu->is_uncore)
 		pmu->id = pmu_id(name);
 	pmu->max_precise = pmu_max_precise(dirfd, pmu);
+	pmu->events_table = perf_pmu__find_events_table(pmu);
 	pmu_add_cpu_aliases(pmu);
 	pmu_add_sys_aliases(pmu);
 	list_add_tail(&pmu->list, pmus);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 2b1730152bc0..6bf0fbde4e85 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -114,6 +114,10 @@ struct perf_pmu {
 	 * from json events in pmu-events.c.
 	 */
 	struct list_head aliases;
+	/**
+	 * @events_table: The events table for json events in pmu-events.c.
+	 */
+	const struct pmu_events_table *events_table;
 	/** @caps_initialized: Has the list caps been initialized? */
 	bool caps_initialized;
 	/** @nr_caps: The length of the list caps. */
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 13/18] perf pmu: Lazily add json events
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (11 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 12/18] perf pmu: Cache json events table Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 14/18] perf pmu: Scan type early to fail an invalid PMU quickly Ian Rogers
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Rather than scanning all json events and adding them when a PMU is
created, add the alias when the json event is needed.

Average core PMU scanning run time reduced by 60.2%. Average PMU
scanning run time reduced by 15%. Page faults with no events reduced
by 74 page faults, 4% of total.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/empty-pmu-events.c | 14 +++++++
 tools/perf/pmu-events/jevents.py         | 15 +++++++
 tools/perf/pmu-events/pmu-events.h       |  4 ++
 tools/perf/tests/pmu-events.c            |  2 +
 tools/perf/util/pmu.c                    | 50 ++++++++++++++++++------
 tools/perf/util/pmu.h                    | 15 +++++--
 6 files changed, 85 insertions(+), 15 deletions(-)

diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
index ef18d403f25f..12bd043a05e3 100644
--- a/tools/perf/pmu-events/empty-pmu-events.c
+++ b/tools/perf/pmu-events/empty-pmu-events.c
@@ -298,6 +298,20 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
         return -1000;
 }
 
+size_t pmu_events_table__num_events(const struct pmu_events_table *table,
+                                    struct perf_pmu *pmu)
+{
+        size_t count = 0;
+
+	for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
+                if (pmu && !pmu__name_match(pmu, pe->pmu))
+                        continue;
+
+		count++;
+	}
+        return count;
+}
+
 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				      void *data)
 {
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index f07864fabd54..01335a452e70 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -909,6 +909,21 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
         return -1000;
 }
 
+size_t pmu_events_table__num_events(const struct pmu_events_table *table,
+                                    struct perf_pmu *pmu)
+{
+        size_t count = 0;
+
+        for (size_t i = 0; i < table->num_pmus; i++) {
+                const struct pmu_table_entry *table_pmu = &table->pmus[i];
+                const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
+
+                if (pmu__name_match(pmu, pmu_name))
+                        count += table_pmu->num_entries;
+        }
+        return count;
+}
+
 static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
                                                 const struct pmu_table_entry *pmu,
                                                 pmu_metric_iter_fn fn,
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
index 9882b7125761..f5aa96f1685c 100644
--- a/tools/perf/pmu-events/pmu-events.h
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -3,6 +3,7 @@
 #define PMU_EVENTS_H
 
 #include <stdbool.h>
+#include <stddef.h>
 
 struct perf_pmu;
 
@@ -86,6 +87,9 @@ int pmu_events_table__find_event(const struct pmu_events_table *table,
                                  const char *name,
                                  pmu_event_iter_fn fn,
 				 void *data);
+size_t pmu_events_table__num_events(const struct pmu_events_table *table,
+				    struct perf_pmu *pmu);
+
 int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
 				     void *data);
 
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 4fcb84fd1f65..9ac893ae5f0d 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -546,6 +546,7 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
 
 	pmu->events_table = table;
 	pmu_add_cpu_aliases_table(pmu, table);
+	pmu->cpu_aliases_added = true;
 
 	res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
 	if (res != 0) {
@@ -586,6 +587,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 		return -1;
 	pmu->events_table = events_table;
 	pmu_add_cpu_aliases_table(pmu, events_table);
+	pmu->cpu_aliases_added = true;
 	pmu_add_sys_aliases(pmu);
 
 	/* Count how many aliases we generated */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 685903c1970b..b6a118226541 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -523,8 +523,9 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 	if (!pe) {
 		/* Update an event from sysfs with json data. */
 		if (pmu->events_table) {
-			pmu_events_table__find_event(pmu->events_table, pmu, name,
-						     update_alias, alias);
+			if (pmu_events_table__find_event(pmu->events_table, pmu, name,
+							 update_alias, alias) == 0)
+				pmu->loaded_json_aliases++;
 		}
 	}
 
@@ -548,6 +549,10 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 					 "%s=%s", term->config, term->val.str);
 	}
 	alias->str = strdup(newval);
+	if (!pe)
+		pmu->sysfs_aliases++;
+	else
+		pmu->loaded_json_aliases++;
 	list_add_tail(&alias->list, &pmu->aliases);
 	return 0;
 }
@@ -878,7 +883,11 @@ static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
 	if (!pmu->events_table)
 		return;
 
+	if (pmu->cpu_aliases_added)
+		return;
+
 	pmu_add_cpu_aliases_table(pmu, pmu->events_table);
+	pmu->cpu_aliases_added = true;
 }
 
 static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
@@ -990,7 +999,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 		pmu->id = pmu_id(name);
 	pmu->max_precise = pmu_max_precise(dirfd, pmu);
 	pmu->events_table = perf_pmu__find_events_table(pmu);
-	pmu_add_cpu_aliases(pmu);
 	pmu_add_sys_aliases(pmu);
 	list_add_tail(&pmu->list, pmus);
 
@@ -1368,6 +1376,7 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 					     struct parse_events_term *term)
 {
+	struct perf_pmu_alias *alias;
 	char *name;
 
 	if (parse_events__is_hardcoded_term(term))
@@ -1388,7 +1397,18 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 		return NULL;
 	}
 
-	return perf_pmu__find_alias(pmu, name);
+	alias = perf_pmu__find_alias(pmu, name);
+	if (alias || pmu->cpu_aliases_added)
+		return alias;
+
+	/* Alias doesn't exist, try to get it from the json events. */
+	if (pmu->events_table &&
+	    pmu_events_table__find_event(pmu->events_table, pmu, name,
+				         pmu_add_cpu_aliases_map_callback,
+				         pmu) == 0) {
+		alias = perf_pmu__find_alias(pmu, name);
+	}
+	return alias;
 }
 
 
@@ -1555,18 +1575,23 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu)
 	return !pmu->is_core || perf_pmus__num_core_pmus() == 1;
 }
 
-bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name)
+bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
 {
-	return perf_pmu__find_alias(pmu, name) != NULL;
+	if (perf_pmu__find_alias(pmu, name) != NULL)
+		return true;
+	if (pmu->cpu_aliases_added || !pmu->events_table)
+		return false;
+	return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0;
 }
 
-size_t perf_pmu__num_events(const struct perf_pmu *pmu)
+size_t perf_pmu__num_events(struct perf_pmu *pmu)
 {
-	struct list_head *list;
-	size_t nr = 0;
+	size_t nr = pmu->sysfs_aliases;
 
-	list_for_each(list, &pmu->aliases)
-		nr++;
+	if (pmu->cpu_aliases_added)
+		 nr += pmu->loaded_json_aliases;
+	else if (pmu->events_table)
+		nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases;
 
 	return pmu->selectable ? nr + 1 : nr;
 }
@@ -1604,7 +1629,7 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
 	return buf;
 }
 
-int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb)
+int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
 {
 	char buf[1024];
 	struct perf_pmu_alias *event;
@@ -1613,6 +1638,7 @@ int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_
 	};
 	int ret = 0;
 
+	pmu_add_cpu_aliases(pmu);
 	list_for_each_entry(event, &pmu->aliases, list) {
 		size_t buf_used;
 
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6bf0fbde4e85..288d2908382a 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -118,6 +118,15 @@ struct perf_pmu {
 	 * @events_table: The events table for json events in pmu-events.c.
 	 */
 	const struct pmu_events_table *events_table;
+	/** @sysfs_aliases: Number of sysfs aliases loaded. */
+	uint32_t sysfs_aliases;
+	/** @sysfs_aliases: Number of json event aliases loaded. */
+	uint32_t loaded_json_aliases;
+	/**
+	 * @cpu_aliases_added: Have all json events table entries for the PMU
+	 * been added?
+	 */
+	bool cpu_aliases_added;
 	/** @caps_initialized: Has the list caps been initialized? */
 	bool caps_initialized;
 	/** @nr_caps: The length of the list caps. */
@@ -199,9 +208,9 @@ bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
 bool is_pmu_core(const char *name);
 bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);
 bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu);
-bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name);
-size_t perf_pmu__num_events(const struct perf_pmu *pmu);
-int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb);
+bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name);
+size_t perf_pmu__num_events(struct perf_pmu *pmu);
+int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
 bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name);
 
 /**
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 14/18] perf pmu: Scan type early to fail an invalid PMU quickly
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (12 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 13/18] perf pmu: Lazily add json events Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 15/18] perf pmu: Be lazy about loading event info files from sysfs Ian Rogers
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Scan sysfs PMU's type early so that format and aliases aren't
attempted to be loaded if the PMU name is invalid. This is the case
for event_pmu tokens in parse-events.y where a wildcard name is first
assumed to be a PMU name.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/pmu.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index b6a118226541..9e3b72d84168 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -957,12 +957,21 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 	if (!pmu)
 		return NULL;
 
-	INIT_LIST_HEAD(&pmu->format);
-	INIT_LIST_HEAD(&pmu->aliases);
-	INIT_LIST_HEAD(&pmu->caps);
 	pmu->name = strdup(name);
 	if (!pmu->name)
 		goto err;
+
+	/*
+	 * Read type early to fail fast if a lookup name isn't a PMU. Ensure
+	 * that type value is successfully assigned (return 1).
+	 */
+	if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1)
+		goto err;
+
+	INIT_LIST_HEAD(&pmu->format);
+	INIT_LIST_HEAD(&pmu->aliases);
+	INIT_LIST_HEAD(&pmu->caps);
+
 	/*
 	 * The pmu data we store & need consists of the pmu
 	 * type value and format definitions. Load both right
@@ -982,10 +991,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 	pmu->is_core = is_pmu_core(name);
 	pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core);
 
-	/* Read type, and ensure that type value is successfully assigned (return 1) */
-	if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1)
-		goto err;
-
 	alias_name = pmu_find_alias_name(name);
 	if (alias_name) {
 		pmu->alias_name = strdup(alias_name);
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 15/18] perf pmu: Be lazy about loading event info files from sysfs
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (13 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 14/18] perf pmu: Scan type early to fail an invalid PMU quickly Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 16/18] perf pmu: Lazily load sysfs aliases Ian Rogers
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Event info is only needed when an event is parsed or when merging data
from an json and sysfs event. Be lazy in its loading to reduce file
accesses.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/util/pmu.c | 128 +++++++++++++++++++++++++++---------------
 1 file changed, 83 insertions(+), 45 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 9e3b72d84168..493d3e59fd50 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -58,6 +58,11 @@ struct perf_pmu_alias {
 	struct list_head terms;
 	/** @list: List element of struct perf_pmu aliases. */
 	struct list_head list;
+	/**
+	 * @pmu_name: The name copied from the json struct pmu_event. This can
+	 * differ from the PMU name as it won't have suffixes.
+	 */
+	char *pmu_name;
 	/** @unit: Units for the event, such as bytes or cache lines. */
 	char unit[UNIT_MAX_LEN+1];
 	/** @scale: Value to scale read counter values by. */
@@ -79,11 +84,10 @@ struct perf_pmu_alias {
 	 * default.
 	 */
 	bool deprecated;
-	/**
-	 * @pmu_name: The name copied from the json struct pmu_event. This can
-	 * differ from the PMU name as it won't have suffixes.
-	 */
-	char *pmu_name;
+	/** @from_sysfs: Was the alias from sysfs or a json event? */
+	bool from_sysfs;
+	/** @info_loaded: Have the scale, unit and other values been read from disk? */
+	bool info_loaded;
 };
 
 /**
@@ -280,17 +284,21 @@ int perf_pmu__convert_scale(const char *scale, char **end, double *sval)
 	return ret;
 }
 
-static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, const char *name)
+static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
 {
 	struct stat st;
 	ssize_t sret;
+	size_t len;
 	char scale[128];
 	int fd, ret = -1;
 	char path[PATH_MAX];
 
-	scnprintf(path, PATH_MAX, "%s.scale", name);
+	len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
+	if (!len)
+		return 0;
+	scnprintf(path + len, sizeof(path) - len, "%s/%s.scale", pmu->name, alias->name);
 
-	fd = openat(dirfd, path, O_RDONLY);
+	fd = open(path, O_RDONLY);
 	if (fd == -1)
 		return -1;
 
@@ -312,15 +320,20 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, const
 	return ret;
 }
 
-static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, const char *name)
+static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
 {
 	char path[PATH_MAX];
+	size_t len;
 	ssize_t sret;
 	int fd;
 
-	scnprintf(path, PATH_MAX, "%s.unit", name);
 
-	fd = openat(dirfd, path, O_RDONLY);
+	len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
+	if (!len)
+		return 0;
+	scnprintf(path + len, sizeof(path) - len, "%s/%s.unit", pmu->name, alias->name);
+
+	fd = open(path, O_RDONLY);
 	if (fd == -1)
 		return -1;
 
@@ -343,14 +356,18 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, const c
 }
 
 static int
-perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, const char *name)
+perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
 {
 	char path[PATH_MAX];
+	size_t len;
 	int fd;
 
-	scnprintf(path, PATH_MAX, "%s.per-pkg", name);
+	len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
+	if (!len)
+		return 0;
+	scnprintf(path + len, sizeof(path) - len, "%s/%s.per-pkg", pmu->name, alias->name);
 
-	fd = openat(dirfd, path, O_RDONLY);
+	fd = open(path, O_RDONLY);
 	if (fd == -1)
 		return -1;
 
@@ -360,15 +377,18 @@ perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, const char *nam
 	return 0;
 }
 
-static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
-				    int dirfd, const char *name)
+static int perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
 {
 	char path[PATH_MAX];
+	size_t len;
 	int fd;
 
-	scnprintf(path, PATH_MAX, "%s.snapshot", name);
+	len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
+	if (!len)
+		return 0;
+	scnprintf(path + len, sizeof(path) - len, "%s/%s.snapshot", pmu->name, alias->name);
 
-	fd = openat(dirfd, path, O_RDONLY);
+	fd = open(path, O_RDONLY);
 	if (fd == -1)
 		return -1;
 
@@ -429,32 +449,52 @@ static bool assign_str(const char *name, const char *field, char **old_str,
 	return true;
 }
 
+static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
+{
+	if (!alias->from_sysfs || alias->info_loaded)
+		return;
+
+	/*
+	 * load unit name and scale if available
+	 */
+	perf_pmu__parse_unit(pmu, alias);
+	perf_pmu__parse_scale(pmu, alias);
+	perf_pmu__parse_per_pkg(pmu, alias);
+	perf_pmu__parse_snapshot(pmu, alias);
+}
+
+struct update_alias_data {
+	struct perf_pmu *pmu;
+	struct perf_pmu_alias *alias;
+};
+
 static int update_alias(const struct pmu_event *pe,
 			const struct pmu_events_table *table __maybe_unused,
 			void *vdata)
 {
-	struct perf_pmu_alias *alias = vdata;
+	struct update_alias_data *data = vdata;
 	int ret = 0;
 
-	assign_str(pe->name, "desc", &alias->desc, pe->desc);
-	assign_str(pe->name, "long_desc", &alias->long_desc, pe->long_desc);
-	assign_str(pe->name, "topic", &alias->topic, pe->topic);
-	alias->per_pkg = pe->perpkg;
-	if (assign_str(pe->name, "value", &alias->str, pe->event)) {
-		parse_events_terms__purge(&alias->terms);
-		ret = parse_events_terms(&alias->terms, pe->event, /*input=*/NULL);
+	read_alias_info(data->pmu, data->alias);
+	assign_str(pe->name, "desc", &data->alias->desc, pe->desc);
+	assign_str(pe->name, "long_desc", &data->alias->long_desc, pe->long_desc);
+	assign_str(pe->name, "topic", &data->alias->topic, pe->topic);
+	data->alias->per_pkg = pe->perpkg;
+	if (assign_str(pe->name, "value", &data->alias->str, pe->event)) {
+		parse_events_terms__purge(&data->alias->terms);
+		ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL);
 	}
 	if (!ret && pe->unit) {
 		char *unit;
 
-		ret = perf_pmu__convert_scale(pe->unit, &unit, &alias->scale);
+		ret = perf_pmu__convert_scale(pe->unit, &unit, &data->alias->scale);
 		if (!ret)
-			snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
+			snprintf(data->alias->unit, sizeof(data->alias->unit), "%s", unit);
 	}
 	return ret;
 }
 
-static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name,
+static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
 				const char *desc, const char *val, FILE *val_fd,
 				const struct pmu_event *pe)
 {
@@ -498,16 +538,6 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 	}
 
 	alias->name = strdup(name);
-	if (dirfd >= 0) {
-		/*
-		 * load unit name and scale if available
-		 */
-		perf_pmu__parse_unit(alias, dirfd, name);
-		perf_pmu__parse_scale(alias, dirfd, name);
-		perf_pmu__parse_per_pkg(alias, dirfd, name);
-		perf_pmu__parse_snapshot(alias, dirfd, name);
-	}
-
 	alias->desc = desc ? strdup(desc) : NULL;
 	alias->long_desc = long_desc ? strdup(long_desc) :
 				desc ? strdup(desc) : NULL;
@@ -522,9 +552,15 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name
 	}
 	if (!pe) {
 		/* Update an event from sysfs with json data. */
+		struct update_alias_data data = {
+			.pmu = pmu,
+			.alias = alias,
+		};
+
+		alias->from_sysfs = true;
 		if (pmu->events_table) {
 			if (pmu_events_table__find_event(pmu->events_table, pmu, name,
-							 update_alias, alias) == 0)
+							 update_alias, &data) == 0)
 				pmu->loaded_json_aliases++;
 		}
 	}
@@ -612,7 +648,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
 			continue;
 		}
 
-		if (perf_pmu__new_alias(pmu, dirfd, name, /*desc=*/ NULL,
+		if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL,
 					/*val=*/ NULL, file, /*pe=*/ NULL) < 0)
 			pr_debug("Cannot set up %s\n", name);
 		fclose(file);
@@ -865,7 +901,7 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
 {
 	struct perf_pmu *pmu = vdata;
 
-	perf_pmu__new_alias(pmu, -1, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
+	perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
 	return 0;
 }
 
@@ -901,7 +937,7 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
 
 	if (!strcmp(pmu->id, pe->compat) &&
 	    pmu_uncore_alias_match(pe->pmu, pmu->name)) {
-		perf_pmu__new_alias(pmu, -1,
+		perf_pmu__new_alias(pmu,
 				pe->name,
 				pe->desc,
 				pe->event,
@@ -1417,11 +1453,13 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 }
 
 
-static int check_info_data(struct perf_pmu_alias *alias,
+static int check_info_data(struct perf_pmu *pmu,
+			   struct perf_pmu_alias *alias,
 			   struct perf_pmu_info *info,
 			   struct parse_events_error *err,
 			   int column)
 {
+	read_alias_info(pmu, alias);
 	/*
 	 * Only one term in event definition can
 	 * define unit, scale and snapshot, fail
@@ -1491,7 +1529,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
 			return ret;
 		}
 
-		ret = check_info_data(alias, info, err, term->err_term);
+		ret = check_info_data(pmu, alias, info, err, term->err_term);
 		if (ret)
 			return ret;
 
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 16/18] perf pmu: Lazily load sysfs aliases
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (14 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 15/18] perf pmu: Be lazy about loading event info files from sysfs Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 17/18] perf jevents: Sort strings in the big C string to reduce faults Ian Rogers
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Don't load sysfs aliases for a PMU when the PMU is first created,
defer until an alias needs to be found. For the pmu-scan benchmark,
average core PMU scanning is reduced by 30.8%, and average PMU
scanning by 12.6%.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/tests/pmu-events.c |  2 +
 tools/perf/util/pmu.c         | 81 ++++++++++++++++++-----------------
 tools/perf/util/pmu.h         |  2 +
 3 files changed, 46 insertions(+), 39 deletions(-)

diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
index 9ac893ae5f0d..3dc1ebee4d9f 100644
--- a/tools/perf/tests/pmu-events.c
+++ b/tools/perf/tests/pmu-events.c
@@ -547,6 +547,7 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
 	pmu->events_table = table;
 	pmu_add_cpu_aliases_table(pmu, table);
 	pmu->cpu_aliases_added = true;
+	pmu->sysfs_aliases_loaded = true;
 
 	res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
 	if (res != 0) {
@@ -588,6 +589,7 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu)
 	pmu->events_table = events_table;
 	pmu_add_cpu_aliases_table(pmu, events_table);
 	pmu->cpu_aliases_added = true;
+	pmu->sysfs_aliases_loaded = true;
 	pmu_add_sys_aliases(pmu);
 
 	/* Count how many aliases we generated */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 493d3e59fd50..bb2ca29cd7bd 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -115,6 +115,8 @@ struct perf_pmu_format {
 	bool loaded;
 };
 
+static int pmu_aliases_parse(struct perf_pmu *pmu);
+
 static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name)
 {
 	struct perf_pmu_format *format;
@@ -420,10 +422,15 @@ static void perf_pmu__del_aliases(struct perf_pmu *pmu)
 	}
 }
 
-static struct perf_pmu_alias *perf_pmu__find_alias(const struct perf_pmu *pmu, const char *name)
+static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu,
+						   const char *name,
+						   bool load)
 {
 	struct perf_pmu_alias *alias;
 
+	if (load && !pmu->sysfs_aliases_loaded)
+		pmu_aliases_parse(pmu);
+
 	list_for_each_entry(alias, &pmu->aliases, list) {
 		if (!strcasecmp(alias->name, name))
 			return alias;
@@ -505,7 +512,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
 	const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL;
 	bool deprecated = false, perpkg = false;
 
-	if (perf_pmu__find_alias(pmu, name)) {
+	if (perf_pmu__find_alias(pmu, name, /*load=*/ false)) {
 		/* Alias was already created/loaded. */
 		return 0;
 	}
@@ -611,18 +618,33 @@ static inline bool pmu_alias_info_file(char *name)
 }
 
 /*
- * Process all the sysfs attributes located under the directory
- * specified in 'dir' parameter.
+ * Reading the pmu event aliases definition, which should be located at:
+ * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
  */
-static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
+static int pmu_aliases_parse(struct perf_pmu *pmu)
 {
+	char path[PATH_MAX];
 	struct dirent *evt_ent;
 	DIR *event_dir;
-	int fd;
+	size_t len;
+	int fd, dir_fd;
 
-	event_dir = fdopendir(dirfd);
-	if (!event_dir)
+	len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
+	if (!len)
+		return 0;
+	scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name);
+
+	dir_fd = open(path, O_DIRECTORY);
+	if (dir_fd == -1) {
+		pmu->sysfs_aliases_loaded = true;
+		return 0;
+	}
+
+	event_dir = fdopendir(dir_fd);
+	if (!event_dir){
+		close (dir_fd);
 		return -EINVAL;
+	}
 
 	while ((evt_ent = readdir(event_dir))) {
 		char *name = evt_ent->d_name;
@@ -637,7 +659,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
 		if (pmu_alias_info_file(name))
 			continue;
 
-		fd = openat(dirfd, name, O_RDONLY);
+		fd = openat(dir_fd, name, O_RDONLY);
 		if (fd == -1) {
 			pr_debug("Cannot open %s\n", name);
 			continue;
@@ -655,25 +677,8 @@ static int pmu_aliases_parse(struct perf_pmu *pmu, int dirfd)
 	}
 
 	closedir(event_dir);
-	return 0;
-}
-
-/*
- * Reading the pmu event aliases definition, which should be located at:
- * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
- */
-static int pmu_aliases(struct perf_pmu *pmu, int dirfd, const char *name)
-{
-	int fd;
-
-	fd = perf_pmu__pathname_fd(dirfd, name, "events", O_DIRECTORY);
-	if (fd < 0)
-		return 0;
-
-	/* it'll close the fd */
-	if (pmu_aliases_parse(pmu, fd))
-		return -1;
-
+	close (dir_fd);
+	pmu->sysfs_aliases_loaded = true;
 	return 0;
 }
 
@@ -1017,13 +1022,6 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
 		free(pmu);
 		return NULL;
 	}
-	/*
-	 * Check the aliases first to avoid unnecessary work.
-	 */
-	if (pmu_aliases(pmu, dirfd, name)) {
-		free(pmu);
-		return NULL;
-	}
 	pmu->is_core = is_pmu_core(name);
 	pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core);
 
@@ -1438,7 +1436,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 		return NULL;
 	}
 
-	alias = perf_pmu__find_alias(pmu, name);
+	alias = perf_pmu__find_alias(pmu, name, /*load=*/ true);
 	if (alias || pmu->cpu_aliases_added)
 		return alias;
 
@@ -1447,7 +1445,7 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 	    pmu_events_table__find_event(pmu->events_table, pmu, name,
 				         pmu_add_cpu_aliases_map_callback,
 				         pmu) == 0) {
-		alias = perf_pmu__find_alias(pmu, name);
+		alias = perf_pmu__find_alias(pmu, name, /*load=*/ false);
 	}
 	return alias;
 }
@@ -1620,7 +1618,7 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu)
 
 bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
 {
-	if (perf_pmu__find_alias(pmu, name) != NULL)
+	if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL)
 		return true;
 	if (pmu->cpu_aliases_added || !pmu->events_table)
 		return false;
@@ -1629,7 +1627,12 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
 
 size_t perf_pmu__num_events(struct perf_pmu *pmu)
 {
-	size_t nr = pmu->sysfs_aliases;
+	size_t nr;
+
+	if (!pmu->sysfs_aliases_loaded)
+		pmu_aliases_parse(pmu);
+
+	nr = pmu->sysfs_aliases;
 
 	if (pmu->cpu_aliases_added)
 		 nr += pmu->loaded_json_aliases;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 288d2908382a..bae0de3ed7a5 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -122,6 +122,8 @@ struct perf_pmu {
 	uint32_t sysfs_aliases;
 	/** @sysfs_aliases: Number of json event aliases loaded. */
 	uint32_t loaded_json_aliases;
+	/** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */
+	bool sysfs_aliases_loaded;
 	/**
 	 * @cpu_aliases_added: Have all json events table entries for the PMU
 	 * been added?
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 17/18] perf jevents: Sort strings in the big C string to reduce faults
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (15 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 16/18] perf pmu: Lazily load sysfs aliases Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24  4:13 ` [PATCH v2 18/18] perf jevents: Don't append Unit to desc Ian Rogers
  2023-08-24 14:52 ` [PATCH v2 00/18] Lazily load PMU data Arnaldo Carvalho de Melo
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Sort the strings within the big C string based on whether they were
for a metric and then by when they were added. This helps group
related strings and reduce minor faults by approximately 10 in 1740,
about 0.57%.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/pmu-events/jevents.py | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index 01335a452e70..e5bce57f5688 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -113,13 +113,24 @@ class BigCString:
   strings: Set[str]
   big_string: Sequence[str]
   offsets: Dict[str, int]
+  insert_number: int
+  insert_point: Dict[str, int]
+  metrics: Set[str]
 
   def __init__(self):
     self.strings = set()
+    self.insert_number = 0;
+    self.insert_point = {}
+    self.metrics = set()
 
-  def add(self, s: str) -> None:
+  def add(self, s: str, metric: bool) -> None:
     """Called to add to the big string."""
-    self.strings.add(s)
+    if s not in self.strings:
+      self.strings.add(s)
+      self.insert_point[s] = self.insert_number
+      self.insert_number += 1
+      if metric:
+        self.metrics.add(s)
 
   def compute(self) -> None:
     """Called once all strings are added to compute the string and offsets."""
@@ -160,8 +171,11 @@ class BigCString:
     self.big_string = []
     self.offsets = {}
 
+    def string_cmp_key(s: str) -> Tuple[bool, int, str]:
+      return (s in self.metrics, self.insert_point[s], s)
+
     # Emit all strings that aren't folded in a sorted manner.
-    for s in sorted(self.strings):
+    for s in sorted(self.strings, key=string_cmp_key):
       if s not in folded_strings:
         self.offsets[s] = big_string_offset
         self.big_string.append(f'/* offset={big_string_offset} */ "')
@@ -574,19 +588,20 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
       assert len(mgroup) > 1, parents
       description = f"{metricgroup_descriptions[mgroup]}\\000"
       mgroup = f"{mgroup}\\000"
-      _bcs.add(mgroup)
-      _bcs.add(description)
+      _bcs.add(mgroup, metric=True)
+      _bcs.add(description, metric=True)
       _metricgroups[mgroup] = description
     return
 
   topic = get_topic(item.name)
   for event in read_json_events(item.path, topic):
     pmu_name = f"{event.pmu}\\000"
-    _bcs.add(pmu_name)
     if event.name:
-      _bcs.add(event.build_c_string(metric=False))
+      _bcs.add(pmu_name, metric=False)
+      _bcs.add(event.build_c_string(metric=False), metric=False)
     if event.metric_name:
-      _bcs.add(event.build_c_string(metric=True))
+      _bcs.add(pmu_name, metric=True)
+      _bcs.add(event.build_c_string(metric=True), metric=True)
 
 def process_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
   """Process a JSON file during the main walk."""
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH v2 18/18] perf jevents: Don't append Unit to desc
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (16 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 17/18] perf jevents: Sort strings in the big C string to reduce faults Ian Rogers
@ 2023-08-24  4:13 ` Ian Rogers
  2023-08-24 14:52 ` [PATCH v2 00/18] Lazily load PMU data Arnaldo Carvalho de Melo
  18 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24  4:13 UTC (permalink / raw)
  To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, James Clark, Kan Liang, John Garry,
	Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

Unit with the PMU name is appended to desc in jevents.py, but on
hybrid platforms it causes the desc to differ from the regular
non-hybrid system with a PMU of 'cpu'. Having differing descs means
the events don't deduplicate. To make the perf list output not differ,
append the Unit on again in the perf list printing code.

On x86 reduces the binary size by 409,600 bytes or about 4%.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/builtin-list.c        | 13 ++++++++++++-
 tools/perf/pmu-events/jevents.py |  7 -------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 7fec2cca759f..d8b9f606e734 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -145,9 +145,20 @@ static void default_print_event(void *ps, const char *pmu_name, const char *topi
 		putchar('\n');
 
 	if (desc && print_state->desc) {
+		char *desc_with_unit = NULL;
+		int desc_len = -1;
+
+		if (pmu_name && strcmp(pmu_name, "cpu")) {
+			desc_len = strlen(desc);
+			desc_len = asprintf(&desc_with_unit,
+					    desc[desc_len - 1] != '.'
+					      ? "%s. Unit: %s" : "%s Unit: %s",
+					    desc, pmu_name);
+		}
 		printf("%*s", 8, "[");
-		wordwrap(desc, 8, pager_get_columns(), 0);
+		wordwrap(desc_len > 0 ? desc_with_unit : desc, 8, pager_get_columns(), 0);
 		printf("]\n");
+		free(desc_with_unit);
 	}
 	long_desc = long_desc ?: desc;
 	if (long_desc && print_state->long_desc) {
diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
index e5bce57f5688..712f80d7d071 100755
--- a/tools/perf/pmu-events/jevents.py
+++ b/tools/perf/pmu-events/jevents.py
@@ -357,13 +357,6 @@ class JsonEvent:
       self.desc += extra_desc
     if self.long_desc and extra_desc:
       self.long_desc += extra_desc
-    if self.pmu and self.pmu != 'cpu':
-      if not self.desc:
-        self.desc = 'Unit: ' + self.pmu
-      else:
-        if not self.desc.endswith('. '):
-          self.desc += '. '
-      self.desc += 'Unit: ' + self.pmu
     if arch_std:
       if arch_std.lower() in _arch_std_events:
         event = _arch_std_events[arch_std.lower()].event
-- 
2.42.0.rc1.204.g551eb34607-goog


^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-24  4:13 ` [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs Ian Rogers
@ 2023-08-24 13:59   ` Arnaldo Carvalho de Melo
  2023-08-24 17:31     ` Ian Rogers
  2023-08-25  8:19     ` Thomas Richter
  0 siblings, 2 replies; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-24 13:59 UTC (permalink / raw)
  To: Ian Rogers, Thomas Richter
  Cc: Heiko Carstens, Sumanth Korikkar, Sven Schnelle, Vasily Gorbik,
	Peter Zijlstra, Ingo Molnar, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Adrian Hunter, James Clark, Kan Liang,
	John Garry, Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring,
	Gaosheng Cui, linux-perf-users, linux-kernel

Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> Rather than scanning all PMUs for a counter name, scan the PMU
> associated with the evsel of the sample. This is done to remove a
> dependence on pmu-events.h.

I'm applying this one, and CCing the S/390 developers so that they can
try this and maybe provide an Acked-by/Tested-by,

- Arnaldo
 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/util/s390-sample-raw.c | 50 ++++++++++++++++---------------
>  1 file changed, 26 insertions(+), 24 deletions(-)
> 
> diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c
> index 91330c874170..dc1ed3e95d4d 100644
> --- a/tools/perf/util/s390-sample-raw.c
> +++ b/tools/perf/util/s390-sample-raw.c
> @@ -27,7 +27,7 @@
>  #include "color.h"
>  #include "sample-raw.h"
>  #include "s390-cpumcf-kernel.h"
> -#include "pmu-events/pmu-events.h"
> +#include "util/pmu.h"
>  #include "util/sample.h"
>  
>  static size_t ctrset_size(struct cf_ctrset_entry *set)
> @@ -132,56 +132,57 @@ static int get_counterset_start(int setnr)
>  
>  struct get_counter_name_data {
>  	int wanted;
> -	const char *result;
> +	char *result;
>  };
>  
> -static int get_counter_name_callback(const struct pmu_event *evp,
> -				     const struct pmu_events_table *table __maybe_unused,
> -				     void *vdata)
> +static int get_counter_name_callback(void *vdata, struct pmu_event_info *info)
>  {
>  	struct get_counter_name_data *data = vdata;
>  	int rc, event_nr;
> +	const char *event_str;
>  
> -	if (evp->name == NULL || evp->event == NULL)
> +	if (info->str == NULL)
>  		return 0;
> -	rc = sscanf(evp->event, "event=%x", &event_nr);
> +
> +	event_str = strstr(info->str, "event=");
> +	if (!event_str)
> +		return 0;
> +
> +	rc = sscanf(event_str, "event=%x", &event_nr);
>  	if (rc == 1 && event_nr == data->wanted) {
> -		data->result = evp->name;
> +		data->result = strdup(info->name);
>  		return 1; /* Terminate the search. */
>  	}
>  	return 0;
>  }
>  
> -/* Scan the PMU table and extract the logical name of a counter from the
> - * PMU events table. Input is the counter set and counter number with in the
> - * set. Construct the event number and use this as key. If they match return
> - * the name of this counter.
> +/* Scan the PMU and extract the logical name of a counter from the event. Input
> + * is the counter set and counter number with in the set. Construct the event
> + * number and use this as key. If they match return the name of this counter.
>   * If no match is found a NULL pointer is returned.
>   */
> -static const char *get_counter_name(int set, int nr, const struct pmu_events_table *table)
> +static char *get_counter_name(int set, int nr, struct perf_pmu *pmu)
>  {
>  	struct get_counter_name_data data = {
>  		.wanted = get_counterset_start(set) + nr,
>  		.result = NULL,
>  	};
>  
> -	if (!table)
> +	if (!pmu)
>  		return NULL;
>  
> -	pmu_events_table__for_each_event(table, get_counter_name_callback, &data);
> +	perf_pmu__for_each_event(pmu, &data, get_counter_name_callback);
>  	return data.result;
>  }
>  
> -static void s390_cpumcfdg_dump(struct perf_sample *sample)
> +static void s390_cpumcfdg_dump(struct perf_pmu *pmu, struct perf_sample *sample)
>  {
>  	size_t i, len = sample->raw_size, offset = 0;
>  	unsigned char *buf = sample->raw_data;
>  	const char *color = PERF_COLOR_BLUE;
>  	struct cf_ctrset_entry *cep, ce;
> -	const struct pmu_events_table *table;
>  	u64 *p;
>  
> -	table = pmu_events_table__find();
>  	while (offset < len) {
>  		cep = (struct cf_ctrset_entry *)(buf + offset);
>  
> @@ -199,11 +200,12 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample)
>  		color_fprintf(stdout, color, "    [%#08zx] Counterset:%d"
>  			      " Counters:%d\n", offset, ce.set, ce.ctr);
>  		for (i = 0, p = (u64 *)(cep + 1); i < ce.ctr; ++i, ++p) {
> -			const char *ev_name = get_counter_name(ce.set, i, table);
> +			char *ev_name = get_counter_name(ce.set, i, pmu);
>  
>  			color_fprintf(stdout, color,
>  				      "\tCounter:%03d %s Value:%#018lx\n", i,
>  				      ev_name ?: "<unknown>", be64_to_cpu(*p));
> +			free(ev_name);
>  		}
>  		offset += ctrset_size(&ce);
>  	}
> @@ -216,14 +218,14 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample)
>   */
>  void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, struct perf_sample *sample)
>  {
> -	struct evsel *ev_bc000;
> +	struct evsel *evsel;
>  
>  	if (event->header.type != PERF_RECORD_SAMPLE)
>  		return;
>  
> -	ev_bc000 = evlist__event2evsel(evlist, event);
> -	if (ev_bc000 == NULL ||
> -	    ev_bc000->core.attr.config != PERF_EVENT_CPUM_CF_DIAG)
> +	evsel = evlist__event2evsel(evlist, event);
> +	if (evsel == NULL ||
> +	    evsel->core.attr.config != PERF_EVENT_CPUM_CF_DIAG)
>  		return;
>  
>  	/* Display raw data on screen */
> @@ -231,5 +233,5 @@ void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, str
>  		pr_err("Invalid counter set data encountered\n");
>  		return;
>  	}
> -	s390_cpumcfdg_dump(sample);
> +	s390_cpumcfdg_dump(evsel->pmu, sample);
>  }
> -- 
> 2.42.0.rc1.204.g551eb34607-goog
> 

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 00/18] Lazily load PMU data
  2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
                   ` (17 preceding siblings ...)
  2023-08-24  4:13 ` [PATCH v2 18/18] perf jevents: Don't append Unit to desc Ian Rogers
@ 2023-08-24 14:52 ` Arnaldo Carvalho de Melo
  2023-08-24 18:01   ` Ian Rogers
  18 siblings, 1 reply; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-24 14:52 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Adrian Hunter, James Clark, Kan Liang,
	John Garry, Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring,
	Gaosheng Cui, linux-perf-users, linux-kernel

Em Wed, Aug 23, 2023 at 09:13:12PM -0700, Ian Rogers escreveu:
> Lazily load PMU data both from sysfs and json files. Reorganize
> json data to be more PMU oriented to facilitate this, for
> example, json data is now sorted into arrays for their PMU.
> 
> In refactoring the code some changes were made to get rid of maximum
> encoding sizes for events (256 bytes), with input files being directly
> passed to the lex generated code. There is also a small event parse
> error message improvement.
> 
> Some results from an Intel tigerlake laptop running Debian:
> 
> Binary size reduction of 5.3% or 552,864 bytes because the PMU
> name no longer appears in the string or desc field.
> 
> stat -e cpu/cycles/ minor faults reduced from 1733 to 1667, open calls reduced
> from 171 to 94.
> 
> stat default minor faults reduced from 1805 to 1717, open calls reduced
> from 654 to 343.
> 
> Average PMU scanning reduced from 4720.641usec to 2927.293usec.
> Average core PMU scanning reduced from 1004.658usec to 232.668usec
> (4.3x faster).
> 
> v2: Add error path for failing strdup when allocating a format,
>     suggested by Arnaldo. Rebased on top of tmp.perf-tools-next
>     removing 8 patches. Added "perf jevents: Don't append Unit to
>     desc" to save yet more encoding json event space.

So this is failing here:

[acme@quaco ~]$ perf test 10
 10: PMU events                                 :
 10.1: PMU event table sanity                           : FAILED!
 10.2: PMU event map aliases                            : FAILED!
 10.3: Parsing of PMU event table metrics               : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs: Ok
 10.5: Parsing of metric thresholds with fake PMUs      : Ok
[acme@quaco ~]$

[root@quaco ~]# grep -m1 "model name" /proc/cpuinfo
model name	: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
[root@quaco ~]# 


[root@quaco ~]# perf test -vv -F 10 |& head -40
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        :
--- start ---
testing event table bp_l1_btb_correct: pass
testing event table bp_l2_btb_correct: pass
testing event table dispatch_blocked.any: pass
testing event table eist_trans: pass
testing event table l3_cache_rd: pass
testing event table segment_reg_loads.any: pass
testing event e1 uncore_hisi_ddrc.flux_wcmd: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc


Strange:

        if (!is_same(e1->desc, e2->desc)) {
                pr_debug2("testing event e1 %s: mismatched desc, %s vs %s\n",
                          e1->name, e1->desc, e2->desc);
                return -1;
        }

Adding "" around those descs:

testing event e1 uncore_hisi_ddrc.flux_wcmd: mismatched desc, "DDRC write commands" vs "DDRC write commands. Unit: hisi_sccl,ddrc"

I see, its the last patch, removing it the tests passes, please take a
look at tmp.perf-tools-next

- Arnaldo



---- end ----
PMU events subtest 1: FAILED!
 10.2: PMU event map aliases                                         :
--- start ---
Using CPUID GenuineIntel-6-8E-A
testing aliases core PMU cpu: matched event bp_l1_btb_correct
testing aliases core PMU cpu: matched event bp_l2_btb_correct
testing aliases core PMU cpu: matched event segment_reg_loads.any
testing aliases core PMU cpu: matched event dispatch_blocked.any
testing aliases core PMU cpu: matched event eist_trans
testing aliases core PMU cpu: matched event l3_cache_rd
testing core PMU cpu aliases: pass
testing aliases PMU hisi_sccl1_ddrc2: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc
testing aliases uncore PMU hisi_sccl1_ddrc2: could not match alias uncore_hisi_ddrc.flux_wcmd
---- end ----
PMU events subtest 2: FAILED!
 10.3: Parsing of PMU event table metrics                            :
--- start ---
Found metric 'CPI'
metric expr 1 / IPC for CPI
parsing metric: 1 / IPC
metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC
parsing metric: inst_retired.any / cpu_clk_unhalted.thread
found event inst_retired.any
found event cpu_clk_unhalted.thread
Parsing metric events '{inst_retired.any/metric-id=inst_retired.any/,cpu_clk_unhalted.thread/metric-id=cpu_clk_unhalted.thread/}:W'
Attempting to add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
After aliases, add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
Attempting to add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
After aliases, add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
[root@quaco ~]#

Trying on a AMD 5950x:

[root@five ~]# perf test -F -vv 10 |& head -40
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        :
--- start ---
testing event table bp_l1_btb_correct: pass
testing event table bp_l2_btb_correct: pass
testing event table dispatch_blocked.any: pass
testing event table eist_trans: pass
testing event table l3_cache_rd: pass
testing event table segment_reg_loads.any: pass
testing event e1 uncore_hisi_ddrc.flux_wcmd: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc
---- end ----
PMU events subtest 1: FAILED!
 10.2: PMU event map aliases                                         :
--- start ---
Using CPUID AuthenticAMD-25-21-0
testing aliases core PMU cpu: matched event bp_l1_btb_correct
testing aliases core PMU cpu: matched event bp_l2_btb_correct
testing aliases core PMU cpu: matched event segment_reg_loads.any
testing aliases core PMU cpu: matched event dispatch_blocked.any
testing aliases core PMU cpu: matched event eist_trans
testing aliases core PMU cpu: matched event l3_cache_rd
testing core PMU cpu aliases: pass
testing aliases PMU hisi_sccl1_ddrc2: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc
testing aliases uncore PMU hisi_sccl1_ddrc2: could not match alias uncore_hisi_ddrc.flux_wcmd
---- end ----
PMU events subtest 2: FAILED!
 10.3: Parsing of PMU event table metrics                            :
--- start ---
Found metric 'CPI'
metric expr 1 / IPC for CPI
parsing metric: 1 / IPC
metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC
parsing metric: inst_retired.any / cpu_clk_unhalted.thread
found event inst_retired.any
found event cpu_clk_unhalted.thread
Parsing metric events '{inst_retired.any/metric-id=inst_retired.any/,cpu_clk_unhalted.thread/metric-id=cpu_clk_unhalted.thread/}:W'
Attempting to add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
After aliases, add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
Attempting to add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
After aliases, add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
[root@five ~]#

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-24 13:59   ` Arnaldo Carvalho de Melo
@ 2023-08-24 17:31     ` Ian Rogers
  2023-08-25  8:19     ` Thomas Richter
  1 sibling, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24 17:31 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Thomas Richter, Heiko Carstens, Sumanth Korikkar, Sven Schnelle,
	Vasily Gorbik, Peter Zijlstra, Ingo Molnar, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Namhyung Kim, Adrian Hunter,
	James Clark, Kan Liang, John Garry, Kajol Jain, Jing Zhang,
	Ravi Bangoria, Rob Herring, Gaosheng Cui, linux-perf-users,
	linux-kernel

On Thu, Aug 24, 2023 at 7:00 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> > Rather than scanning all PMUs for a counter name, scan the PMU
> > associated with the evsel of the sample. This is done to remove a
> > dependence on pmu-events.h.
>
> I'm applying this one, and CCing the S/390 developers so that they can
> try this and maybe provide an Acked-by/Tested-by,

Thanks Arnaldo! You're right that I wasn't able to test this s390
change on an s390.

Ian

> - Arnaldo
>
> > Signed-off-by: Ian Rogers <irogers@google.com>
> > ---
> >  tools/perf/util/s390-sample-raw.c | 50 ++++++++++++++++---------------
> >  1 file changed, 26 insertions(+), 24 deletions(-)
> >
> > diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c
> > index 91330c874170..dc1ed3e95d4d 100644
> > --- a/tools/perf/util/s390-sample-raw.c
> > +++ b/tools/perf/util/s390-sample-raw.c
> > @@ -27,7 +27,7 @@
> >  #include "color.h"
> >  #include "sample-raw.h"
> >  #include "s390-cpumcf-kernel.h"
> > -#include "pmu-events/pmu-events.h"
> > +#include "util/pmu.h"
> >  #include "util/sample.h"
> >
> >  static size_t ctrset_size(struct cf_ctrset_entry *set)
> > @@ -132,56 +132,57 @@ static int get_counterset_start(int setnr)
> >
> >  struct get_counter_name_data {
> >       int wanted;
> > -     const char *result;
> > +     char *result;
> >  };
> >
> > -static int get_counter_name_callback(const struct pmu_event *evp,
> > -                                  const struct pmu_events_table *table __maybe_unused,
> > -                                  void *vdata)
> > +static int get_counter_name_callback(void *vdata, struct pmu_event_info *info)
> >  {
> >       struct get_counter_name_data *data = vdata;
> >       int rc, event_nr;
> > +     const char *event_str;
> >
> > -     if (evp->name == NULL || evp->event == NULL)
> > +     if (info->str == NULL)
> >               return 0;
> > -     rc = sscanf(evp->event, "event=%x", &event_nr);
> > +
> > +     event_str = strstr(info->str, "event=");
> > +     if (!event_str)
> > +             return 0;
> > +
> > +     rc = sscanf(event_str, "event=%x", &event_nr);
> >       if (rc == 1 && event_nr == data->wanted) {
> > -             data->result = evp->name;
> > +             data->result = strdup(info->name);
> >               return 1; /* Terminate the search. */
> >       }
> >       return 0;
> >  }
> >
> > -/* Scan the PMU table and extract the logical name of a counter from the
> > - * PMU events table. Input is the counter set and counter number with in the
> > - * set. Construct the event number and use this as key. If they match return
> > - * the name of this counter.
> > +/* Scan the PMU and extract the logical name of a counter from the event. Input
> > + * is the counter set and counter number with in the set. Construct the event
> > + * number and use this as key. If they match return the name of this counter.
> >   * If no match is found a NULL pointer is returned.
> >   */
> > -static const char *get_counter_name(int set, int nr, const struct pmu_events_table *table)
> > +static char *get_counter_name(int set, int nr, struct perf_pmu *pmu)
> >  {
> >       struct get_counter_name_data data = {
> >               .wanted = get_counterset_start(set) + nr,
> >               .result = NULL,
> >       };
> >
> > -     if (!table)
> > +     if (!pmu)
> >               return NULL;
> >
> > -     pmu_events_table__for_each_event(table, get_counter_name_callback, &data);
> > +     perf_pmu__for_each_event(pmu, &data, get_counter_name_callback);
> >       return data.result;
> >  }
> >
> > -static void s390_cpumcfdg_dump(struct perf_sample *sample)
> > +static void s390_cpumcfdg_dump(struct perf_pmu *pmu, struct perf_sample *sample)
> >  {
> >       size_t i, len = sample->raw_size, offset = 0;
> >       unsigned char *buf = sample->raw_data;
> >       const char *color = PERF_COLOR_BLUE;
> >       struct cf_ctrset_entry *cep, ce;
> > -     const struct pmu_events_table *table;
> >       u64 *p;
> >
> > -     table = pmu_events_table__find();
> >       while (offset < len) {
> >               cep = (struct cf_ctrset_entry *)(buf + offset);
> >
> > @@ -199,11 +200,12 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample)
> >               color_fprintf(stdout, color, "    [%#08zx] Counterset:%d"
> >                             " Counters:%d\n", offset, ce.set, ce.ctr);
> >               for (i = 0, p = (u64 *)(cep + 1); i < ce.ctr; ++i, ++p) {
> > -                     const char *ev_name = get_counter_name(ce.set, i, table);
> > +                     char *ev_name = get_counter_name(ce.set, i, pmu);
> >
> >                       color_fprintf(stdout, color,
> >                                     "\tCounter:%03d %s Value:%#018lx\n", i,
> >                                     ev_name ?: "<unknown>", be64_to_cpu(*p));
> > +                     free(ev_name);
> >               }
> >               offset += ctrset_size(&ce);
> >       }
> > @@ -216,14 +218,14 @@ static void s390_cpumcfdg_dump(struct perf_sample *sample)
> >   */
> >  void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, struct perf_sample *sample)
> >  {
> > -     struct evsel *ev_bc000;
> > +     struct evsel *evsel;
> >
> >       if (event->header.type != PERF_RECORD_SAMPLE)
> >               return;
> >
> > -     ev_bc000 = evlist__event2evsel(evlist, event);
> > -     if (ev_bc000 == NULL ||
> > -         ev_bc000->core.attr.config != PERF_EVENT_CPUM_CF_DIAG)
> > +     evsel = evlist__event2evsel(evlist, event);
> > +     if (evsel == NULL ||
> > +         evsel->core.attr.config != PERF_EVENT_CPUM_CF_DIAG)
> >               return;
> >
> >       /* Display raw data on screen */
> > @@ -231,5 +233,5 @@ void evlist__s390_sample_raw(struct evlist *evlist, union perf_event *event, str
> >               pr_err("Invalid counter set data encountered\n");
> >               return;
> >       }
> > -     s390_cpumcfdg_dump(sample);
> > +     s390_cpumcfdg_dump(evsel->pmu, sample);
> >  }
> > --
> > 2.42.0.rc1.204.g551eb34607-goog
> >
>
> --
>
> - Arnaldo

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 00/18] Lazily load PMU data
  2023-08-24 14:52 ` [PATCH v2 00/18] Lazily load PMU data Arnaldo Carvalho de Melo
@ 2023-08-24 18:01   ` Ian Rogers
  0 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-24 18:01 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Adrian Hunter, James Clark, Kan Liang,
	John Garry, Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring,
	Gaosheng Cui, linux-perf-users, linux-kernel

On Thu, Aug 24, 2023 at 7:52 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> Em Wed, Aug 23, 2023 at 09:13:12PM -0700, Ian Rogers escreveu:
> > Lazily load PMU data both from sysfs and json files. Reorganize
> > json data to be more PMU oriented to facilitate this, for
> > example, json data is now sorted into arrays for their PMU.
> >
> > In refactoring the code some changes were made to get rid of maximum
> > encoding sizes for events (256 bytes), with input files being directly
> > passed to the lex generated code. There is also a small event parse
> > error message improvement.
> >
> > Some results from an Intel tigerlake laptop running Debian:
> >
> > Binary size reduction of 5.3% or 552,864 bytes because the PMU
> > name no longer appears in the string or desc field.
> >
> > stat -e cpu/cycles/ minor faults reduced from 1733 to 1667, open calls reduced
> > from 171 to 94.
> >
> > stat default minor faults reduced from 1805 to 1717, open calls reduced
> > from 654 to 343.
> >
> > Average PMU scanning reduced from 4720.641usec to 2927.293usec.
> > Average core PMU scanning reduced from 1004.658usec to 232.668usec
> > (4.3x faster).
> >
> > v2: Add error path for failing strdup when allocating a format,
> >     suggested by Arnaldo. Rebased on top of tmp.perf-tools-next
> >     removing 8 patches. Added "perf jevents: Don't append Unit to
> >     desc" to save yet more encoding json event space.
>
> So this is failing here:
>
> [acme@quaco ~]$ perf test 10
>  10: PMU events                                 :
>  10.1: PMU event table sanity                           : FAILED!
>  10.2: PMU event map aliases                            : FAILED!
>  10.3: Parsing of PMU event table metrics               : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs: Ok
>  10.5: Parsing of metric thresholds with fake PMUs      : Ok
> [acme@quaco ~]$
>
> [root@quaco ~]# grep -m1 "model name" /proc/cpuinfo
> model name      : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
> [root@quaco ~]#
>
>
> [root@quaco ~]# perf test -vv -F 10 |& head -40
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        :
> --- start ---
> testing event table bp_l1_btb_correct: pass
> testing event table bp_l2_btb_correct: pass
> testing event table dispatch_blocked.any: pass
> testing event table eist_trans: pass
> testing event table l3_cache_rd: pass
> testing event table segment_reg_loads.any: pass
> testing event e1 uncore_hisi_ddrc.flux_wcmd: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc
>
>
> Strange:
>
>         if (!is_same(e1->desc, e2->desc)) {
>                 pr_debug2("testing event e1 %s: mismatched desc, %s vs %s\n",
>                           e1->name, e1->desc, e2->desc);
>                 return -1;
>         }
>
> Adding "" around those descs:
>
> testing event e1 uncore_hisi_ddrc.flux_wcmd: mismatched desc, "DDRC write commands" vs "DDRC write commands. Unit: hisi_sccl,ddrc"
>
> I see, its the last patch, removing it the tests passes, please take a
> look at tmp.perf-tools-next
>
> - Arnaldo

Thanks, I'll address the issue (hardcoded assumption on jevents.py
output) and resend the patch.

Ian

> ---- end ----
> PMU events subtest 1: FAILED!
>  10.2: PMU event map aliases                                         :
> --- start ---
> Using CPUID GenuineIntel-6-8E-A
> testing aliases core PMU cpu: matched event bp_l1_btb_correct
> testing aliases core PMU cpu: matched event bp_l2_btb_correct
> testing aliases core PMU cpu: matched event segment_reg_loads.any
> testing aliases core PMU cpu: matched event dispatch_blocked.any
> testing aliases core PMU cpu: matched event eist_trans
> testing aliases core PMU cpu: matched event l3_cache_rd
> testing core PMU cpu aliases: pass
> testing aliases PMU hisi_sccl1_ddrc2: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc
> testing aliases uncore PMU hisi_sccl1_ddrc2: could not match alias uncore_hisi_ddrc.flux_wcmd
> ---- end ----
> PMU events subtest 2: FAILED!
>  10.3: Parsing of PMU event table metrics                            :
> --- start ---
> Found metric 'CPI'
> metric expr 1 / IPC for CPI
> parsing metric: 1 / IPC
> metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC
> parsing metric: inst_retired.any / cpu_clk_unhalted.thread
> found event inst_retired.any
> found event cpu_clk_unhalted.thread
> Parsing metric events '{inst_retired.any/metric-id=inst_retired.any/,cpu_clk_unhalted.thread/metric-id=cpu_clk_unhalted.thread/}:W'
> Attempting to add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
> After aliases, add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
> Attempting to add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
> After aliases, add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
> [root@quaco ~]#
>
> Trying on a AMD 5950x:
>
> [root@five ~]# perf test -F -vv 10 |& head -40
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        :
> --- start ---
> testing event table bp_l1_btb_correct: pass
> testing event table bp_l2_btb_correct: pass
> testing event table dispatch_blocked.any: pass
> testing event table eist_trans: pass
> testing event table l3_cache_rd: pass
> testing event table segment_reg_loads.any: pass
> testing event e1 uncore_hisi_ddrc.flux_wcmd: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc
> ---- end ----
> PMU events subtest 1: FAILED!
>  10.2: PMU event map aliases                                         :
> --- start ---
> Using CPUID AuthenticAMD-25-21-0
> testing aliases core PMU cpu: matched event bp_l1_btb_correct
> testing aliases core PMU cpu: matched event bp_l2_btb_correct
> testing aliases core PMU cpu: matched event segment_reg_loads.any
> testing aliases core PMU cpu: matched event dispatch_blocked.any
> testing aliases core PMU cpu: matched event eist_trans
> testing aliases core PMU cpu: matched event l3_cache_rd
> testing core PMU cpu aliases: pass
> testing aliases PMU hisi_sccl1_ddrc2: mismatched desc, DDRC write commands vs DDRC write commands. Unit: hisi_sccl,ddrc
> testing aliases uncore PMU hisi_sccl1_ddrc2: could not match alias uncore_hisi_ddrc.flux_wcmd
> ---- end ----
> PMU events subtest 2: FAILED!
>  10.3: Parsing of PMU event table metrics                            :
> --- start ---
> Found metric 'CPI'
> metric expr 1 / IPC for CPI
> parsing metric: 1 / IPC
> metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC
> parsing metric: inst_retired.any / cpu_clk_unhalted.thread
> found event inst_retired.any
> found event cpu_clk_unhalted.thread
> Parsing metric events '{inst_retired.any/metric-id=inst_retired.any/,cpu_clk_unhalted.thread/metric-id=cpu_clk_unhalted.thread/}:W'
> Attempting to add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
> After aliases, add event pmu 'inst_retired.any' with '(null),' that may result in non-fatal errors
> Attempting to add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
> After aliases, add event pmu 'cpu_clk_unhalted.thread' with '(null),' that may result in non-fatal errors
> [root@five ~]#

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-24 13:59   ` Arnaldo Carvalho de Melo
  2023-08-24 17:31     ` Ian Rogers
@ 2023-08-25  8:19     ` Thomas Richter
  2023-08-25 13:14       ` Ian Rogers
  1 sibling, 1 reply; 39+ messages in thread
From: Thomas Richter @ 2023-08-25  8:19 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Ian Rogers
  Cc: Heiko Carstens, Sumanth Korikkar, Sven Schnelle, Vasily Gorbik,
	Peter Zijlstra, Ingo Molnar, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Adrian Hunter, James Clark, Kan Liang,
	John Garry, Kajol Jain, Jing Zhang, Ravi Bangoria, Rob Herring,
	Gaosheng Cui, linux-perf-users, linux-kernel

On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
>> Rather than scanning all PMUs for a counter name, scan the PMU
>> associated with the evsel of the sample. This is done to remove a
>> dependence on pmu-events.h.
> 
> I'm applying this one, and CCing the S/390 developers so that they can
> try this and maybe provide an Acked-by/Tested-by,
> 
> - Arnaldo


Arnaldo,

I have downloaded this patch set of 18 patches (using b4), but they do not
apply on my git tree.

Which git branch do I have to use to test this. Thanks a lot.

-- 
Thomas Richter, Dept 3303, IBM s390 Linux Development, Boeblingen, Germany
--
Vorsitzender des Aufsichtsrats: Gregor Pillen
Geschäftsführung: David Faller
Sitz der Gesellschaft: Böblingen / Registergericht: Amtsgericht Stuttgart, HRB 243294


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-25  8:19     ` Thomas Richter
@ 2023-08-25 13:14       ` Ian Rogers
  2023-08-25 14:39         ` Thomas Richter
  0 siblings, 1 reply; 39+ messages in thread
From: Ian Rogers @ 2023-08-25 13:14 UTC (permalink / raw)
  To: Thomas Richter
  Cc: Arnaldo Carvalho de Melo, Heiko Carstens, Sumanth Korikkar,
	Sven Schnelle, Vasily Gorbik, Peter Zijlstra, Ingo Molnar,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Adrian Hunter, James Clark, Kan Liang, John Garry, Kajol Jain,
	Jing Zhang, Ravi Bangoria, Rob Herring, Gaosheng Cui,
	linux-perf-users, linux-kernel

On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
>
> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> > Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> >> Rather than scanning all PMUs for a counter name, scan the PMU
> >> associated with the evsel of the sample. This is done to remove a
> >> dependence on pmu-events.h.
> >
> > I'm applying this one, and CCing the S/390 developers so that they can
> > try this and maybe provide an Acked-by/Tested-by,
> >
> > - Arnaldo
>
>
> Arnaldo,
>
> I have downloaded this patch set of 18 patches (using b4), but they do not
> apply on my git tree.
>
> Which git branch do I have to use to test this. Thanks a lot.

Hi Thomas,

the changes are in the perf-tools-next tree:
https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/

Thanks,
Ian

> --
> Thomas Richter, Dept 3303, IBM s390 Linux Development, Boeblingen, Germany
> --
> Vorsitzender des Aufsichtsrats: Gregor Pillen
> Geschäftsführung: David Faller
> Sitz der Gesellschaft: Böblingen / Registergericht: Amtsgericht Stuttgart, HRB 243294
>

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-25 13:14       ` Ian Rogers
@ 2023-08-25 14:39         ` Thomas Richter
  2023-08-25 20:56           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 39+ messages in thread
From: Thomas Richter @ 2023-08-25 14:39 UTC (permalink / raw)
  To: Ian Rogers, Sumanth Korikkar
  Cc: Arnaldo Carvalho de Melo, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

On 8/25/23 15:14, Ian Rogers wrote:
> On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
>>
>> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
>>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
>>>> Rather than scanning all PMUs for a counter name, scan the PMU
>>>> associated with the evsel of the sample. This is done to remove a
>>>> dependence on pmu-events.h.
>>>
>>> I'm applying this one, and CCing the S/390 developers so that they can
>>> try this and maybe provide an Acked-by/Tested-by,
>>>
>>> - Arnaldo
>>
>>
>> Arnaldo,
>>
>> I have downloaded this patch set of 18 patches (using b4), but they do not
>> apply on my git tree.
>>
>> Which git branch do I have to use to test this. Thanks a lot.
> 
> Hi Thomas,
> 
> the changes are in the perf-tools-next tree:
> https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
> 
> Thanks,
> Ian
> 


Hi Ian,

thanks for the pointer.

Unfurtunately this patch set fails again on s390.
Here is the test output from the current 6.5.0rc7 kernel:

# ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          : Ok
  6.3: Parsing of given PMU events from sysfs                        : Ok
  6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
  6.5: Parsing of aliased events                                     : Ok
  6.6: Parsing of terms (event modifiers)                            : Ok
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : Ok
 10.3: Parsing of PMU event table metrics                            : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
 95: perf all metricgroups test                                      : Ok
 96: perf all metrics test                                           : Ok
# 

This looks good.

However when I use the check-out from perf-tools-next, I get this output:
# ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          : FAILED!
  6.3: Parsing of given PMU events from sysfs                        : Ok
  6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
  6.5: Parsing of aliased events                                     : FAILED!
  6.6: Parsing of terms (event modifiers)                            : Ok
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : FAILED!
 10.3: Parsing of PMU event table metrics                            : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
 93: perf all metricgroups test                                      : FAILED!
 94: perf all metrics test                                           : FAILED!
# 

So some tests are failing again.

I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
Thanks a lot.

-- 
Thomas Richter, Dept 3303, IBM s390 Linux Development, Boeblingen, Germany
--
Vorsitzender des Aufsichtsrats: Gregor Pillen
Geschäftsführung: David Faller
Sitz der Gesellschaft: Böblingen / Registergericht: Amtsgericht Stuttgart, HRB 243294


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-25 14:39         ` Thomas Richter
@ 2023-08-25 20:56           ` Arnaldo Carvalho de Melo
  2023-08-25 22:56             ` Ian Rogers
  0 siblings, 1 reply; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-25 20:56 UTC (permalink / raw)
  To: Thomas Richter
  Cc: Ian Rogers, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
> On 8/25/23 15:14, Ian Rogers wrote:
> > On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:

> >> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> >>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> >>>> Rather than scanning all PMUs for a counter name, scan the PMU
> >>>> associated with the evsel of the sample. This is done to remove a
> >>>> dependence on pmu-events.h.

> >>> I'm applying this one, and CCing the S/390 developers so that they can
> >>> try this and maybe provide an Acked-by/Tested-by,

> >> I have downloaded this patch set of 18 patches (using b4), but they do not
> >> apply on my git tree.

> >> Which git branch do I have to use to test this. Thanks a lot.

> > the changes are in the perf-tools-next tree:
> > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
 
> Unfurtunately this patch set fails again on s390.
> Here is the test output from the current 6.5.0rc7 kernel:
> 
> # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : Ok
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : Ok
>   6.6: Parsing of terms (event modifiers)                            : Ok
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : Ok
>  10.3: Parsing of PMU event table metrics                            : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>  95: perf all metricgroups test                                      : Ok
>  96: perf all metrics test                                           : Ok
> # 
> 
> This looks good.

Reproduced:

# grep -E vendor_id\|^processor -m2 /proc/cpuinfo
vendor_id       : IBM/S390
processor 0: version = 00,  identification = 1A33E8,  machine = 2964
#
# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          : Ok
  6.3: Parsing of given PMU events from sysfs                        : Ok
  6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
  6.5: Parsing of aliased events                                     : Ok
  6.6: Parsing of terms (event modifiers)                            : Ok
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : Ok
 10.3: Parsing of PMU event table metrics                            : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
 95: perf all metricgroups test                                      : Ok
 96: perf all metrics test                                           : Ok
# perf -v
perf version 6.5.rc7.g6f0edbb833ec
#
 
> However when I use the check-out from perf-tools-next, I get this output:
> # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : FAILED!
>   6.6: Parsing of terms (event modifiers)                            : Ok
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : FAILED!
>  10.3: Parsing of PMU event table metrics                            : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>  93: perf all metricgroups test                                      : FAILED!
>  94: perf all metrics test                                           : FAILED!
> # 
> 
> So some tests are failing again.
> 
> I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
> Thanks a lot.

[root@kernelqe3 linux]# git checkout perf-tools-next
git Switched to branch 'perf-tools-next'
Your branch is up to date with 'perf-tools-next/perf-tools-next'.
[root@kernelqe3 linux]# git log --oneline -5
eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
43803cb16f99 perf scripts python: Add support for input args in gecko script
f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
[root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin

[root@kernelqe3 linux]# perf -v
perf version 6.5.rc5.geeb6b12992c4
[root@kernelqe3 linux]# git log --oneline -1
eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
[root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          : FAILED!
  6.3: Parsing of given PMU events from sysfs                        : Ok
  6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
  6.5: Parsing of aliased events                                     : FAILED!
  6.6: Parsing of terms (event modifiers)                            : Ok
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : FAILED!
 10.3: Parsing of PMU event table metrics                            : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
 93: perf all metricgroups test                                      : FAILED!
 94: perf all metrics test                                           : FAILED!
[root@kernelqe3 linux]#

Bisecting the first problem:

 10.2: PMU event map aliases                                         : FAILED!

make: Leaving directory '/root/git/linux/tools/perf'
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          : Ok
  6.3: Parsing of given PMU events from sysfs                        : Ok
  6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
  6.5: Parsing of aliased events                                     : Ok
  6.6: Parsing of terms (event modifiers)                            : Ok
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : FAILED!
 10.3: Parsing of PMU event table metrics                            : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
 93: perf all metricgroups test                                      : Ok
 94: perf all metrics test                                           : Ok
[root@kernelqe3 linux]# git bisect bad
2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
Author: Ian Rogers <irogers@google.com>
Date:   Wed Aug 23 21:13:16 2023 -0700

    perf jevents: Group events by PMU

    Prior to this change a cpuid would map to a list of events where the PMU
    would be encoded alongside the event information. This change breaks
    apart each group of events so that there is a group per PMU. A new table
    is added with the PMU's name and the list of events, the original table
    now holding an array of these per PMU tables.

    These changes are to make it easier to get per PMU information about
    events, rather than the current approach of scanning all events. The
    perf binary size with BPF skeletons on x86 is reduced by about 1%. The
    unidentified PMU is now always expanded to "cpu".

    Signed-off-by: Ian Rogers <irogers@google.com>
    Cc: Adrian Hunter <adrian.hunter@intel.com>
    Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: James Clark <james.clark@arm.com>
    Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
    Cc: Jiri Olsa <jolsa@kernel.org>
    Cc: John Garry <john.g.garry@oracle.com>
    Cc: Kajol Jain <kjain@linux.ibm.com>
    Cc: Kan Liang <kan.liang@linux.intel.com>
    Cc: Mark Rutland <mark.rutland@arm.com>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Ravi Bangoria <ravi.bangoria@amd.com>
    Cc: Rob Herring <robh@kernel.org>
    Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

 tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
 tools/perf/tests/pmu-events.c    |  30 ++++---
 2 files changed, 154 insertions(+), 57 deletions(-)
[root@kernelqe3 linux]#



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-25 20:56           ` Arnaldo Carvalho de Melo
@ 2023-08-25 22:56             ` Ian Rogers
  2023-08-26  1:38               ` Arnaldo Carvalho de Melo
  2023-08-28 17:44               ` Arnaldo Carvalho de Melo
  0 siblings, 2 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-25 22:56 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
> > On 8/25/23 15:14, Ian Rogers wrote:
> > > On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
>
> > >> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> > >>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> > >>>> Rather than scanning all PMUs for a counter name, scan the PMU
> > >>>> associated with the evsel of the sample. This is done to remove a
> > >>>> dependence on pmu-events.h.
>
> > >>> I'm applying this one, and CCing the S/390 developers so that they can
> > >>> try this and maybe provide an Acked-by/Tested-by,
>
> > >> I have downloaded this patch set of 18 patches (using b4), but they do not
> > >> apply on my git tree.
>
> > >> Which git branch do I have to use to test this. Thanks a lot.
>
> > > the changes are in the perf-tools-next tree:
> > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
>
> > Unfurtunately this patch set fails again on s390.
> > Here is the test output from the current 6.5.0rc7 kernel:
> >
> > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : Ok
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : Ok
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : Ok
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> >  95: perf all metricgroups test                                      : Ok
> >  96: perf all metrics test                                           : Ok
> > #
> >
> > This looks good.
>
> Reproduced:
>
> # grep -E vendor_id\|^processor -m2 /proc/cpuinfo
> vendor_id       : IBM/S390
> processor 0: version = 00,  identification = 1A33E8,  machine = 2964
> #
> # perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : Ok
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : Ok
>   6.6: Parsing of terms (event modifiers)                            : Ok
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : Ok
>  10.3: Parsing of PMU event table metrics                            : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>  95: perf all metricgroups test                                      : Ok
>  96: perf all metrics test                                           : Ok
> # perf -v
> perf version 6.5.rc7.g6f0edbb833ec
> #
>
> > However when I use the check-out from perf-tools-next, I get this output:
> > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : FAILED!
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : FAILED!
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> >  93: perf all metricgroups test                                      : FAILED!
> >  94: perf all metrics test                                           : FAILED!
> > #
> >
> > So some tests are failing again.
> >
> > I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
> > Thanks a lot.
>
> [root@kernelqe3 linux]# git checkout perf-tools-next
> git Switched to branch 'perf-tools-next'
> Your branch is up to date with 'perf-tools-next/perf-tools-next'.
> [root@kernelqe3 linux]# git log --oneline -5
> eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
> 43803cb16f99 perf scripts python: Add support for input args in gecko script
> f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
> 8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
> [root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin
>
> [root@kernelqe3 linux]# perf -v
> perf version 6.5.rc5.geeb6b12992c4
> [root@kernelqe3 linux]# git log --oneline -1
> eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : FAILED!
>   6.6: Parsing of terms (event modifiers)                            : Ok
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : FAILED!
>  10.3: Parsing of PMU event table metrics                            : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>  93: perf all metricgroups test                                      : FAILED!
>  94: perf all metrics test                                           : FAILED!
> [root@kernelqe3 linux]#
>
> Bisecting the first problem:
>
>  10.2: PMU event map aliases                                         : FAILED!
>
> make: Leaving directory '/root/git/linux/tools/perf'
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : Ok
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : Ok
>   6.6: Parsing of terms (event modifiers)                            : Ok
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : FAILED!
>  10.3: Parsing of PMU event table metrics                            : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>  93: perf all metricgroups test                                      : Ok
>  94: perf all metrics test                                           : Ok
> [root@kernelqe3 linux]# git bisect bad
> 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> Author: Ian Rogers <irogers@google.com>
> Date:   Wed Aug 23 21:13:16 2023 -0700
>
>     perf jevents: Group events by PMU
>
>     Prior to this change a cpuid would map to a list of events where the PMU
>     would be encoded alongside the event information. This change breaks
>     apart each group of events so that there is a group per PMU. A new table
>     is added with the PMU's name and the list of events, the original table
>     now holding an array of these per PMU tables.
>
>     These changes are to make it easier to get per PMU information about
>     events, rather than the current approach of scanning all events. The
>     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
>     unidentified PMU is now always expanded to "cpu".
>
>     Signed-off-by: Ian Rogers <irogers@google.com>
>     Cc: Adrian Hunter <adrian.hunter@intel.com>
>     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
>     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
>     Cc: Ingo Molnar <mingo@redhat.com>
>     Cc: James Clark <james.clark@arm.com>
>     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
>     Cc: Jiri Olsa <jolsa@kernel.org>
>     Cc: John Garry <john.g.garry@oracle.com>
>     Cc: Kajol Jain <kjain@linux.ibm.com>
>     Cc: Kan Liang <kan.liang@linux.intel.com>
>     Cc: Mark Rutland <mark.rutland@arm.com>
>     Cc: Namhyung Kim <namhyung@kernel.org>
>     Cc: Peter Zijlstra <peterz@infradead.org>
>     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
>     Cc: Rob Herring <robh@kernel.org>
>     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
>     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
>
>  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
>  tools/perf/tests/pmu-events.c    |  30 ++++---
>  2 files changed, 154 insertions(+), 57 deletions(-)
> [root@kernelqe3 linux]#
>

This change defaulted events without a specified PMU to being for the
PMU 'cpu', so that events in pmu-events.c were associated with a PMU
and we could find per-PMU information easily. The test events have no
PMU and so this has broken s390 where the the PMU should be "cpum_cf".
It has probably also broken x86 hybrid and arm where their default PMU
isn't cpu. I'll work on a fix, but the problem will be limited to the
test.

Thanks,
Ian

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-25 22:56             ` Ian Rogers
@ 2023-08-26  1:38               ` Arnaldo Carvalho de Melo
  2023-08-26  6:28                 ` Ian Rogers
  2023-08-28 17:44               ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-26  1:38 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
> On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > [root@kernelqe3 linux]# git bisect bad
> > 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> > commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> > Author: Ian Rogers <irogers@google.com>
> > Date:   Wed Aug 23 21:13:16 2023 -0700
> >
> >     perf jevents: Group events by PMU
> >
> >     Prior to this change a cpuid would map to a list of events where the PMU
> >     would be encoded alongside the event information. This change breaks
> >     apart each group of events so that there is a group per PMU. A new table
> >     is added with the PMU's name and the list of events, the original table
> >     now holding an array of these per PMU tables.
> >
> >     These changes are to make it easier to get per PMU information about
> >     events, rather than the current approach of scanning all events. The
> >     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> >     unidentified PMU is now always expanded to "cpu".
> >
> >     Signed-off-by: Ian Rogers <irogers@google.com>
> >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> >     Cc: Ingo Molnar <mingo@redhat.com>
> >     Cc: James Clark <james.clark@arm.com>
> >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> >     Cc: Jiri Olsa <jolsa@kernel.org>
> >     Cc: John Garry <john.g.garry@oracle.com>
> >     Cc: Kajol Jain <kjain@linux.ibm.com>
> >     Cc: Kan Liang <kan.liang@linux.intel.com>
> >     Cc: Mark Rutland <mark.rutland@arm.com>
> >     Cc: Namhyung Kim <namhyung@kernel.org>
> >     Cc: Peter Zijlstra <peterz@infradead.org>
> >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> >     Cc: Rob Herring <robh@kernel.org>
> >     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
> >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> >
> >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
> >  tools/perf/tests/pmu-events.c    |  30 ++++---
> >  2 files changed, 154 insertions(+), 57 deletions(-)
> > [root@kernelqe3 linux]#
> 
> This change defaulted events without a specified PMU to being for the
> PMU 'cpu', so that events in pmu-events.c were associated with a PMU
> and we could find per-PMU information easily. The test events have no
> PMU and so this has broken s390 where the the PMU should be "cpum_cf".
> It has probably also broken x86 hybrid and arm where their default PMU
> isn't cpu. I'll work on a fix, but the problem will be limited to the
> test.

Ok, please use tmp.perf-tools-next as the basis for your work, that is
what I have right now.

- Arnaldo

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-26  1:38               ` Arnaldo Carvalho de Melo
@ 2023-08-26  6:28                 ` Ian Rogers
  0 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-26  6:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

On Fri, Aug 25, 2023 at 6:38 PM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
> > On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > > [root@kernelqe3 linux]# git bisect bad
> > > 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> > > commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> > > Author: Ian Rogers <irogers@google.com>
> > > Date:   Wed Aug 23 21:13:16 2023 -0700
> > >
> > >     perf jevents: Group events by PMU
> > >
> > >     Prior to this change a cpuid would map to a list of events where the PMU
> > >     would be encoded alongside the event information. This change breaks
> > >     apart each group of events so that there is a group per PMU. A new table
> > >     is added with the PMU's name and the list of events, the original table
> > >     now holding an array of these per PMU tables.
> > >
> > >     These changes are to make it easier to get per PMU information about
> > >     events, rather than the current approach of scanning all events. The
> > >     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> > >     unidentified PMU is now always expanded to "cpu".
> > >
> > >     Signed-off-by: Ian Rogers <irogers@google.com>
> > >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> > >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> > >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> > >     Cc: Ingo Molnar <mingo@redhat.com>
> > >     Cc: James Clark <james.clark@arm.com>
> > >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> > >     Cc: Jiri Olsa <jolsa@kernel.org>
> > >     Cc: John Garry <john.g.garry@oracle.com>
> > >     Cc: Kajol Jain <kjain@linux.ibm.com>
> > >     Cc: Kan Liang <kan.liang@linux.intel.com>
> > >     Cc: Mark Rutland <mark.rutland@arm.com>
> > >     Cc: Namhyung Kim <namhyung@kernel.org>
> > >     Cc: Peter Zijlstra <peterz@infradead.org>
> > >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> > >     Cc: Rob Herring <robh@kernel.org>
> > >     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
> > >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> > >
> > >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
> > >  tools/perf/tests/pmu-events.c    |  30 ++++---
> > >  2 files changed, 154 insertions(+), 57 deletions(-)
> > > [root@kernelqe3 linux]#
> >
> > This change defaulted events without a specified PMU to being for the
> > PMU 'cpu', so that events in pmu-events.c were associated with a PMU
> > and we could find per-PMU information easily. The test events have no
> > PMU and so this has broken s390 where the the PMU should be "cpum_cf".
> > It has probably also broken x86 hybrid and arm where their default PMU
> > isn't cpu. I'll work on a fix, but the problem will be limited to the
> > test.
>
> Ok, please use tmp.perf-tools-next as the basis for your work, that is
> what I have right now.

Thanks. I repro-ed the PMU events failure on alderlake and the patch I sent:
https://lore.kernel.org/lkml/20230826062203.1058041-1-irogers@google.com/
addressed it. I didn't repro the sysfs issue and so it may be resolved
by this too, but it may be a different issue. There may also be more
issues specific to s390. I'm hopeful the patch fixes them but please
give it a go.

Thanks,
Ian

> - Arnaldo

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-25 22:56             ` Ian Rogers
  2023-08-26  1:38               ` Arnaldo Carvalho de Melo
@ 2023-08-28 17:44               ` Arnaldo Carvalho de Melo
  2023-08-28 17:53                 ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-28 17:44 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
> On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> >
> > Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
> > > On 8/25/23 15:14, Ian Rogers wrote:
> > > > On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
> >
> > > >> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> > > >>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> > > >>>> Rather than scanning all PMUs for a counter name, scan the PMU
> > > >>>> associated with the evsel of the sample. This is done to remove a
> > > >>>> dependence on pmu-events.h.
> >
> > > >>> I'm applying this one, and CCing the S/390 developers so that they can
> > > >>> try this and maybe provide an Acked-by/Tested-by,
> >
> > > >> I have downloaded this patch set of 18 patches (using b4), but they do not
> > > >> apply on my git tree.
> >
> > > >> Which git branch do I have to use to test this. Thanks a lot.
> >
> > > > the changes are in the perf-tools-next tree:
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
> >
> > > Unfurtunately this patch set fails again on s390.
> > > Here is the test output from the current 6.5.0rc7 kernel:
> > >
> > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > >   6: Parse event definition strings                                  :
> > >   6.1: Test event parsing                                            : Ok
> > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > >   6.5: Parsing of aliased events                                     : Ok
> > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > >  10: PMU events                                                      :
> > >  10.1: PMU event table sanity                                        : Ok
> > >  10.2: PMU event map aliases                                         : Ok
> > >  10.3: Parsing of PMU event table metrics                            : Ok
> > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > >  95: perf all metricgroups test                                      : Ok
> > >  96: perf all metrics test                                           : Ok
> > > #
> > >
> > > This looks good.
> >
> > Reproduced:
> >
> > # grep -E vendor_id\|^processor -m2 /proc/cpuinfo
> > vendor_id       : IBM/S390
> > processor 0: version = 00,  identification = 1A33E8,  machine = 2964
> > #
> > # perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : Ok
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : Ok
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : Ok
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> >  95: perf all metricgroups test                                      : Ok
> >  96: perf all metrics test                                           : Ok
> > # perf -v
> > perf version 6.5.rc7.g6f0edbb833ec
> > #
> >
> > > However when I use the check-out from perf-tools-next, I get this output:
> > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > >   6: Parse event definition strings                                  :
> > >   6.1: Test event parsing                                            : Ok
> > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > >   6.5: Parsing of aliased events                                     : FAILED!
> > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > >  10: PMU events                                                      :
> > >  10.1: PMU event table sanity                                        : Ok
> > >  10.2: PMU event map aliases                                         : FAILED!
> > >  10.3: Parsing of PMU event table metrics                            : Ok
> > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > >  93: perf all metricgroups test                                      : FAILED!
> > >  94: perf all metrics test                                           : FAILED!
> > > #
> > >
> > > So some tests are failing again.
> > >
> > > I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
> > > Thanks a lot.
> >
> > [root@kernelqe3 linux]# git checkout perf-tools-next
> > git Switched to branch 'perf-tools-next'
> > Your branch is up to date with 'perf-tools-next/perf-tools-next'.
> > [root@kernelqe3 linux]# git log --oneline -5
> > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
> > 43803cb16f99 perf scripts python: Add support for input args in gecko script
> > f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
> > 8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
> > [root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin
> >
> > [root@kernelqe3 linux]# perf -v
> > perf version 6.5.rc5.geeb6b12992c4
> > [root@kernelqe3 linux]# git log --oneline -1
> > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : FAILED!
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : FAILED!
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> >  93: perf all metricgroups test                                      : FAILED!
> >  94: perf all metrics test                                           : FAILED!
> > [root@kernelqe3 linux]#
> >
> > Bisecting the first problem:
> >
> >  10.2: PMU event map aliases                                         : FAILED!
> >
> > make: Leaving directory '/root/git/linux/tools/perf'
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : Ok
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : Ok
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : FAILED!
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> >  93: perf all metricgroups test                                      : Ok
> >  94: perf all metrics test                                           : Ok
> > [root@kernelqe3 linux]# git bisect bad
> > 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> > commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> > Author: Ian Rogers <irogers@google.com>
> > Date:   Wed Aug 23 21:13:16 2023 -0700
> >
> >     perf jevents: Group events by PMU
> >
> >     Prior to this change a cpuid would map to a list of events where the PMU
> >     would be encoded alongside the event information. This change breaks
> >     apart each group of events so that there is a group per PMU. A new table
> >     is added with the PMU's name and the list of events, the original table
> >     now holding an array of these per PMU tables.
> >
> >     These changes are to make it easier to get per PMU information about
> >     events, rather than the current approach of scanning all events. The
> >     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> >     unidentified PMU is now always expanded to "cpu".
> >
> >     Signed-off-by: Ian Rogers <irogers@google.com>
> >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> >     Cc: Ingo Molnar <mingo@redhat.com>
> >     Cc: James Clark <james.clark@arm.com>
> >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> >     Cc: Jiri Olsa <jolsa@kernel.org>
> >     Cc: John Garry <john.g.garry@oracle.com>
> >     Cc: Kajol Jain <kjain@linux.ibm.com>
> >     Cc: Kan Liang <kan.liang@linux.intel.com>
> >     Cc: Mark Rutland <mark.rutland@arm.com>
> >     Cc: Namhyung Kim <namhyung@kernel.org>
> >     Cc: Peter Zijlstra <peterz@infradead.org>
> >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> >     Cc: Rob Herring <robh@kernel.org>
> >     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
> >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> >
> >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
> >  tools/perf/tests/pmu-events.c    |  30 ++++---
> >  2 files changed, 154 insertions(+), 57 deletions(-)
> > [root@kernelqe3 linux]#
> >
> 
> This change defaulted events without a specified PMU to being for the
> PMU 'cpu', so that events in pmu-events.c were associated with a PMU
> and we could find per-PMU information easily. The test events have no
> PMU and so this has broken s390 where the the PMU should be "cpum_cf".
> It has probably also broken x86 hybrid and arm where their default PMU
> isn't cpu. I'll work on a fix, but the problem will be limited to the
> test.

So, with your "default_core" branche we go to:

[root@kernelqe3 linux]# perf test 10
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : Ok
 10.3: Parsing of PMU event table metrics                            : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
[root@kernelqe3 linux]# perf --version
perf version 6.5.rc5.g3d63ae82aa12
[root@kernelqe3 linux]#

The other tests:

[root@kernelqe3 linux]# perf --version
perf version 6.5.rc5.g3d63ae82aa12
[root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          : FAILED!
  6.3: Parsing of given PMU events from sysfs                        : Ok
  6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
  6.5: Parsing of aliased events                                     : FAILED!
  6.6: Parsing of terms (event modifiers)                            : Ok
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : Ok
 10.3: Parsing of PMU event table metrics                            : Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
 93: perf all metricgroups test                                      : FAILED!
 94: perf all metrics test                                           : FAILED!
[root@kernelqe3 linux]#

Trying to bisect it now.

- Arnaldo

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-28 17:44               ` Arnaldo Carvalho de Melo
@ 2023-08-28 17:53                 ` Arnaldo Carvalho de Melo
  2023-08-28 21:39                   ` Arnaldo Carvalho de Melo
  2023-08-29  0:59                   ` Ian Rogers
  0 siblings, 2 replies; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-28 17:53 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

Em Mon, Aug 28, 2023 at 02:44:53PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
> > On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo
> > <acme@kernel.org> wrote:
> > >
> > > Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
> > > > On 8/25/23 15:14, Ian Rogers wrote:
> > > > > On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
> > >
> > > > >> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> > > > >>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> > > > >>>> Rather than scanning all PMUs for a counter name, scan the PMU
> > > > >>>> associated with the evsel of the sample. This is done to remove a
> > > > >>>> dependence on pmu-events.h.
> > >
> > > > >>> I'm applying this one, and CCing the S/390 developers so that they can
> > > > >>> try this and maybe provide an Acked-by/Tested-by,
> > >
> > > > >> I have downloaded this patch set of 18 patches (using b4), but they do not
> > > > >> apply on my git tree.
> > >
> > > > >> Which git branch do I have to use to test this. Thanks a lot.
> > >
> > > > > the changes are in the perf-tools-next tree:
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
> > >
> > > > Unfurtunately this patch set fails again on s390.
> > > > Here is the test output from the current 6.5.0rc7 kernel:
> > > >
> > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : Ok
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : Ok
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  95: perf all metricgroups test                                      : Ok
> > > >  96: perf all metrics test                                           : Ok
> > > > #
> > > >
> > > > This looks good.
> > >
> > > Reproduced:
> > >
> > > # grep -E vendor_id\|^processor -m2 /proc/cpuinfo
> > > vendor_id       : IBM/S390
> > > processor 0: version = 00,  identification = 1A33E8,  machine = 2964
> > > #
> > > # perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > >   6: Parse event definition strings                                  :
> > >   6.1: Test event parsing                                            : Ok
> > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > >   6.5: Parsing of aliased events                                     : Ok
> > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > >  10: PMU events                                                      :
> > >  10.1: PMU event table sanity                                        : Ok
> > >  10.2: PMU event map aliases                                         : Ok
> > >  10.3: Parsing of PMU event table metrics                            : Ok
> > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > >  95: perf all metricgroups test                                      : Ok
> > >  96: perf all metrics test                                           : Ok
> > > # perf -v
> > > perf version 6.5.rc7.g6f0edbb833ec
> > > #
> > >
> > > > However when I use the check-out from perf-tools-next, I get this output:
> > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : FAILED!
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : FAILED!
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  93: perf all metricgroups test                                      : FAILED!
> > > >  94: perf all metrics test                                           : FAILED!
> > > > #
> > > >
> > > > So some tests are failing again.
> > > >
> > > > I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
> > > > Thanks a lot.
> > >
> > > [root@kernelqe3 linux]# git checkout perf-tools-next
> > > git Switched to branch 'perf-tools-next'
> > > Your branch is up to date with 'perf-tools-next/perf-tools-next'.
> > > [root@kernelqe3 linux]# git log --oneline -5
> > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
> > > 43803cb16f99 perf scripts python: Add support for input args in gecko script
> > > f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
> > > 8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
> > > [root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin
> > >
> > > [root@kernelqe3 linux]# perf -v
> > > perf version 6.5.rc5.geeb6b12992c4
> > > [root@kernelqe3 linux]# git log --oneline -1
> > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > >   6: Parse event definition strings                                  :
> > >   6.1: Test event parsing                                            : Ok
> > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > >   6.5: Parsing of aliased events                                     : FAILED!
> > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > >  10: PMU events                                                      :
> > >  10.1: PMU event table sanity                                        : Ok
> > >  10.2: PMU event map aliases                                         : FAILED!
> > >  10.3: Parsing of PMU event table metrics                            : Ok
> > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > >  93: perf all metricgroups test                                      : FAILED!
> > >  94: perf all metrics test                                           : FAILED!
> > > [root@kernelqe3 linux]#
> > >
> > > Bisecting the first problem:
> > >
> > >  10.2: PMU event map aliases                                         : FAILED!
> > >
> > > make: Leaving directory '/root/git/linux/tools/perf'
> > >   6: Parse event definition strings                                  :
> > >   6.1: Test event parsing                                            : Ok
> > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > >   6.5: Parsing of aliased events                                     : Ok
> > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > >  10: PMU events                                                      :
> > >  10.1: PMU event table sanity                                        : Ok
> > >  10.2: PMU event map aliases                                         : FAILED!
> > >  10.3: Parsing of PMU event table metrics                            : Ok
> > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > >  93: perf all metricgroups test                                      : Ok
> > >  94: perf all metrics test                                           : Ok
> > > [root@kernelqe3 linux]# git bisect bad
> > > 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> > > commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> > > Author: Ian Rogers <irogers@google.com>
> > > Date:   Wed Aug 23 21:13:16 2023 -0700
> > >
> > >     perf jevents: Group events by PMU
> > >
> > >     Prior to this change a cpuid would map to a list of events where the PMU
> > >     would be encoded alongside the event information. This change breaks
> > >     apart each group of events so that there is a group per PMU. A new table
> > >     is added with the PMU's name and the list of events, the original table
> > >     now holding an array of these per PMU tables.
> > >
> > >     These changes are to make it easier to get per PMU information about
> > >     events, rather than the current approach of scanning all events. The
> > >     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> > >     unidentified PMU is now always expanded to "cpu".
> > >
> > >     Signed-off-by: Ian Rogers <irogers@google.com>
> > >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> > >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> > >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> > >     Cc: Ingo Molnar <mingo@redhat.com>
> > >     Cc: James Clark <james.clark@arm.com>
> > >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> > >     Cc: Jiri Olsa <jolsa@kernel.org>
> > >     Cc: John Garry <john.g.garry@oracle.com>
> > >     Cc: Kajol Jain <kjain@linux.ibm.com>
> > >     Cc: Kan Liang <kan.liang@linux.intel.com>
> > >     Cc: Mark Rutland <mark.rutland@arm.com>
> > >     Cc: Namhyung Kim <namhyung@kernel.org>
> > >     Cc: Peter Zijlstra <peterz@infradead.org>
> > >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> > >     Cc: Rob Herring <robh@kernel.org>
> > >     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
> > >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> > >
> > >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
> > >  tools/perf/tests/pmu-events.c    |  30 ++++---
> > >  2 files changed, 154 insertions(+), 57 deletions(-)
> > > [root@kernelqe3 linux]#
> > >
> > 
> > This change defaulted events without a specified PMU to being for the
> > PMU 'cpu', so that events in pmu-events.c were associated with a PMU
> > and we could find per-PMU information easily. The test events have no
> > PMU and so this has broken s390 where the the PMU should be "cpum_cf".
> > It has probably also broken x86 hybrid and arm where their default PMU
> > isn't cpu. I'll work on a fix, but the problem will be limited to the
> > test.
> 
> So, with your "default_core" branche we go to:
> 
> [root@kernelqe3 linux]# perf test 10
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : Ok
>  10.3: Parsing of PMU event table metrics                            : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> [root@kernelqe3 linux]# perf --version
> perf version 6.5.rc5.g3d63ae82aa12
> [root@kernelqe3 linux]#
> 
> The other tests:
> 
> [root@kernelqe3 linux]# perf --version
> perf version 6.5.rc5.g3d63ae82aa12
> [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : FAILED!
>   6.6: Parsing of terms (event modifiers)                            : Ok
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : Ok
>  10.3: Parsing of PMU event table metrics                            : Ok
>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>  93: perf all metricgroups test                                      : FAILED!
>  94: perf all metrics test                                           : FAILED!
> [root@kernelqe3 linux]#
> 
> Trying to bisect it now.

make: Leaving directory '/root/git/linux/tools/perf'
[root@kernelqe3 linux]# perf test 6
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          : FAILED!
  6.3: Parsing of given PMU events from sysfs                        : Ok
  6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
  6.5: Parsing of aliased events                                     : FAILED!
  6.6: Parsing of terms (event modifiers)                            : Ok
[root@kernelqe3 linux]# git bisect bad
8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53 is the first bad commit
commit 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53
Author: Ian Rogers <irogers@google.com>
Date:   Wed Aug 23 21:13:28 2023 -0700

    perf pmu: Lazily load sysfs aliases

    Don't load sysfs aliases for a PMU when the PMU is first created, defer
    until an alias needs to be found. For the pmu-scan benchmark, average
    core PMU scanning is reduced by 30.8%, and average PMU scanning by
    12.6%.

    Signed-off-by: Ian Rogers <irogers@google.com>
    Cc: Adrian Hunter <adrian.hunter@intel.com>
    Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: James Clark <james.clark@arm.com>
    Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
    Cc: Jiri Olsa <jolsa@kernel.org>
    Cc: John Garry <john.g.garry@oracle.com>
    Cc: Kajol Jain <kjain@linux.ibm.com>
    Cc: Kan Liang <kan.liang@linux.intel.com>
    Cc: Mark Rutland <mark.rutland@arm.com>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Ravi Bangoria <ravi.bangoria@amd.com>
    Cc: Rob Herring <robh@kernel.org>
    Link: https://lore.kernel.org/r/20230824041330.266337-17-irogers@google.com
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

 tools/perf/tests/pmu-events.c |  2 ++
 tools/perf/util/pmu.c         | 81 ++++++++++++++++++++++---------------------
 tools/perf/util/pmu.h         |  2 ++
 3 files changed, 46 insertions(+), 39 deletions(-)
[root@kernelqe3 linux]#

It is segfaulting:

  6.2: Parsing of all PMU events from sysfs                          :
--- start ---
test child forked, pid 1202947
Using CPUID IBM,2964,400,N96,1.4,002f
perf: Segmentation fault
Obtained 16 stack frames.
perf(dump_stack+0x36) [0x1156dbe]
perf(sighandler_dump_stack+0x3a) [0x1156e8a]
[0x3fffd4790b6]
/lib64/libc.so.6(__strcasecmp+0x42) [0x3ffa889c51a]
perf() [0x11792ac]
perf(pmu_events_table__find_event+0x27c) [0x12432fc]
perf() [0x11777cc]
perf() [0x1179842]
perf(perf_pmu__check_alias+0x4f0) [0x1179e98]
perf(parse_events_add_pmu+0x72c) [0x1128e84]
perf(parse_events_parse+0x4d4) [0x11754d4]
perf(__parse_events+0xda) [0x112644a]
perf() [0x10cecb2]
perf() [0x10d3264]
perf() [0x10cb250]
perf(cmd_test+0x109e) [0x10cc756]
test child interrupted
---- end ----
Parse event definition strings subtest 2: FAILED!


Starting program: /root/bin/perf test -F 6
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
  6: Parse event definition strings                                  :
  6.1: Test event parsing                                            : Ok
  6.2: Parsing of all PMU events from sysfs                          :
Program received signal SIGSEGV, Segmentation fault.
0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
#0  0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
#1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
#2  0x000000000123e82c in update_alias (pe=0x3ffffff8ac0, table=0x1555cb0 <pmu_events_map+160>, vdata=0x3ffffff8c40) at util/pmu.c:490
#3  0x000000000137b9dc in pmu_events_table.find_event ()
#4  0x000000000123ed4e in perf_pmu__new_alias (pmu=0x15ce490, name=0x23c2593 "L1I_ONDRAWER_MEM_SOURCED_WRITES", desc=0x0, val=0x0, val_fd=0x16058a0, pe=0x0) at util/pmu.c:569
#5  0x000000000123f370 in pmu_aliases_parse (pmu=0x15ce490) at util/pmu.c:673
#6  0x000000000123e3a2 in perf_pmu__find_alias (pmu=0x15ce490, name=0x238eb10 "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV", load=true) at util/pmu.c:432
#7  0x0000000001241bb2 in pmu_find_alias (pmu=0x15ce490, term=0x18409d0) at util/pmu.c:1439
#8  0x0000000001241f82 in perf_pmu__check_alias (pmu=0x15ce490, head_terms=0x21b14d0, info=0x3ffffffa238, err=0x3ffffffc4c8) at util/pmu.c:1519
#9  0x00000000011bbbd4 in parse_events_add_pmu (parse_state=0x3ffffffc2f0, list=0x21afec0, name=0x21c6430 "cpum_cf", head_config=0x21b14d0, auto_merge_stats=false, loc_=0x3ffffffb4d8) at util/parse-events.c:1351
#10 0x000000000123aa4c in parse_events_parse (_parse_state=0x3ffffffc2f0, scanner=0x15b9310) at util/parse-events.y:299
#11 0x00000000011bd190 in parse_events__scanner (str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", input=0x0, parse_state=0x3ffffffc2f0) at util/parse-events.c:1738
#12 0x00000000011bde00 in __parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", pmu_filter=0x0, err=0x3ffffffc4c8, fake_pmu=0x0, warn_if_reordered=true) at util/parse-events.c:2010
#13 0x0000000001121884 in parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", err=0x3ffffffc4c8) at /root/git/linux/tools/perf/util/parse-events.h:40
#14 0x0000000001134084 in test_event (e=0x3ffffffc5e0) at tests/parse-events.c:2393
#15 0x00000000011349ec in test__pmu_events (test=0x156b860 <suite.parse_events>, subtest=1) at tests/parse-events.c:2551
#16 0x000000000111f884 in run_test (test=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:242
#17 0x000000000111fa1a in test_and_print (t=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:271
#18 0x00000000011203fa in __cmd_test (argc=1, argv=0x3ffffffe5d0, skiplist=0x0) at tests/builtin-test.c:442
#19 0x0000000001120cca in cmd_test (argc=1, argv=0x3ffffffe5d0) at tests/builtin-test.c:564
#20 0x00000000011713a4 in run_builtin (p=0x1561190 <commands+600>, argc=3, argv=0x3ffffffe5d0) at perf.c:322
#21 0x0000000001171712 in handle_internal_command (argc=3, argv=0x3ffffffe5d0) at perf.c:375
#22 0x0000000001171920 in run_argv (argcp=0x3ffffffe304, argv=0x3ffffffe2f8) at perf.c:419
#23 0x0000000001171ce8 in main (argc=3, argv=0x3ffffffe5d0) at perf.c:535
(gdb)

(gdb) fr 1
#1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
449		if (!new_str || !strcasecmp(*old_str, new_str))
(gdb) p new_str
$1 = 0x1487d1f "event=0xb1"
(gdb) p *old_str
$2 = 0x1 <error: Cannot access memory at address 0x1>
(gdb) p old_str
$3 = (char **) 0x18c12e0
(gdb)

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-28 17:53                 ` Arnaldo Carvalho de Melo
@ 2023-08-28 21:39                   ` Arnaldo Carvalho de Melo
  2023-08-29  0:59                   ` Ian Rogers
  1 sibling, 0 replies; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-28 21:39 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

Em Mon, Aug 28, 2023 at 02:53:32PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Mon, Aug 28, 2023 at 02:44:53PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
> > > On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo
> > > <acme@kernel.org> wrote:
> > > >
> > > > Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
> > > > > On 8/25/23 15:14, Ian Rogers wrote:
> > > > > > On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
> > > >
> > > > > >> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> > > > > >>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> > > > > >>>> Rather than scanning all PMUs for a counter name, scan the PMU
> > > > > >>>> associated with the evsel of the sample. This is done to remove a
> > > > > >>>> dependence on pmu-events.h.
> > > >
> > > > > >>> I'm applying this one, and CCing the S/390 developers so that they can
> > > > > >>> try this and maybe provide an Acked-by/Tested-by,
> > > >
> > > > > >> I have downloaded this patch set of 18 patches (using b4), but they do not
> > > > > >> apply on my git tree.
> > > >
> > > > > >> Which git branch do I have to use to test this. Thanks a lot.
> > > >
> > > > > > the changes are in the perf-tools-next tree:
> > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
> > > >
> > > > > Unfurtunately this patch set fails again on s390.
> > > > > Here is the test output from the current 6.5.0rc7 kernel:
> > > > >
> > > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > >   6: Parse event definition strings                                  :
> > > > >   6.1: Test event parsing                                            : Ok
> > > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > >   6.5: Parsing of aliased events                                     : Ok
> > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > >  10: PMU events                                                      :
> > > > >  10.1: PMU event table sanity                                        : Ok
> > > > >  10.2: PMU event map aliases                                         : Ok
> > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > >  95: perf all metricgroups test                                      : Ok
> > > > >  96: perf all metrics test                                           : Ok
> > > > > #
> > > > >
> > > > > This looks good.
> > > >
> > > > Reproduced:
> > > >
> > > > # grep -E vendor_id\|^processor -m2 /proc/cpuinfo
> > > > vendor_id       : IBM/S390
> > > > processor 0: version = 00,  identification = 1A33E8,  machine = 2964
> > > > #
> > > > # perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : Ok
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : Ok
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  95: perf all metricgroups test                                      : Ok
> > > >  96: perf all metrics test                                           : Ok
> > > > # perf -v
> > > > perf version 6.5.rc7.g6f0edbb833ec
> > > > #
> > > >
> > > > > However when I use the check-out from perf-tools-next, I get this output:
> > > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > >   6: Parse event definition strings                                  :
> > > > >   6.1: Test event parsing                                            : Ok
> > > > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > >   6.5: Parsing of aliased events                                     : FAILED!
> > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > >  10: PMU events                                                      :
> > > > >  10.1: PMU event table sanity                                        : Ok
> > > > >  10.2: PMU event map aliases                                         : FAILED!
> > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > >  93: perf all metricgroups test                                      : FAILED!
> > > > >  94: perf all metrics test                                           : FAILED!
> > > > > #
> > > > >
> > > > > So some tests are failing again.
> > > > >
> > > > > I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
> > > > > Thanks a lot.
> > > >
> > > > [root@kernelqe3 linux]# git checkout perf-tools-next
> > > > git Switched to branch 'perf-tools-next'
> > > > Your branch is up to date with 'perf-tools-next/perf-tools-next'.
> > > > [root@kernelqe3 linux]# git log --oneline -5
> > > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > > f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
> > > > 43803cb16f99 perf scripts python: Add support for input args in gecko script
> > > > f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
> > > > 8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
> > > > [root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin
> > > >
> > > > [root@kernelqe3 linux]# perf -v
> > > > perf version 6.5.rc5.geeb6b12992c4
> > > > [root@kernelqe3 linux]# git log --oneline -1
> > > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : FAILED!
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : FAILED!
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  93: perf all metricgroups test                                      : FAILED!
> > > >  94: perf all metrics test                                           : FAILED!
> > > > [root@kernelqe3 linux]#
> > > >
> > > > Bisecting the first problem:
> > > >
> > > >  10.2: PMU event map aliases                                         : FAILED!
> > > >
> > > > make: Leaving directory '/root/git/linux/tools/perf'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : Ok
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : FAILED!
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  93: perf all metricgroups test                                      : Ok
> > > >  94: perf all metrics test                                           : Ok
> > > > [root@kernelqe3 linux]# git bisect bad
> > > > 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> > > > commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> > > > Author: Ian Rogers <irogers@google.com>
> > > > Date:   Wed Aug 23 21:13:16 2023 -0700
> > > >
> > > >     perf jevents: Group events by PMU
> > > >
> > > >     Prior to this change a cpuid would map to a list of events where the PMU
> > > >     would be encoded alongside the event information. This change breaks
> > > >     apart each group of events so that there is a group per PMU. A new table
> > > >     is added with the PMU's name and the list of events, the original table
> > > >     now holding an array of these per PMU tables.
> > > >
> > > >     These changes are to make it easier to get per PMU information about
> > > >     events, rather than the current approach of scanning all events. The
> > > >     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> > > >     unidentified PMU is now always expanded to "cpu".
> > > >
> > > >     Signed-off-by: Ian Rogers <irogers@google.com>
> > > >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> > > >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> > > >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> > > >     Cc: Ingo Molnar <mingo@redhat.com>
> > > >     Cc: James Clark <james.clark@arm.com>
> > > >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> > > >     Cc: Jiri Olsa <jolsa@kernel.org>
> > > >     Cc: John Garry <john.g.garry@oracle.com>
> > > >     Cc: Kajol Jain <kjain@linux.ibm.com>
> > > >     Cc: Kan Liang <kan.liang@linux.intel.com>
> > > >     Cc: Mark Rutland <mark.rutland@arm.com>
> > > >     Cc: Namhyung Kim <namhyung@kernel.org>
> > > >     Cc: Peter Zijlstra <peterz@infradead.org>
> > > >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> > > >     Cc: Rob Herring <robh@kernel.org>
> > > >     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
> > > >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> > > >
> > > >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
> > > >  tools/perf/tests/pmu-events.c    |  30 ++++---
> > > >  2 files changed, 154 insertions(+), 57 deletions(-)
> > > > [root@kernelqe3 linux]#
> > > >
> > > 
> > > This change defaulted events without a specified PMU to being for the
> > > PMU 'cpu', so that events in pmu-events.c were associated with a PMU
> > > and we could find per-PMU information easily. The test events have no
> > > PMU and so this has broken s390 where the the PMU should be "cpum_cf".
> > > It has probably also broken x86 hybrid and arm where their default PMU
> > > isn't cpu. I'll work on a fix, but the problem will be limited to the
> > > test.
> > 
> > So, with your "default_core" branche we go to:
> > 
> > [root@kernelqe3 linux]# perf test 10
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : Ok
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > [root@kernelqe3 linux]# perf --version
> > perf version 6.5.rc5.g3d63ae82aa12
> > [root@kernelqe3 linux]#
> > 
> > The other tests:
> > 
> > [root@kernelqe3 linux]# perf --version
> > perf version 6.5.rc5.g3d63ae82aa12
> > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : FAILED!
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : Ok
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> >  93: perf all metricgroups test                                      : FAILED!
> >  94: perf all metrics test                                           : FAILED!
> > [root@kernelqe3 linux]#
> > 
> > Trying to bisect it now.
> 
> make: Leaving directory '/root/git/linux/tools/perf'
> [root@kernelqe3 linux]# perf test 6
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : FAILED!
>   6.6: Parsing of terms (event modifiers)                            : Ok
> [root@kernelqe3 linux]# git bisect bad
> 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53 is the first bad commit
> commit 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53
> Author: Ian Rogers <irogers@google.com>
> Date:   Wed Aug 23 21:13:28 2023 -0700
> 
>     perf pmu: Lazily load sysfs aliases
> 
>     Don't load sysfs aliases for a PMU when the PMU is first created, defer
>     until an alias needs to be found. For the pmu-scan benchmark, average
>     core PMU scanning is reduced by 30.8%, and average PMU scanning by
>     12.6%.
> 
>     Signed-off-by: Ian Rogers <irogers@google.com>
>     Cc: Adrian Hunter <adrian.hunter@intel.com>
>     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
>     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
>     Cc: Ingo Molnar <mingo@redhat.com>
>     Cc: James Clark <james.clark@arm.com>
>     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
>     Cc: Jiri Olsa <jolsa@kernel.org>
>     Cc: John Garry <john.g.garry@oracle.com>
>     Cc: Kajol Jain <kjain@linux.ibm.com>
>     Cc: Kan Liang <kan.liang@linux.intel.com>
>     Cc: Mark Rutland <mark.rutland@arm.com>
>     Cc: Namhyung Kim <namhyung@kernel.org>
>     Cc: Peter Zijlstra <peterz@infradead.org>
>     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
>     Cc: Rob Herring <robh@kernel.org>
>     Link: https://lore.kernel.org/r/20230824041330.266337-17-irogers@google.com
>     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
>  tools/perf/tests/pmu-events.c |  2 ++
>  tools/perf/util/pmu.c         | 81 ++++++++++++++++++++++---------------------
>  tools/perf/util/pmu.h         |  2 ++
>  3 files changed, 46 insertions(+), 39 deletions(-)
> [root@kernelqe3 linux]#
> 
> It is segfaulting:
> 
>   6.2: Parsing of all PMU events from sysfs                          :
> --- start ---
> test child forked, pid 1202947
> Using CPUID IBM,2964,400,N96,1.4,002f
> perf: Segmentation fault
> Obtained 16 stack frames.
> perf(dump_stack+0x36) [0x1156dbe]
> perf(sighandler_dump_stack+0x3a) [0x1156e8a]
> [0x3fffd4790b6]
> /lib64/libc.so.6(__strcasecmp+0x42) [0x3ffa889c51a]
> perf() [0x11792ac]
> perf(pmu_events_table__find_event+0x27c) [0x12432fc]
> perf() [0x11777cc]
> perf() [0x1179842]
> perf(perf_pmu__check_alias+0x4f0) [0x1179e98]
> perf(parse_events_add_pmu+0x72c) [0x1128e84]
> perf(parse_events_parse+0x4d4) [0x11754d4]
> perf(__parse_events+0xda) [0x112644a]
> perf() [0x10cecb2]
> perf() [0x10d3264]
> perf() [0x10cb250]
> perf(cmd_test+0x109e) [0x10cc756]
> test child interrupted
> ---- end ----
> Parse event definition strings subtest 2: FAILED!
> 
> 
> Starting program: /root/bin/perf test -F 6
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib64/libthread_db.so.1".
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          :
> Program received signal SIGSEGV, Segmentation fault.
> 0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
> #0  0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
> #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
> #2  0x000000000123e82c in update_alias (pe=0x3ffffff8ac0, table=0x1555cb0 <pmu_events_map+160>, vdata=0x3ffffff8c40) at util/pmu.c:490
> #3  0x000000000137b9dc in pmu_events_table.find_event ()
> #4  0x000000000123ed4e in perf_pmu__new_alias (pmu=0x15ce490, name=0x23c2593 "L1I_ONDRAWER_MEM_SOURCED_WRITES", desc=0x0, val=0x0, val_fd=0x16058a0, pe=0x0) at util/pmu.c:569
> #5  0x000000000123f370 in pmu_aliases_parse (pmu=0x15ce490) at util/pmu.c:673
> #6  0x000000000123e3a2 in perf_pmu__find_alias (pmu=0x15ce490, name=0x238eb10 "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV", load=true) at util/pmu.c:432
> #7  0x0000000001241bb2 in pmu_find_alias (pmu=0x15ce490, term=0x18409d0) at util/pmu.c:1439
> #8  0x0000000001241f82 in perf_pmu__check_alias (pmu=0x15ce490, head_terms=0x21b14d0, info=0x3ffffffa238, err=0x3ffffffc4c8) at util/pmu.c:1519
> #9  0x00000000011bbbd4 in parse_events_add_pmu (parse_state=0x3ffffffc2f0, list=0x21afec0, name=0x21c6430 "cpum_cf", head_config=0x21b14d0, auto_merge_stats=false, loc_=0x3ffffffb4d8) at util/parse-events.c:1351
> #10 0x000000000123aa4c in parse_events_parse (_parse_state=0x3ffffffc2f0, scanner=0x15b9310) at util/parse-events.y:299
> #11 0x00000000011bd190 in parse_events__scanner (str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", input=0x0, parse_state=0x3ffffffc2f0) at util/parse-events.c:1738
> #12 0x00000000011bde00 in __parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", pmu_filter=0x0, err=0x3ffffffc4c8, fake_pmu=0x0, warn_if_reordered=true) at util/parse-events.c:2010
> #13 0x0000000001121884 in parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", err=0x3ffffffc4c8) at /root/git/linux/tools/perf/util/parse-events.h:40
> #14 0x0000000001134084 in test_event (e=0x3ffffffc5e0) at tests/parse-events.c:2393
> #15 0x00000000011349ec in test__pmu_events (test=0x156b860 <suite.parse_events>, subtest=1) at tests/parse-events.c:2551
> #16 0x000000000111f884 in run_test (test=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:242
> #17 0x000000000111fa1a in test_and_print (t=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:271
> #18 0x00000000011203fa in __cmd_test (argc=1, argv=0x3ffffffe5d0, skiplist=0x0) at tests/builtin-test.c:442
> #19 0x0000000001120cca in cmd_test (argc=1, argv=0x3ffffffe5d0) at tests/builtin-test.c:564
> #20 0x00000000011713a4 in run_builtin (p=0x1561190 <commands+600>, argc=3, argv=0x3ffffffe5d0) at perf.c:322
> #21 0x0000000001171712 in handle_internal_command (argc=3, argv=0x3ffffffe5d0) at perf.c:375
> #22 0x0000000001171920 in run_argv (argcp=0x3ffffffe304, argv=0x3ffffffe2f8) at perf.c:419
> #23 0x0000000001171ce8 in main (argc=3, argv=0x3ffffffe5d0) at perf.c:535
> (gdb)
> 
> (gdb) fr 1
> #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
> 449		if (!new_str || !strcasecmp(*old_str, new_str))
> (gdb) p new_str
> $1 = 0x1487d1f "event=0xb1"
> (gdb) p *old_str
> $2 = 0x1 <error: Cannot access memory at address 0x1>
> (gdb) p old_str
> $3 = (char **) 0x18c12e0
> (gdb)

Same thing on a hybrid ARM system:

  6.5: Parsing of aliased events                                     :
--- start ---
test child forked, pid 49658
Using CPUID 0x00000000410fd082
perf: Segmentation fault
Obtained 16 stack frames.
perf(sighandler_dump_stack+0x43) [0xaaaad58f5047]
linux-vdso.so.1(+0x7a7) [0xffff978fb7a7]
/lib/aarch64-linux-gnu/libc.so.6(__strcasecmp+0x2c) [0xffff96aa1dac]
perf(+0x19378b) [0xaaaad591378b]
perf(pmu_events_table__find_event+0x8b) [0xaaaad59d74cb]
perf(+0x193f87) [0xaaaad5913f87]
perf(+0x19433b) [0xaaaad591433b]
perf(perf_pmu__have_event+0xd3) [0xaaaad5915c17]
perf(parse_events_multi_pmu_add+0x137) [0xaaaad58cb787]
perf(parse_events_parse+0x1247) [0xaaaad5912627]
perf(+0x146c27) [0xaaaad58c6c27]
perf(__parse_events+0x7b) [0xaaaad58c86bb]
perf(+0xeed23) [0xaaaad586ed23]
perf(+0xeb97b) [0xaaaad586b97b]
perf(cmd_test+0x747) [0xaaaad586c477]
perf(+0x11e64b) [0xaaaad589e64b]
test child interrupted
---- end ----
Parse event definition strings subtest 5: FAILED!
  6.6: Parsing of terms (event modifiers)                            :
--- start ---
test child forked, pid 49660
running test 0 'config=10,config1,config2=3,config3=4,umask=1,read,r0xead'
test child finished with 0
---- end ----
Parse event definition strings subtest 6: Ok
root@roc-rk3399-pc:~# grep -i "model name" /proc/cpuinfo
root@roc-rk3399-pc:~# grep -i "model" /proc/cpuinfo
root@roc-rk3399-pc:~# cat /proc/cpuinfo
processor	: 0
BogoMIPS	: 48.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd03
CPU revision	: 4

processor	: 1
BogoMIPS	: 48.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd03
CPU revision	: 4

processor	: 2
BogoMIPS	: 48.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd03
CPU revision	: 4

processor	: 3
BogoMIPS	: 48.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd03
CPU revision	: 4

processor	: 4
BogoMIPS	: 48.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd08
CPU revision	: 2

processor	: 5
BogoMIPS	: 48.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd08
CPU revision	: 2

root@roc-rk3399-pc:~#

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-28 17:53                 ` Arnaldo Carvalho de Melo
  2023-08-28 21:39                   ` Arnaldo Carvalho de Melo
@ 2023-08-29  0:59                   ` Ian Rogers
  2023-08-29  9:20                     ` Jing Zhang
  2023-08-29 11:28                     ` Arnaldo Carvalho de Melo
  1 sibling, 2 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-29  0:59 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

On Mon, Aug 28, 2023 at 10:53 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> Em Mon, Aug 28, 2023 at 02:44:53PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
> > > On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo
> > > <acme@kernel.org> wrote:
> > > >
> > > > Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
> > > > > On 8/25/23 15:14, Ian Rogers wrote:
> > > > > > On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
> > > >
> > > > > >> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> > > > > >>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> > > > > >>>> Rather than scanning all PMUs for a counter name, scan the PMU
> > > > > >>>> associated with the evsel of the sample. This is done to remove a
> > > > > >>>> dependence on pmu-events.h.
> > > >
> > > > > >>> I'm applying this one, and CCing the S/390 developers so that they can
> > > > > >>> try this and maybe provide an Acked-by/Tested-by,
> > > >
> > > > > >> I have downloaded this patch set of 18 patches (using b4), but they do not
> > > > > >> apply on my git tree.
> > > >
> > > > > >> Which git branch do I have to use to test this. Thanks a lot.
> > > >
> > > > > > the changes are in the perf-tools-next tree:
> > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
> > > >
> > > > > Unfurtunately this patch set fails again on s390.
> > > > > Here is the test output from the current 6.5.0rc7 kernel:
> > > > >
> > > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > >   6: Parse event definition strings                                  :
> > > > >   6.1: Test event parsing                                            : Ok
> > > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > >   6.5: Parsing of aliased events                                     : Ok
> > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > >  10: PMU events                                                      :
> > > > >  10.1: PMU event table sanity                                        : Ok
> > > > >  10.2: PMU event map aliases                                         : Ok
> > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > >  95: perf all metricgroups test                                      : Ok
> > > > >  96: perf all metrics test                                           : Ok
> > > > > #
> > > > >
> > > > > This looks good.
> > > >
> > > > Reproduced:
> > > >
> > > > # grep -E vendor_id\|^processor -m2 /proc/cpuinfo
> > > > vendor_id       : IBM/S390
> > > > processor 0: version = 00,  identification = 1A33E8,  machine = 2964
> > > > #
> > > > # perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : Ok
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : Ok
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  95: perf all metricgroups test                                      : Ok
> > > >  96: perf all metrics test                                           : Ok
> > > > # perf -v
> > > > perf version 6.5.rc7.g6f0edbb833ec
> > > > #
> > > >
> > > > > However when I use the check-out from perf-tools-next, I get this output:
> > > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > >   6: Parse event definition strings                                  :
> > > > >   6.1: Test event parsing                                            : Ok
> > > > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > >   6.5: Parsing of aliased events                                     : FAILED!
> > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > >  10: PMU events                                                      :
> > > > >  10.1: PMU event table sanity                                        : Ok
> > > > >  10.2: PMU event map aliases                                         : FAILED!
> > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > >  93: perf all metricgroups test                                      : FAILED!
> > > > >  94: perf all metrics test                                           : FAILED!
> > > > > #
> > > > >
> > > > > So some tests are failing again.
> > > > >
> > > > > I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
> > > > > Thanks a lot.
> > > >
> > > > [root@kernelqe3 linux]# git checkout perf-tools-next
> > > > git Switched to branch 'perf-tools-next'
> > > > Your branch is up to date with 'perf-tools-next/perf-tools-next'.
> > > > [root@kernelqe3 linux]# git log --oneline -5
> > > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > > f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
> > > > 43803cb16f99 perf scripts python: Add support for input args in gecko script
> > > > f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
> > > > 8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
> > > > [root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin
> > > >
> > > > [root@kernelqe3 linux]# perf -v
> > > > perf version 6.5.rc5.geeb6b12992c4
> > > > [root@kernelqe3 linux]# git log --oneline -1
> > > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : FAILED!
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : FAILED!
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  93: perf all metricgroups test                                      : FAILED!
> > > >  94: perf all metrics test                                           : FAILED!
> > > > [root@kernelqe3 linux]#
> > > >
> > > > Bisecting the first problem:
> > > >
> > > >  10.2: PMU event map aliases                                         : FAILED!
> > > >
> > > > make: Leaving directory '/root/git/linux/tools/perf'
> > > >   6: Parse event definition strings                                  :
> > > >   6.1: Test event parsing                                            : Ok
> > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > >   6.5: Parsing of aliased events                                     : Ok
> > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > >  10: PMU events                                                      :
> > > >  10.1: PMU event table sanity                                        : Ok
> > > >  10.2: PMU event map aliases                                         : FAILED!
> > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > >  93: perf all metricgroups test                                      : Ok
> > > >  94: perf all metrics test                                           : Ok
> > > > [root@kernelqe3 linux]# git bisect bad
> > > > 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> > > > commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> > > > Author: Ian Rogers <irogers@google.com>
> > > > Date:   Wed Aug 23 21:13:16 2023 -0700
> > > >
> > > >     perf jevents: Group events by PMU
> > > >
> > > >     Prior to this change a cpuid would map to a list of events where the PMU
> > > >     would be encoded alongside the event information. This change breaks
> > > >     apart each group of events so that there is a group per PMU. A new table
> > > >     is added with the PMU's name and the list of events, the original table
> > > >     now holding an array of these per PMU tables.
> > > >
> > > >     These changes are to make it easier to get per PMU information about
> > > >     events, rather than the current approach of scanning all events. The
> > > >     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> > > >     unidentified PMU is now always expanded to "cpu".
> > > >
> > > >     Signed-off-by: Ian Rogers <irogers@google.com>
> > > >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> > > >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> > > >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> > > >     Cc: Ingo Molnar <mingo@redhat.com>
> > > >     Cc: James Clark <james.clark@arm.com>
> > > >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> > > >     Cc: Jiri Olsa <jolsa@kernel.org>
> > > >     Cc: John Garry <john.g.garry@oracle.com>
> > > >     Cc: Kajol Jain <kjain@linux.ibm.com>
> > > >     Cc: Kan Liang <kan.liang@linux.intel.com>
> > > >     Cc: Mark Rutland <mark.rutland@arm.com>
> > > >     Cc: Namhyung Kim <namhyung@kernel.org>
> > > >     Cc: Peter Zijlstra <peterz@infradead.org>
> > > >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> > > >     Cc: Rob Herring <robh@kernel.org>
> > > >     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
> > > >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> > > >
> > > >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
> > > >  tools/perf/tests/pmu-events.c    |  30 ++++---
> > > >  2 files changed, 154 insertions(+), 57 deletions(-)
> > > > [root@kernelqe3 linux]#
> > > >
> > >
> > > This change defaulted events without a specified PMU to being for the
> > > PMU 'cpu', so that events in pmu-events.c were associated with a PMU
> > > and we could find per-PMU information easily. The test events have no
> > > PMU and so this has broken s390 where the the PMU should be "cpum_cf".
> > > It has probably also broken x86 hybrid and arm where their default PMU
> > > isn't cpu. I'll work on a fix, but the problem will be limited to the
> > > test.
> >
> > So, with your "default_core" branche we go to:
> >
> > [root@kernelqe3 linux]# perf test 10
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : Ok
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > [root@kernelqe3 linux]# perf --version
> > perf version 6.5.rc5.g3d63ae82aa12
> > [root@kernelqe3 linux]#
> >
> > The other tests:
> >
> > [root@kernelqe3 linux]# perf --version
> > perf version 6.5.rc5.g3d63ae82aa12
> > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : FAILED!
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> >  10: PMU events                                                      :
> >  10.1: PMU event table sanity                                        : Ok
> >  10.2: PMU event map aliases                                         : Ok
> >  10.3: Parsing of PMU event table metrics                            : Ok
> >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> >  93: perf all metricgroups test                                      : FAILED!
> >  94: perf all metrics test                                           : FAILED!
> > [root@kernelqe3 linux]#
> >
> > Trying to bisect it now.
>
> make: Leaving directory '/root/git/linux/tools/perf'
> [root@kernelqe3 linux]# perf test 6
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>   6.3: Parsing of given PMU events from sysfs                        : Ok
>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>   6.5: Parsing of aliased events                                     : FAILED!
>   6.6: Parsing of terms (event modifiers)                            : Ok
> [root@kernelqe3 linux]# git bisect bad
> 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53 is the first bad commit
> commit 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53
> Author: Ian Rogers <irogers@google.com>
> Date:   Wed Aug 23 21:13:28 2023 -0700
>
>     perf pmu: Lazily load sysfs aliases
>
>     Don't load sysfs aliases for a PMU when the PMU is first created, defer
>     until an alias needs to be found. For the pmu-scan benchmark, average
>     core PMU scanning is reduced by 30.8%, and average PMU scanning by
>     12.6%.
>
>     Signed-off-by: Ian Rogers <irogers@google.com>
>     Cc: Adrian Hunter <adrian.hunter@intel.com>
>     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
>     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
>     Cc: Ingo Molnar <mingo@redhat.com>
>     Cc: James Clark <james.clark@arm.com>
>     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
>     Cc: Jiri Olsa <jolsa@kernel.org>
>     Cc: John Garry <john.g.garry@oracle.com>
>     Cc: Kajol Jain <kjain@linux.ibm.com>
>     Cc: Kan Liang <kan.liang@linux.intel.com>
>     Cc: Mark Rutland <mark.rutland@arm.com>
>     Cc: Namhyung Kim <namhyung@kernel.org>
>     Cc: Peter Zijlstra <peterz@infradead.org>
>     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
>     Cc: Rob Herring <robh@kernel.org>
>     Link: https://lore.kernel.org/r/20230824041330.266337-17-irogers@google.com
>     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
>
>  tools/perf/tests/pmu-events.c |  2 ++
>  tools/perf/util/pmu.c         | 81 ++++++++++++++++++++++---------------------
>  tools/perf/util/pmu.h         |  2 ++
>  3 files changed, 46 insertions(+), 39 deletions(-)
> [root@kernelqe3 linux]#
>
> It is segfaulting:
>
>   6.2: Parsing of all PMU events from sysfs                          :
> --- start ---
> test child forked, pid 1202947
> Using CPUID IBM,2964,400,N96,1.4,002f
> perf: Segmentation fault
> Obtained 16 stack frames.
> perf(dump_stack+0x36) [0x1156dbe]
> perf(sighandler_dump_stack+0x3a) [0x1156e8a]
> [0x3fffd4790b6]
> /lib64/libc.so.6(__strcasecmp+0x42) [0x3ffa889c51a]
> perf() [0x11792ac]
> perf(pmu_events_table__find_event+0x27c) [0x12432fc]
> perf() [0x11777cc]
> perf() [0x1179842]
> perf(perf_pmu__check_alias+0x4f0) [0x1179e98]
> perf(parse_events_add_pmu+0x72c) [0x1128e84]
> perf(parse_events_parse+0x4d4) [0x11754d4]
> perf(__parse_events+0xda) [0x112644a]
> perf() [0x10cecb2]
> perf() [0x10d3264]
> perf() [0x10cb250]
> perf(cmd_test+0x109e) [0x10cc756]
> test child interrupted
> ---- end ----
> Parse event definition strings subtest 2: FAILED!
>
>
> Starting program: /root/bin/perf test -F 6
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib64/libthread_db.so.1".
>   6: Parse event definition strings                                  :
>   6.1: Test event parsing                                            : Ok
>   6.2: Parsing of all PMU events from sysfs                          :
> Program received signal SIGSEGV, Segmentation fault.
> 0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
> #0  0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
> #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
> #2  0x000000000123e82c in update_alias (pe=0x3ffffff8ac0, table=0x1555cb0 <pmu_events_map+160>, vdata=0x3ffffff8c40) at util/pmu.c:490
> #3  0x000000000137b9dc in pmu_events_table.find_event ()
> #4  0x000000000123ed4e in perf_pmu__new_alias (pmu=0x15ce490, name=0x23c2593 "L1I_ONDRAWER_MEM_SOURCED_WRITES", desc=0x0, val=0x0, val_fd=0x16058a0, pe=0x0) at util/pmu.c:569
> #5  0x000000000123f370 in pmu_aliases_parse (pmu=0x15ce490) at util/pmu.c:673
> #6  0x000000000123e3a2 in perf_pmu__find_alias (pmu=0x15ce490, name=0x238eb10 "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV", load=true) at util/pmu.c:432
> #7  0x0000000001241bb2 in pmu_find_alias (pmu=0x15ce490, term=0x18409d0) at util/pmu.c:1439
> #8  0x0000000001241f82 in perf_pmu__check_alias (pmu=0x15ce490, head_terms=0x21b14d0, info=0x3ffffffa238, err=0x3ffffffc4c8) at util/pmu.c:1519
> #9  0x00000000011bbbd4 in parse_events_add_pmu (parse_state=0x3ffffffc2f0, list=0x21afec0, name=0x21c6430 "cpum_cf", head_config=0x21b14d0, auto_merge_stats=false, loc_=0x3ffffffb4d8) at util/parse-events.c:1351
> #10 0x000000000123aa4c in parse_events_parse (_parse_state=0x3ffffffc2f0, scanner=0x15b9310) at util/parse-events.y:299
> #11 0x00000000011bd190 in parse_events__scanner (str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", input=0x0, parse_state=0x3ffffffc2f0) at util/parse-events.c:1738
> #12 0x00000000011bde00 in __parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", pmu_filter=0x0, err=0x3ffffffc4c8, fake_pmu=0x0, warn_if_reordered=true) at util/parse-events.c:2010
> #13 0x0000000001121884 in parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", err=0x3ffffffc4c8) at /root/git/linux/tools/perf/util/parse-events.h:40
> #14 0x0000000001134084 in test_event (e=0x3ffffffc5e0) at tests/parse-events.c:2393
> #15 0x00000000011349ec in test__pmu_events (test=0x156b860 <suite.parse_events>, subtest=1) at tests/parse-events.c:2551
> #16 0x000000000111f884 in run_test (test=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:242
> #17 0x000000000111fa1a in test_and_print (t=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:271
> #18 0x00000000011203fa in __cmd_test (argc=1, argv=0x3ffffffe5d0, skiplist=0x0) at tests/builtin-test.c:442
> #19 0x0000000001120cca in cmd_test (argc=1, argv=0x3ffffffe5d0) at tests/builtin-test.c:564
> #20 0x00000000011713a4 in run_builtin (p=0x1561190 <commands+600>, argc=3, argv=0x3ffffffe5d0) at perf.c:322
> #21 0x0000000001171712 in handle_internal_command (argc=3, argv=0x3ffffffe5d0) at perf.c:375
> #22 0x0000000001171920 in run_argv (argcp=0x3ffffffe304, argv=0x3ffffffe2f8) at perf.c:419
> #23 0x0000000001171ce8 in main (argc=3, argv=0x3ffffffe5d0) at perf.c:535
> (gdb)
>
> (gdb) fr 1
> #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
> 449             if (!new_str || !strcasecmp(*old_str, new_str))
> (gdb) p new_str
> $1 = 0x1487d1f "event=0xb1"
> (gdb) p *old_str
> $2 = 0x1 <error: Cannot access memory at address 0x1>
> (gdb) p old_str
> $3 = (char **) 0x18c12e0
> (gdb)

I can't explain this, how come the line numbers don't agree with?
https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=tmp.perf-tools-next#n449

The values are coming from the json event data. I'd need to see the
generated pmu-events.c.

Thanks,
Ian

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-29  0:59                   ` Ian Rogers
@ 2023-08-29  9:20                     ` Jing Zhang
  2023-08-29 13:20                       ` Arnaldo Carvalho de Melo
  2023-08-29 11:28                     ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 39+ messages in thread
From: Jing Zhang @ 2023-08-29  9:20 UTC (permalink / raw)
  To: Ian Rogers, Arnaldo Carvalho de Melo
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel



在 2023/8/29 上午8:59, Ian Rogers 写道:
> On Mon, Aug 28, 2023 at 10:53 AM Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
>>
>> Em Mon, Aug 28, 2023 at 02:44:53PM -0300, Arnaldo Carvalho de Melo escreveu:
>>> Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
>>>> On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo
>>>> <acme@kernel.org> wrote:
>>>>>
>>>>> Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
>>>>>> On 8/25/23 15:14, Ian Rogers wrote:
>>>>>>> On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
>>>>>
>>>>>>>> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
>>>>>>>>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
>>>>>>>>>> Rather than scanning all PMUs for a counter name, scan the PMU
>>>>>>>>>> associated with the evsel of the sample. This is done to remove a
>>>>>>>>>> dependence on pmu-events.h.
>>>>>
>>>>>>>>> I'm applying this one, and CCing the S/390 developers so that they can
>>>>>>>>> try this and maybe provide an Acked-by/Tested-by,
>>>>>
>>>>>>>> I have downloaded this patch set of 18 patches (using b4), but they do not
>>>>>>>> apply on my git tree.
>>>>>
>>>>>>>> Which git branch do I have to use to test this. Thanks a lot.
>>>>>
>>>>>>> the changes are in the perf-tools-next tree:
>>>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
>>>>>
>>>>>> Unfurtunately this patch set fails again on s390.
>>>>>> Here is the test output from the current 6.5.0rc7 kernel:
>>>>>>
>>>>>> # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>>>>>>   6: Parse event definition strings                                  :
>>>>>>   6.1: Test event parsing                                            : Ok
>>>>>>   6.2: Parsing of all PMU events from sysfs                          : Ok
>>>>>>   6.3: Parsing of given PMU events from sysfs                        : Ok
>>>>>>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>>>>>>   6.5: Parsing of aliased events                                     : Ok
>>>>>>   6.6: Parsing of terms (event modifiers)                            : Ok
>>>>>>  10: PMU events                                                      :
>>>>>>  10.1: PMU event table sanity                                        : Ok
>>>>>>  10.2: PMU event map aliases                                         : Ok
>>>>>>  10.3: Parsing of PMU event table metrics                            : Ok
>>>>>>  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
>>>>>>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>>>>>>  95: perf all metricgroups test                                      : Ok
>>>>>>  96: perf all metrics test                                           : Ok
>>>>>> #
>>>>>>
>>>>>> This looks good.
>>>>>
>>>>> Reproduced:
>>>>>
>>>>> # grep -E vendor_id\|^processor -m2 /proc/cpuinfo
>>>>> vendor_id       : IBM/S390
>>>>> processor 0: version = 00,  identification = 1A33E8,  machine = 2964
>>>>> #
>>>>> # perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>>>>>   6: Parse event definition strings                                  :
>>>>>   6.1: Test event parsing                                            : Ok
>>>>>   6.2: Parsing of all PMU events from sysfs                          : Ok
>>>>>   6.3: Parsing of given PMU events from sysfs                        : Ok
>>>>>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>>>>>   6.5: Parsing of aliased events                                     : Ok
>>>>>   6.6: Parsing of terms (event modifiers)                            : Ok
>>>>>  10: PMU events                                                      :
>>>>>  10.1: PMU event table sanity                                        : Ok
>>>>>  10.2: PMU event map aliases                                         : Ok
>>>>>  10.3: Parsing of PMU event table metrics                            : Ok
>>>>>  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
>>>>>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>>>>>  95: perf all metricgroups test                                      : Ok
>>>>>  96: perf all metrics test                                           : Ok
>>>>> # perf -v
>>>>> perf version 6.5.rc7.g6f0edbb833ec
>>>>> #
>>>>>
>>>>>> However when I use the check-out from perf-tools-next, I get this output:
>>>>>> # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>>>>>>   6: Parse event definition strings                                  :
>>>>>>   6.1: Test event parsing                                            : Ok
>>>>>>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>>>>>>   6.3: Parsing of given PMU events from sysfs                        : Ok
>>>>>>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>>>>>>   6.5: Parsing of aliased events                                     : FAILED!
>>>>>>   6.6: Parsing of terms (event modifiers)                            : Ok
>>>>>>  10: PMU events                                                      :
>>>>>>  10.1: PMU event table sanity                                        : Ok
>>>>>>  10.2: PMU event map aliases                                         : FAILED!
>>>>>>  10.3: Parsing of PMU event table metrics                            : Ok
>>>>>>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>>>>>>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>>>>>>  93: perf all metricgroups test                                      : FAILED!
>>>>>>  94: perf all metrics test                                           : FAILED!
>>>>>> #
>>>>>>
>>>>>> So some tests are failing again.
>>>>>>
>>>>>> I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
>>>>>> Thanks a lot.
>>>>>
>>>>> [root@kernelqe3 linux]# git checkout perf-tools-next
>>>>> git Switched to branch 'perf-tools-next'
>>>>> Your branch is up to date with 'perf-tools-next/perf-tools-next'.
>>>>> [root@kernelqe3 linux]# git log --oneline -5
>>>>> eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
>>>>> f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
>>>>> 43803cb16f99 perf scripts python: Add support for input args in gecko script
>>>>> f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
>>>>> 8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
>>>>> [root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin
>>>>>
>>>>> [root@kernelqe3 linux]# perf -v
>>>>> perf version 6.5.rc5.geeb6b12992c4
>>>>> [root@kernelqe3 linux]# git log --oneline -1
>>>>> eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
>>>>> [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>>>>>   6: Parse event definition strings                                  :
>>>>>   6.1: Test event parsing                                            : Ok
>>>>>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>>>>>   6.3: Parsing of given PMU events from sysfs                        : Ok
>>>>>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>>>>>   6.5: Parsing of aliased events                                     : FAILED!
>>>>>   6.6: Parsing of terms (event modifiers)                            : Ok
>>>>>  10: PMU events                                                      :
>>>>>  10.1: PMU event table sanity                                        : Ok
>>>>>  10.2: PMU event map aliases                                         : FAILED!
>>>>>  10.3: Parsing of PMU event table metrics                            : Ok
>>>>>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>>>>>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>>>>>  93: perf all metricgroups test                                      : FAILED!
>>>>>  94: perf all metrics test                                           : FAILED!
>>>>> [root@kernelqe3 linux]#
>>>>>
>>>>> Bisecting the first problem:
>>>>>
>>>>>  10.2: PMU event map aliases                                         : FAILED!
>>>>>
>>>>> make: Leaving directory '/root/git/linux/tools/perf'
>>>>>   6: Parse event definition strings                                  :
>>>>>   6.1: Test event parsing                                            : Ok
>>>>>   6.2: Parsing of all PMU events from sysfs                          : Ok
>>>>>   6.3: Parsing of given PMU events from sysfs                        : Ok
>>>>>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>>>>>   6.5: Parsing of aliased events                                     : Ok
>>>>>   6.6: Parsing of terms (event modifiers)                            : Ok
>>>>>  10: PMU events                                                      :
>>>>>  10.1: PMU event table sanity                                        : Ok
>>>>>  10.2: PMU event map aliases                                         : FAILED!
>>>>>  10.3: Parsing of PMU event table metrics                            : Ok
>>>>>  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
>>>>>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>>>>>  93: perf all metricgroups test                                      : Ok
>>>>>  94: perf all metrics test                                           : Ok
>>>>> [root@kernelqe3 linux]# git bisect bad
>>>>> 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
>>>>> commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
>>>>> Author: Ian Rogers <irogers@google.com>
>>>>> Date:   Wed Aug 23 21:13:16 2023 -0700
>>>>>
>>>>>     perf jevents: Group events by PMU
>>>>>
>>>>>     Prior to this change a cpuid would map to a list of events where the PMU
>>>>>     would be encoded alongside the event information. This change breaks
>>>>>     apart each group of events so that there is a group per PMU. A new table
>>>>>     is added with the PMU's name and the list of events, the original table
>>>>>     now holding an array of these per PMU tables.
>>>>>
>>>>>     These changes are to make it easier to get per PMU information about
>>>>>     events, rather than the current approach of scanning all events. The
>>>>>     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
>>>>>     unidentified PMU is now always expanded to "cpu".
>>>>>
>>>>>     Signed-off-by: Ian Rogers <irogers@google.com>
>>>>>     Cc: Adrian Hunter <adrian.hunter@intel.com>
>>>>>     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
>>>>>     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
>>>>>     Cc: Ingo Molnar <mingo@redhat.com>
>>>>>     Cc: James Clark <james.clark@arm.com>
>>>>>     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
>>>>>     Cc: Jiri Olsa <jolsa@kernel.org>
>>>>>     Cc: John Garry <john.g.garry@oracle.com>
>>>>>     Cc: Kajol Jain <kjain@linux.ibm.com>
>>>>>     Cc: Kan Liang <kan.liang@linux.intel.com>
>>>>>     Cc: Mark Rutland <mark.rutland@arm.com>
>>>>>     Cc: Namhyung Kim <namhyung@kernel.org>
>>>>>     Cc: Peter Zijlstra <peterz@infradead.org>
>>>>>     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
>>>>>     Cc: Rob Herring <robh@kernel.org>
>>>>>     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
>>>>>     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
>>>>>
>>>>>  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
>>>>>  tools/perf/tests/pmu-events.c    |  30 ++++---
>>>>>  2 files changed, 154 insertions(+), 57 deletions(-)
>>>>> [root@kernelqe3 linux]#
>>>>>
>>>>
>>>> This change defaulted events without a specified PMU to being for the
>>>> PMU 'cpu', so that events in pmu-events.c were associated with a PMU
>>>> and we could find per-PMU information easily. The test events have no
>>>> PMU and so this has broken s390 where the the PMU should be "cpum_cf".
>>>> It has probably also broken x86 hybrid and arm where their default PMU
>>>> isn't cpu. I'll work on a fix, but the problem will be limited to the
>>>> test.
>>>
>>> So, with your "default_core" branche we go to:
>>>
>>> [root@kernelqe3 linux]# perf test 10
>>>  10: PMU events                                                      :
>>>  10.1: PMU event table sanity                                        : Ok
>>>  10.2: PMU event map aliases                                         : Ok
>>>  10.3: Parsing of PMU event table metrics                            : Ok
>>>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>>>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>>> [root@kernelqe3 linux]# perf --version
>>> perf version 6.5.rc5.g3d63ae82aa12
>>> [root@kernelqe3 linux]#
>>>
>>> The other tests:
>>>
>>> [root@kernelqe3 linux]# perf --version
>>> perf version 6.5.rc5.g3d63ae82aa12
>>> [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
>>>   6: Parse event definition strings                                  :
>>>   6.1: Test event parsing                                            : Ok
>>>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>>>   6.3: Parsing of given PMU events from sysfs                        : Ok
>>>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>>>   6.5: Parsing of aliased events                                     : FAILED!
>>>   6.6: Parsing of terms (event modifiers)                            : Ok
>>>  10: PMU events                                                      :
>>>  10.1: PMU event table sanity                                        : Ok
>>>  10.2: PMU event map aliases                                         : Ok
>>>  10.3: Parsing of PMU event table metrics                            : Ok
>>>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>>>  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
>>>  93: perf all metricgroups test                                      : FAILED!
>>>  94: perf all metrics test                                           : FAILED!
>>> [root@kernelqe3 linux]#
>>>
>>> Trying to bisect it now.
>>
>> make: Leaving directory '/root/git/linux/tools/perf'
>> [root@kernelqe3 linux]# perf test 6
>>   6: Parse event definition strings                                  :
>>   6.1: Test event parsing                                            : Ok
>>   6.2: Parsing of all PMU events from sysfs                          : FAILED!
>>   6.3: Parsing of given PMU events from sysfs                        : Ok
>>   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
>>   6.5: Parsing of aliased events                                     : FAILED!
>>   6.6: Parsing of terms (event modifiers)                            : Ok
>> [root@kernelqe3 linux]# git bisect bad
>> 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53 is the first bad commit
>> commit 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53
>> Author: Ian Rogers <irogers@google.com>
>> Date:   Wed Aug 23 21:13:28 2023 -0700
>>
>>     perf pmu: Lazily load sysfs aliases
>>
>>     Don't load sysfs aliases for a PMU when the PMU is first created, defer
>>     until an alias needs to be found. For the pmu-scan benchmark, average
>>     core PMU scanning is reduced by 30.8%, and average PMU scanning by
>>     12.6%.
>>
>>     Signed-off-by: Ian Rogers <irogers@google.com>
>>     Cc: Adrian Hunter <adrian.hunter@intel.com>
>>     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
>>     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
>>     Cc: Ingo Molnar <mingo@redhat.com>
>>     Cc: James Clark <james.clark@arm.com>
>>     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
>>     Cc: Jiri Olsa <jolsa@kernel.org>
>>     Cc: John Garry <john.g.garry@oracle.com>
>>     Cc: Kajol Jain <kjain@linux.ibm.com>
>>     Cc: Kan Liang <kan.liang@linux.intel.com>
>>     Cc: Mark Rutland <mark.rutland@arm.com>
>>     Cc: Namhyung Kim <namhyung@kernel.org>
>>     Cc: Peter Zijlstra <peterz@infradead.org>
>>     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
>>     Cc: Rob Herring <robh@kernel.org>
>>     Link: https://lore.kernel.org/r/20230824041330.266337-17-irogers@google.com
>>     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
>>
>>  tools/perf/tests/pmu-events.c |  2 ++
>>  tools/perf/util/pmu.c         | 81 ++++++++++++++++++++++---------------------
>>  tools/perf/util/pmu.h         |  2 ++
>>  3 files changed, 46 insertions(+), 39 deletions(-)
>> [root@kernelqe3 linux]#
>>
>> It is segfaulting:
>>
>>   6.2: Parsing of all PMU events from sysfs                          :
>> --- start ---
>> test child forked, pid 1202947
>> Using CPUID IBM,2964,400,N96,1.4,002f
>> perf: Segmentation fault
>> Obtained 16 stack frames.
>> perf(dump_stack+0x36) [0x1156dbe]
>> perf(sighandler_dump_stack+0x3a) [0x1156e8a]
>> [0x3fffd4790b6]
>> /lib64/libc.so.6(__strcasecmp+0x42) [0x3ffa889c51a]
>> perf() [0x11792ac]
>> perf(pmu_events_table__find_event+0x27c) [0x12432fc]
>> perf() [0x11777cc]
>> perf() [0x1179842]
>> perf(perf_pmu__check_alias+0x4f0) [0x1179e98]
>> perf(parse_events_add_pmu+0x72c) [0x1128e84]
>> perf(parse_events_parse+0x4d4) [0x11754d4]
>> perf(__parse_events+0xda) [0x112644a]
>> perf() [0x10cecb2]
>> perf() [0x10d3264]
>> perf() [0x10cb250]
>> perf(cmd_test+0x109e) [0x10cc756]
>> test child interrupted
>> ---- end ----
>> Parse event definition strings subtest 2: FAILED!
>>
>>
>> Starting program: /root/bin/perf test -F 6
>> [Thread debugging using libthread_db enabled]
>> Using host libthread_db library "/lib64/libthread_db.so.1".
>>   6: Parse event definition strings                                  :
>>   6.1: Test event parsing                                            : Ok
>>   6.2: Parsing of all PMU events from sysfs                          :
>> Program received signal SIGSEGV, Segmentation fault.
>> 0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
>> #0  0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
>> #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
>> #2  0x000000000123e82c in update_alias (pe=0x3ffffff8ac0, table=0x1555cb0 <pmu_events_map+160>, vdata=0x3ffffff8c40) at util/pmu.c:490
>> #3  0x000000000137b9dc in pmu_events_table.find_event ()
>> #4  0x000000000123ed4e in perf_pmu__new_alias (pmu=0x15ce490, name=0x23c2593 "L1I_ONDRAWER_MEM_SOURCED_WRITES", desc=0x0, val=0x0, val_fd=0x16058a0, pe=0x0) at util/pmu.c:569
>> #5  0x000000000123f370 in pmu_aliases_parse (pmu=0x15ce490) at util/pmu.c:673
>> #6  0x000000000123e3a2 in perf_pmu__find_alias (pmu=0x15ce490, name=0x238eb10 "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV", load=true) at util/pmu.c:432
>> #7  0x0000000001241bb2 in pmu_find_alias (pmu=0x15ce490, term=0x18409d0) at util/pmu.c:1439
>> #8  0x0000000001241f82 in perf_pmu__check_alias (pmu=0x15ce490, head_terms=0x21b14d0, info=0x3ffffffa238, err=0x3ffffffc4c8) at util/pmu.c:1519
>> #9  0x00000000011bbbd4 in parse_events_add_pmu (parse_state=0x3ffffffc2f0, list=0x21afec0, name=0x21c6430 "cpum_cf", head_config=0x21b14d0, auto_merge_stats=false, loc_=0x3ffffffb4d8) at util/parse-events.c:1351
>> #10 0x000000000123aa4c in parse_events_parse (_parse_state=0x3ffffffc2f0, scanner=0x15b9310) at util/parse-events.y:299
>> #11 0x00000000011bd190 in parse_events__scanner (str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", input=0x0, parse_state=0x3ffffffc2f0) at util/parse-events.c:1738
>> #12 0x00000000011bde00 in __parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", pmu_filter=0x0, err=0x3ffffffc4c8, fake_pmu=0x0, warn_if_reordered=true) at util/parse-events.c:2010
>> #13 0x0000000001121884 in parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", err=0x3ffffffc4c8) at /root/git/linux/tools/perf/util/parse-events.h:40
>> #14 0x0000000001134084 in test_event (e=0x3ffffffc5e0) at tests/parse-events.c:2393
>> #15 0x00000000011349ec in test__pmu_events (test=0x156b860 <suite.parse_events>, subtest=1) at tests/parse-events.c:2551
>> #16 0x000000000111f884 in run_test (test=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:242
>> #17 0x000000000111fa1a in test_and_print (t=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:271
>> #18 0x00000000011203fa in __cmd_test (argc=1, argv=0x3ffffffe5d0, skiplist=0x0) at tests/builtin-test.c:442
>> #19 0x0000000001120cca in cmd_test (argc=1, argv=0x3ffffffe5d0) at tests/builtin-test.c:564
>> #20 0x00000000011713a4 in run_builtin (p=0x1561190 <commands+600>, argc=3, argv=0x3ffffffe5d0) at perf.c:322
>> #21 0x0000000001171712 in handle_internal_command (argc=3, argv=0x3ffffffe5d0) at perf.c:375
>> #22 0x0000000001171920 in run_argv (argcp=0x3ffffffe304, argv=0x3ffffffe2f8) at perf.c:419
>> #23 0x0000000001171ce8 in main (argc=3, argv=0x3ffffffe5d0) at perf.c:535
>> (gdb)
>>
>> (gdb) fr 1
>> #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
>> 449             if (!new_str || !strcasecmp(*old_str, new_str))
>> (gdb) p new_str
>> $1 = 0x1487d1f "event=0xb1"
>> (gdb) p *old_str
>> $2 = 0x1 <error: Cannot access memory at address 0x1>
>> (gdb) p old_str
>> $3 = (char **) 0x18c12e0
>> (gdb)
> 
> I can't explain this, how come the line numbers don't agree with?
> https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=tmp.perf-tools-next#n449
> 
> The values are coming from the json event data. I'd need to see the
> generated pmu-events.c.
> 
> Thanks,
> Ian


Hi Ian,

I pulled the lastest tmp.perf-tools-next, and build with JEVENT_ARCH=all on ARM(KunPeng) system. The test 10 also fails.

The bad commit maybe is "edb217f perf pmu: Parse sysfs events directly from a file". Hope it helps.

#git log --oneline -1
3d63ae8 perf jevents: Use "default_core" for events with no Unit

#./perf test 10
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : Ok
 10.3: Parsing of PMU event table metrics                            : FAILED!
 10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
 10.5: Parsing of metric thresholds with fake PMUs                   : FAILED!

Found metric 'tsx_aborted_cycles'
metric expr (max(cycles\-t - cycles\-ct, 0) / cycles if has_event(cycles\-t) else 0) for tsx_aborted_cycles
parsing metric: (max(cycles\-t - cycles\-ct, 0) / cycles if has_event(cycles\-t) else 0)
perf: Segmentation fault
Obtained 16 stack frames.
./perf() [0x514a23]
linux-vdso.so.1(+0x7c3) [0xffff8ac847c3]
./perf() [0x52bb08]
./perf() [0x52ffc3]
./perf() [0x4e8cab]
./perf() [0x4ea27b]
./perf() [0x532137]
./perf() [0x53273b]
./perf() [0x533ed7]
./perf() [0x4ed58b]
./perf() [0x530763]
./perf() [0x4e8c47]
./perf() [0x4ea5e3]
./perf() [0x4eaa8f]
./perf() [0x595393]
./perf() [0x593753]
test child interrupted
---- end ----
PMU events subtest 3: FAILED!
 10.4: Parsing of PMU event table metrics with fake PMUs             :
--- start ---
test child forked, pid 24107
parsing '': '(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100.'
parsing metric: (unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100.
Using CPUID 0x00000000481fd010
perf: Segmentation fault
Obtained 16 stack frames.
./perf() [0x514a23]
linux-vdso.so.1(+0x7c3) [0xffff8ac847c3]
./perf() [0x52bb08]
./perf() [0x52ffc3]
./perf() [0x4e8cab]
./perf() [0x4ea27b]
./perf() [0x532137]
./perf() [0x53273b]
./perf() [0x533ed7]
./perf() [0x4ed58b]
./perf() [0x530763]
./perf() [0x4e8c47]
./perf() [0x4ea5e3]
./perf() [0x4a50b3]
./perf() [0x4a5343]
./perf() [0x48fef7]
test child interrupted
---- end ----
PMU events subtest 4: FAILED!
 10.5: Parsing of metric thresholds with fake PMUs                   :
--- start ---
test child forked, pid 24108
parsing 'tma_alloc_restriction': 'tma_alloc_restriction > 0.1'
parsing metric: tma_alloc_restriction > 0.1
Using CPUID 0x00000000481fd010
perf: Segmentation fault
Obtained 16 stack frames.
./perf() [0x514a23]
linux-vdso.so.1(+0x7c3) [0xffff8ac847c3]
./perf() [0x52bb08]
./perf() [0x52ffc3]
./perf() [0x4e8cab]
./perf() [0x4ea27b]
./perf() [0x532137]
./perf() [0x53273b]
./perf() [0x533ed7]
./perf() [0x4ed58b]
./perf() [0x530763]
./perf() [0x4e8c47]
./perf() [0x4ea5e3]
./perf() [0x4a50b3]
./perf() [0x5dec0b]
./perf() [0x5df117]
test child interrupted
---- end ----
PMU events subtest 5: FAILED!

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-29  0:59                   ` Ian Rogers
  2023-08-29  9:20                     ` Jing Zhang
@ 2023-08-29 11:28                     ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-29 11:28 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Thomas Richter, Sumanth Korikkar, Heiko Carstens, Sven Schnelle,
	Jiri Olsa, James Clark, linux-perf-users, linux-kernel

Em Mon, Aug 28, 2023 at 05:59:47PM -0700, Ian Rogers escreveu:
> On Mon, Aug 28, 2023 at 10:53 AM Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> >
> > Em Mon, Aug 28, 2023 at 02:44:53PM -0300, Arnaldo Carvalho de Melo escreveu:
> > > Em Fri, Aug 25, 2023 at 03:56:54PM -0700, Ian Rogers escreveu:
> > > > On Fri, Aug 25, 2023 at 1:56 PM Arnaldo Carvalho de Melo
> > > > <acme@kernel.org> wrote:
> > > > >
> > > > > Em Fri, Aug 25, 2023 at 04:39:22PM +0200, Thomas Richter escreveu:
> > > > > > On 8/25/23 15:14, Ian Rogers wrote:
> > > > > > > On Fri, Aug 25, 2023 at 1:20 AM Thomas Richter <tmricht@linux.ibm.com> wrote:
> > > > >
> > > > > > >> On 8/24/23 15:59, Arnaldo Carvalho de Melo wrote:
> > > > > > >>> Em Wed, Aug 23, 2023 at 09:13:18PM -0700, Ian Rogers escreveu:
> > > > > > >>>> Rather than scanning all PMUs for a counter name, scan the PMU
> > > > > > >>>> associated with the evsel of the sample. This is done to remove a
> > > > > > >>>> dependence on pmu-events.h.
> > > > >
> > > > > > >>> I'm applying this one, and CCing the S/390 developers so that they can
> > > > > > >>> try this and maybe provide an Acked-by/Tested-by,
> > > > >
> > > > > > >> I have downloaded this patch set of 18 patches (using b4), but they do not
> > > > > > >> apply on my git tree.
> > > > >
> > > > > > >> Which git branch do I have to use to test this. Thanks a lot.
> > > > >
> > > > > > > the changes are in the perf-tools-next tree:
> > > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/
> > > > >
> > > > > > Unfurtunately this patch set fails again on s390.
> > > > > > Here is the test output from the current 6.5.0rc7 kernel:
> > > > > >
> > > > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > > >   6: Parse event definition strings                                  :
> > > > > >   6.1: Test event parsing                                            : Ok
> > > > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > > >   6.5: Parsing of aliased events                                     : Ok
> > > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > > >  10: PMU events                                                      :
> > > > > >  10.1: PMU event table sanity                                        : Ok
> > > > > >  10.2: PMU event map aliases                                         : Ok
> > > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > > >  95: perf all metricgroups test                                      : Ok
> > > > > >  96: perf all metrics test                                           : Ok
> > > > > > #
> > > > > >
> > > > > > This looks good.
> > > > >
> > > > > Reproduced:
> > > > >
> > > > > # grep -E vendor_id\|^processor -m2 /proc/cpuinfo
> > > > > vendor_id       : IBM/S390
> > > > > processor 0: version = 00,  identification = 1A33E8,  machine = 2964
> > > > > #
> > > > > # perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > >   6: Parse event definition strings                                  :
> > > > >   6.1: Test event parsing                                            : Ok
> > > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > >   6.5: Parsing of aliased events                                     : Ok
> > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > >  10: PMU events                                                      :
> > > > >  10.1: PMU event table sanity                                        : Ok
> > > > >  10.2: PMU event map aliases                                         : Ok
> > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > >  95: perf all metricgroups test                                      : Ok
> > > > >  96: perf all metrics test                                           : Ok
> > > > > # perf -v
> > > > > perf version 6.5.rc7.g6f0edbb833ec
> > > > > #
> > > > >
> > > > > > However when I use the check-out from perf-tools-next, I get this output:
> > > > > > # ./perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > > >   6: Parse event definition strings                                  :
> > > > > >   6.1: Test event parsing                                            : Ok
> > > > > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > > >   6.5: Parsing of aliased events                                     : FAILED!
> > > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > > >  10: PMU events                                                      :
> > > > > >  10.1: PMU event table sanity                                        : Ok
> > > > > >  10.2: PMU event map aliases                                         : FAILED!
> > > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > > >  93: perf all metricgroups test                                      : FAILED!
> > > > > >  94: perf all metrics test                                           : FAILED!
> > > > > > #
> > > > > >
> > > > > > So some tests are failing again.
> > > > > >
> > > > > > I am out for the next two weeks, Sumanth Korikkar (on to list) might be able to help.
> > > > > > Thanks a lot.
> > > > >
> > > > > [root@kernelqe3 linux]# git checkout perf-tools-next
> > > > > git Switched to branch 'perf-tools-next'
> > > > > Your branch is up to date with 'perf-tools-next/perf-tools-next'.
> > > > > [root@kernelqe3 linux]# git log --oneline -5
> > > > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > > > f208b2c6f984 (perf-tools-next/tmp.perf-tools-next) perf scripts python gecko: Launch the profiler UI on the default browser with the appropriate URL
> > > > > 43803cb16f99 perf scripts python: Add support for input args in gecko script
> > > > > f85d120c46e7 perf jevents: Sort strings in the big C string to reduce faults
> > > > > 8d4b6d37ea78 perf pmu: Lazily load sysfs aliases
> > > > > [root@kernelqe3 linux]# make BUILD_BPF_SKEL=1 -C tools/perf O=/tmp/build/perf install-bin
> > > > >
> > > > > [root@kernelqe3 linux]# perf -v
> > > > > perf version 6.5.rc5.geeb6b12992c4
> > > > > [root@kernelqe3 linux]# git log --oneline -1
> > > > > eeb6b12992c4 (HEAD -> perf-tools-next, perf-tools-next/perf-tools-next) perf jevents: Don't append Unit to desc
> > > > > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > > > >   6: Parse event definition strings                                  :
> > > > >   6.1: Test event parsing                                            : Ok
> > > > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > >   6.5: Parsing of aliased events                                     : FAILED!
> > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > >  10: PMU events                                                      :
> > > > >  10.1: PMU event table sanity                                        : Ok
> > > > >  10.2: PMU event map aliases                                         : FAILED!
> > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > >  93: perf all metricgroups test                                      : FAILED!
> > > > >  94: perf all metrics test                                           : FAILED!
> > > > > [root@kernelqe3 linux]#
> > > > >
> > > > > Bisecting the first problem:
> > > > >
> > > > >  10.2: PMU event map aliases                                         : FAILED!
> > > > >
> > > > > make: Leaving directory '/root/git/linux/tools/perf'
> > > > >   6: Parse event definition strings                                  :
> > > > >   6.1: Test event parsing                                            : Ok
> > > > >   6.2: Parsing of all PMU events from sysfs                          : Ok
> > > > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > > > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > > > >   6.5: Parsing of aliased events                                     : Ok
> > > > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > > > >  10: PMU events                                                      :
> > > > >  10.1: PMU event table sanity                                        : Ok
> > > > >  10.2: PMU event map aliases                                         : FAILED!
> > > > >  10.3: Parsing of PMU event table metrics                            : Ok
> > > > >  10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
> > > > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > > >  93: perf all metricgroups test                                      : Ok
> > > > >  94: perf all metrics test                                           : Ok
> > > > > [root@kernelqe3 linux]# git bisect bad
> > > > > 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28 is the first bad commit
> > > > > commit 2e255b4f9f41f137d9e3dc4fae3603a9c2c3dd28
> > > > > Author: Ian Rogers <irogers@google.com>
> > > > > Date:   Wed Aug 23 21:13:16 2023 -0700
> > > > >
> > > > >     perf jevents: Group events by PMU
> > > > >
> > > > >     Prior to this change a cpuid would map to a list of events where the PMU
> > > > >     would be encoded alongside the event information. This change breaks
> > > > >     apart each group of events so that there is a group per PMU. A new table
> > > > >     is added with the PMU's name and the list of events, the original table
> > > > >     now holding an array of these per PMU tables.
> > > > >
> > > > >     These changes are to make it easier to get per PMU information about
> > > > >     events, rather than the current approach of scanning all events. The
> > > > >     perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> > > > >     unidentified PMU is now always expanded to "cpu".
> > > > >
> > > > >     Signed-off-by: Ian Rogers <irogers@google.com>
> > > > >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> > > > >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> > > > >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> > > > >     Cc: Ingo Molnar <mingo@redhat.com>
> > > > >     Cc: James Clark <james.clark@arm.com>
> > > > >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> > > > >     Cc: Jiri Olsa <jolsa@kernel.org>
> > > > >     Cc: John Garry <john.g.garry@oracle.com>
> > > > >     Cc: Kajol Jain <kjain@linux.ibm.com>
> > > > >     Cc: Kan Liang <kan.liang@linux.intel.com>
> > > > >     Cc: Mark Rutland <mark.rutland@arm.com>
> > > > >     Cc: Namhyung Kim <namhyung@kernel.org>
> > > > >     Cc: Peter Zijlstra <peterz@infradead.org>
> > > > >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> > > > >     Cc: Rob Herring <robh@kernel.org>
> > > > >     Link: https://lore.kernel.org/r/20230824041330.266337-5-irogers@google.com
> > > > >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> > > > >
> > > > >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++++++++----------
> > > > >  tools/perf/tests/pmu-events.c    |  30 ++++---
> > > > >  2 files changed, 154 insertions(+), 57 deletions(-)
> > > > > [root@kernelqe3 linux]#
> > > > >
> > > >
> > > > This change defaulted events without a specified PMU to being for the
> > > > PMU 'cpu', so that events in pmu-events.c were associated with a PMU
> > > > and we could find per-PMU information easily. The test events have no
> > > > PMU and so this has broken s390 where the the PMU should be "cpum_cf".
> > > > It has probably also broken x86 hybrid and arm where their default PMU
> > > > isn't cpu. I'll work on a fix, but the problem will be limited to the
> > > > test.
> > >
> > > So, with your "default_core" branche we go to:
> > >
> > > [root@kernelqe3 linux]# perf test 10
> > >  10: PMU events                                                      :
> > >  10.1: PMU event table sanity                                        : Ok
> > >  10.2: PMU event map aliases                                         : Ok
> > >  10.3: Parsing of PMU event table metrics                            : Ok
> > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > > [root@kernelqe3 linux]# perf --version
> > > perf version 6.5.rc5.g3d63ae82aa12
> > > [root@kernelqe3 linux]#
> > >
> > > The other tests:
> > >
> > > [root@kernelqe3 linux]# perf --version
> > > perf version 6.5.rc5.g3d63ae82aa12
> > > [root@kernelqe3 linux]# perf test 6 10 'perf all metricgroups test' 'perf all metrics test'
> > >   6: Parse event definition strings                                  :
> > >   6.1: Test event parsing                                            : Ok
> > >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> > >   6.3: Parsing of given PMU events from sysfs                        : Ok
> > >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> > >   6.5: Parsing of aliased events                                     : FAILED!
> > >   6.6: Parsing of terms (event modifiers)                            : Ok
> > >  10: PMU events                                                      :
> > >  10.1: PMU event table sanity                                        : Ok
> > >  10.2: PMU event map aliases                                         : Ok
> > >  10.3: Parsing of PMU event table metrics                            : Ok
> > >  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
> > >  10.5: Parsing of metric thresholds with fake PMUs                   : Ok
> > >  93: perf all metricgroups test                                      : FAILED!
> > >  94: perf all metrics test                                           : FAILED!
> > > [root@kernelqe3 linux]#
> > >
> > > Trying to bisect it now.
> >
> > make: Leaving directory '/root/git/linux/tools/perf'
> > [root@kernelqe3 linux]# perf test 6
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          : FAILED!
> >   6.3: Parsing of given PMU events from sysfs                        : Ok
> >   6.4: Parsing of aliased events from sysfs                          : Skip (no aliases in sysfs)
> >   6.5: Parsing of aliased events                                     : FAILED!
> >   6.6: Parsing of terms (event modifiers)                            : Ok
> > [root@kernelqe3 linux]# git bisect bad
> > 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53 is the first bad commit
> > commit 8d4b6d37ea7862d230ad2e1bd4c7d2ff5e9acd53
> > Author: Ian Rogers <irogers@google.com>
> > Date:   Wed Aug 23 21:13:28 2023 -0700
> >
> >     perf pmu: Lazily load sysfs aliases
> >
> >     Don't load sysfs aliases for a PMU when the PMU is first created, defer
> >     until an alias needs to be found. For the pmu-scan benchmark, average
> >     core PMU scanning is reduced by 30.8%, and average PMU scanning by
> >     12.6%.
> >
> >     Signed-off-by: Ian Rogers <irogers@google.com>
> >     Cc: Adrian Hunter <adrian.hunter@intel.com>
> >     Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
> >     Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
> >     Cc: Ingo Molnar <mingo@redhat.com>
> >     Cc: James Clark <james.clark@arm.com>
> >     Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
> >     Cc: Jiri Olsa <jolsa@kernel.org>
> >     Cc: John Garry <john.g.garry@oracle.com>
> >     Cc: Kajol Jain <kjain@linux.ibm.com>
> >     Cc: Kan Liang <kan.liang@linux.intel.com>
> >     Cc: Mark Rutland <mark.rutland@arm.com>
> >     Cc: Namhyung Kim <namhyung@kernel.org>
> >     Cc: Peter Zijlstra <peterz@infradead.org>
> >     Cc: Ravi Bangoria <ravi.bangoria@amd.com>
> >     Cc: Rob Herring <robh@kernel.org>
> >     Link: https://lore.kernel.org/r/20230824041330.266337-17-irogers@google.com
> >     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> >
> >  tools/perf/tests/pmu-events.c |  2 ++
> >  tools/perf/util/pmu.c         | 81 ++++++++++++++++++++++---------------------
> >  tools/perf/util/pmu.h         |  2 ++
> >  3 files changed, 46 insertions(+), 39 deletions(-)
> > [root@kernelqe3 linux]#
> >
> > It is segfaulting:
> >
> >   6.2: Parsing of all PMU events from sysfs                          :
> > --- start ---
> > test child forked, pid 1202947
> > Using CPUID IBM,2964,400,N96,1.4,002f
> > perf: Segmentation fault
> > Obtained 16 stack frames.
> > perf(dump_stack+0x36) [0x1156dbe]
> > perf(sighandler_dump_stack+0x3a) [0x1156e8a]
> > [0x3fffd4790b6]
> > /lib64/libc.so.6(__strcasecmp+0x42) [0x3ffa889c51a]
> > perf() [0x11792ac]
> > perf(pmu_events_table__find_event+0x27c) [0x12432fc]
> > perf() [0x11777cc]
> > perf() [0x1179842]
> > perf(perf_pmu__check_alias+0x4f0) [0x1179e98]
> > perf(parse_events_add_pmu+0x72c) [0x1128e84]
> > perf(parse_events_parse+0x4d4) [0x11754d4]
> > perf(__parse_events+0xda) [0x112644a]
> > perf() [0x10cecb2]
> > perf() [0x10d3264]
> > perf() [0x10cb250]
> > perf(cmd_test+0x109e) [0x10cc756]
> > test child interrupted
> > ---- end ----
> > Parse event definition strings subtest 2: FAILED!
> >
> >
> > Starting program: /root/bin/perf test -F 6
> > [Thread debugging using libthread_db enabled]
> > Using host libthread_db library "/lib64/libthread_db.so.1".
> >   6: Parse event definition strings                                  :
> >   6.1: Test event parsing                                            : Ok
> >   6.2: Parsing of all PMU events from sysfs                          :
> > Program received signal SIGSEGV, Segmentation fault.
> > 0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
> > #0  0x000003fffcf1c51a in strcasecmp () from /lib64/libc.so.6
> > #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
> > #2  0x000000000123e82c in update_alias (pe=0x3ffffff8ac0, table=0x1555cb0 <pmu_events_map+160>, vdata=0x3ffffff8c40) at util/pmu.c:490
> > #3  0x000000000137b9dc in pmu_events_table.find_event ()
> > #4  0x000000000123ed4e in perf_pmu__new_alias (pmu=0x15ce490, name=0x23c2593 "L1I_ONDRAWER_MEM_SOURCED_WRITES", desc=0x0, val=0x0, val_fd=0x16058a0, pe=0x0) at util/pmu.c:569
> > #5  0x000000000123f370 in pmu_aliases_parse (pmu=0x15ce490) at util/pmu.c:673
> > #6  0x000000000123e3a2 in perf_pmu__find_alias (pmu=0x15ce490, name=0x238eb10 "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV", load=true) at util/pmu.c:432
> > #7  0x0000000001241bb2 in pmu_find_alias (pmu=0x15ce490, term=0x18409d0) at util/pmu.c:1439
> > #8  0x0000000001241f82 in perf_pmu__check_alias (pmu=0x15ce490, head_terms=0x21b14d0, info=0x3ffffffa238, err=0x3ffffffc4c8) at util/pmu.c:1519
> > #9  0x00000000011bbbd4 in parse_events_add_pmu (parse_state=0x3ffffffc2f0, list=0x21afec0, name=0x21c6430 "cpum_cf", head_config=0x21b14d0, auto_merge_stats=false, loc_=0x3ffffffb4d8) at util/parse-events.c:1351
> > #10 0x000000000123aa4c in parse_events_parse (_parse_state=0x3ffffffc2f0, scanner=0x15b9310) at util/parse-events.y:299
> > #11 0x00000000011bd190 in parse_events__scanner (str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", input=0x0, parse_state=0x3ffffffc2f0) at util/parse-events.c:1738
> > #12 0x00000000011bde00 in __parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", pmu_filter=0x0, err=0x3ffffffc4c8, fake_pmu=0x0, warn_if_reordered=true) at util/parse-events.c:2010
> > #13 0x0000000001121884 in parse_events (evlist=0x15b7030, str=0x3ffffffc68a "cpum_cf/event=L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV/u", err=0x3ffffffc4c8) at /root/git/linux/tools/perf/util/parse-events.h:40
> > #14 0x0000000001134084 in test_event (e=0x3ffffffc5e0) at tests/parse-events.c:2393
> > #15 0x00000000011349ec in test__pmu_events (test=0x156b860 <suite.parse_events>, subtest=1) at tests/parse-events.c:2551
> > #16 0x000000000111f884 in run_test (test=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:242
> > #17 0x000000000111fa1a in test_and_print (t=0x156b860 <suite.parse_events>, subtest=1) at tests/builtin-test.c:271
> > #18 0x00000000011203fa in __cmd_test (argc=1, argv=0x3ffffffe5d0, skiplist=0x0) at tests/builtin-test.c:442
> > #19 0x0000000001120cca in cmd_test (argc=1, argv=0x3ffffffe5d0) at tests/builtin-test.c:564
> > #20 0x00000000011713a4 in run_builtin (p=0x1561190 <commands+600>, argc=3, argv=0x3ffffffe5d0) at perf.c:322
> > #21 0x0000000001171712 in handle_internal_command (argc=3, argv=0x3ffffffe5d0) at perf.c:375
> > #22 0x0000000001171920 in run_argv (argcp=0x3ffffffe304, argv=0x3ffffffe2f8) at perf.c:419
> > #23 0x0000000001171ce8 in main (argc=3, argv=0x3ffffffe5d0) at perf.c:535
> > (gdb)
> >
> > (gdb) fr 1
> > #1  0x000000000123e518 in assign_str (name=0x1487cc3 "l1i_ondrawer_mem_sourced_writes", field=0x141eeba "value", old_str=0x18c12e0, new_str=0x1487d1f "event=0xb1") at util/pmu.c:449
> > 449             if (!new_str || !strcasecmp(*old_str, new_str))
> > (gdb) p new_str
> > $1 = 0x1487d1f "event=0xb1"
> > (gdb) p *old_str
> > $2 = 0x1 <error: Cannot access memory at address 0x1>
> > (gdb) p old_str
> > $3 = (char **) 0x18c12e0
> > (gdb)
> 
> I can't explain this, how come the line numbers don't agree with?
> https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=tmp.perf-tools-next#n449

Probably because this was done in a bisect? I'll redo it with what is in
tmp-perf.tools-next.

> The values are coming from the json event data. I'd need to see the
> generated pmu-events.c.

And provide this file

- Arnaldo

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs
  2023-08-29  9:20                     ` Jing Zhang
@ 2023-08-29 13:20                       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 39+ messages in thread
From: Arnaldo Carvalho de Melo @ 2023-08-29 13:20 UTC (permalink / raw)
  To: Jing Zhang
  Cc: Ian Rogers, Thomas Richter, Sumanth Korikkar, Heiko Carstens,
	Sven Schnelle, Jiri Olsa, James Clark, linux-perf-users,
	linux-kernel

Em Tue, Aug 29, 2023 at 05:20:09PM +0800, Jing Zhang escreveu:
> 在 2023/8/29 上午8:59, Ian Rogers 写道:
> > On Mon, Aug 28, 2023 at 10:53 AM Arnaldo Carvalho de Melo
> > I can't explain this, how come the line numbers don't agree with?
> > https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/tree/tools/perf/util/pmu.c?h=tmp.perf-tools-next#n449
> > 
> > The values are coming from the json event data. I'd need to see the
> > generated pmu-events.c.

Its at:

http://vger.kernel.org/~acme/perf/pmu-events.c.txt
 
> I pulled the lastest tmp.perf-tools-next, and build with JEVENT_ARCH=all on ARM(KunPeng) system. The test 10 also fails.

acme@roc-rk3399-pc:~/git/perf-tools-next$ git log --oneline -10
3d63ae82aa12 (HEAD -> perf-tools-next, quaco/perf-tools-next, perf-tools-next/tmp.perf-tools-next, five/perf-tools-next) perf jevents: Use "default_core" for events with no Unit
686cca7e97eb perf test stat_bpf_counters_cgrp: Enhance perf stat cgroup BPF counter test
a77abc103942 perf test shell stat_bpf_counters: Fix test on Intel
db02f820603e perf test shell record_bpf_filter: Skip 6.2 kernel
c96b84e89f8a libperf: Get rid of attr.id field
ee6906d247f1 perf tools: Convert to perf_record_header_attr_id()
fd36ca012e0c libperf: Add perf_record_header_attr_id()
bb7eb7458e52 perf tools: Handle old data in PERF_RECORD_ATTR
982d23d6e5e6 perf pmus: Skip duplicate PMUs and don't print list suffix by default
a700b0367364 perf pmus: Sort pmus by name then suffix
acme@roc-rk3399-pc:~/git/perf-tools-next$

Trying to do everything from scratch, to maybe avoid some leftover file
from a previous build:

acme@roc-rk3399-pc:~/git/perf-tools-next$ for a in tools/* ; do make -C $a clean; done
acme@roc-rk3399-pc:~/git/perf-tools-next$ rm -rf /tmp/build/$(basename $(pwd)) ; mkdir -p /tmp/build/$(basename $(pwd)) ;
acme@roc-rk3399-pc:~/git/perf-tools-next$ alias m='make -k DEBUG=1 BUILD_BPF_SKEL=1 CORESIGHT=1 O=/tmp/build/perf-tools-next -C tools/perf install-bin && git status && perf test python'

Then run the 'm' alias to build it, then:

root@roc-rk3399-pc:~# perf test -v 10 |& tail -40
Matched metric-id cpa_cycles to cpa_cycles
Matched metric-id cpa_p1_wr_dat to cpa_p1_wr_dat
Matched metric-id cpa_p1_rd_dat_64b to cpa_p1_rd_dat_64b
Matched metric-id cpa_p1_rd_dat_32b to cpa_p1_rd_dat_32b
Result nan
test child finished with 0
---- end ----
PMU events subtest 3: Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             :
--- start ---
test child forked, pid 12897
parsing '': '(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100.'
Using CPUID 0x00000000410fd082
perf: Segmentation fault
Obtained 16 stack frames.
perf(dump_stack+0x27) [0xaaaade0f19af]
perf(sighandler_dump_stack+0x33) [0xaaaade0f1a7f]
linux-vdso.so.1(+0x7a7) [0xffffa16967a7]
/lib/aarch64-linux-gnu/libc.so.6(__strcasecmp+0x2c) [0xffffa0841dac]
perf(+0x2233db) [0xaaaade1233db]
perf(+0x22364f) [0xaaaade12364f]
perf(+0x343143) [0xaaaade243143]
perf(pmu_events_table__find_event+0xa3) [0xaaaade24335f]
perf(+0x223a4b) [0xaaaade123a4b]
perf(+0x223f6b) [0xaaaade123f6b]
perf(+0x2232bb) [0xaaaade1232bb]
perf(perf_pmu__have_event+0x33) [0xaaaade1268f3]
perf(parse_events_multi_pmu_add+0x127) [0xaaaade0b7077]
perf(parse_events_parse+0xf3f) [0xaaaade120917]
perf(+0x1b7e6f) [0xaaaade0b7e6f]
perf(__parse_events+0xa3) [0xaaaade0b88c7]
test child interrupted
---- end ----
PMU events subtest 4: FAILED!
 10.5: Parsing of metric thresholds with fake PMUs                   :
--- start ---
test child forked, pid 12899
test child finished with 0
---- end ----
PMU events subtest 5: Ok
root@roc-rk3399-pc:~#

Doing it in gdb it doesn't crash, then I try with -F in gdb and it also
doesn't crash:

(gdb) run test -F 10
Starting program: /root/bin/perf test -F 10
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : Ok
 10.3: Parsing of PMU event table metrics                            :failed: recursion detected for M1
failed: recursion detected for M2
failed: recursion detected for M3
 Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
[Inferior 1 (process 12925) exited normally]
(gdb)

root@roc-rk3399-pc:~# perf test -F 10
 10: PMU events                                                      :
 10.1: PMU event table sanity                                        : Ok
 10.2: PMU event map aliases                                         : Ok
 10.3: Parsing of PMU event table metrics                            :failed: recursion detected for M1
failed: recursion detected for M2
failed: recursion detected for M3
 Ok
 10.4: Parsing of PMU event table metrics with fake PMUs             : Ok
 10.5: Parsing of metric thresholds with fake PMUs                   : Ok
root@roc-rk3399-pc:~#

root@roc-rk3399-pc:~# perf test -v -F 10 |& grep ": Ok"
PMU events subtest 1: Ok
PMU events subtest 2: Ok
PMU events subtest 3: Ok
PMU events subtest 4: Ok
PMU events subtest 5: Ok
root@roc-rk3399-pc:~#

Will continue investigating later...

- Arnaldo
 
> The bad commit maybe is "edb217f perf pmu: Parse sysfs events directly from a file". Hope it helps.
> 
> #git log --oneline -1
> 3d63ae8 perf jevents: Use "default_core" for events with no Unit
> 
> #./perf test 10
>  10: PMU events                                                      :
>  10.1: PMU event table sanity                                        : Ok
>  10.2: PMU event map aliases                                         : Ok
>  10.3: Parsing of PMU event table metrics                            : FAILED!
>  10.4: Parsing of PMU event table metrics with fake PMUs             : FAILED!
>  10.5: Parsing of metric thresholds with fake PMUs                   : FAILED!

 
> Found metric 'tsx_aborted_cycles'
> metric expr (max(cycles\-t - cycles\-ct, 0) / cycles if has_event(cycles\-t) else 0) for tsx_aborted_cycles
> parsing metric: (max(cycles\-t - cycles\-ct, 0) / cycles if has_event(cycles\-t) else 0)
> perf: Segmentation fault
> Obtained 16 stack frames.
> ./perf() [0x514a23]
> linux-vdso.so.1(+0x7c3) [0xffff8ac847c3]
> ./perf() [0x52bb08]
> ./perf() [0x52ffc3]
> ./perf() [0x4e8cab]
> ./perf() [0x4ea27b]
> ./perf() [0x532137]
> ./perf() [0x53273b]
> ./perf() [0x533ed7]
> ./perf() [0x4ed58b]
> ./perf() [0x530763]
> ./perf() [0x4e8c47]
> ./perf() [0x4ea5e3]
> ./perf() [0x4eaa8f]
> ./perf() [0x595393]
> ./perf() [0x593753]
> test child interrupted
> ---- end ----
> PMU events subtest 3: FAILED!
>  10.4: Parsing of PMU event table metrics with fake PMUs             :
> --- start ---
> test child forked, pid 24107
> parsing '': '(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100.'
> parsing metric: (unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100.
> Using CPUID 0x00000000481fd010
> perf: Segmentation fault
> Obtained 16 stack frames.
> ./perf() [0x514a23]
> linux-vdso.so.1(+0x7c3) [0xffff8ac847c3]
> ./perf() [0x52bb08]
> ./perf() [0x52ffc3]
> ./perf() [0x4e8cab]
> ./perf() [0x4ea27b]
> ./perf() [0x532137]
> ./perf() [0x53273b]
> ./perf() [0x533ed7]
> ./perf() [0x4ed58b]
> ./perf() [0x530763]
> ./perf() [0x4e8c47]
> ./perf() [0x4ea5e3]
> ./perf() [0x4a50b3]
> ./perf() [0x4a5343]
> ./perf() [0x48fef7]
> test child interrupted
> ---- end ----
> PMU events subtest 4: FAILED!
>  10.5: Parsing of metric thresholds with fake PMUs                   :
> --- start ---
> test child forked, pid 24108
> parsing 'tma_alloc_restriction': 'tma_alloc_restriction > 0.1'
> parsing metric: tma_alloc_restriction > 0.1
> Using CPUID 0x00000000481fd010
> perf: Segmentation fault
> Obtained 16 stack frames.
> ./perf() [0x514a23]
> linux-vdso.so.1(+0x7c3) [0xffff8ac847c3]
> ./perf() [0x52bb08]
> ./perf() [0x52ffc3]
> ./perf() [0x4e8cab]
> ./perf() [0x4ea27b]
> ./perf() [0x532137]
> ./perf() [0x53273b]
> ./perf() [0x533ed7]
> ./perf() [0x4ed58b]
> ./perf() [0x530763]
> ./perf() [0x4e8c47]
> ./perf() [0x4ea5e3]
> ./perf() [0x4a50b3]
> ./perf() [0x5dec0b]
> ./perf() [0x5df117]
> test child interrupted
> ---- end ----
> PMU events subtest 5: FAILED!

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 04/18] perf jevents: Group events by PMU
  2023-08-24  4:13 ` [PATCH v2 04/18] perf jevents: Group events by PMU Ian Rogers
@ 2023-08-29 15:28   ` James Clark
  2023-08-29 15:34     ` Ian Rogers
  0 siblings, 1 reply; 39+ messages in thread
From: James Clark @ 2023-08-29 15:28 UTC (permalink / raw)
  To: Ian Rogers
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Adrian Hunter, Kan Liang, John Garry, Kajol Jain, Jing Zhang,
	Ravi Bangoria, Rob Herring, Gaosheng Cui, linux-perf-users,
	linux-kernel



On 24/08/2023 05:13, Ian Rogers wrote:
> Prior to this change a cpuid would map to a list of events where the
> PMU would be encoded alongside the event information. This change
> breaks apart each group of events so that there is a group per PMU. A
> new table is added with the PMU's name and the list of events, the
> original table now holding an array of these per PMU tables.
> 
> These changes are to make it easier to get per PMU information about
> events, rather than the current approach of scanning all events. The
> perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> unidentified PMU is now always expanded to "cpu".
> 

Hi Ian,

I noticed that after this commit in perf-tools-next, events and
descriptions aren't printed by perf list anymore (on Arm). Only the
metrics and builtin kernel events are printed.

I'm not sure if this is something that's related to test failure that
Arnaldo mentioned on the cover letter, or something else.

I didn't look into the root cause yet, just thought I would mention it
first.

Thanks
James

> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++--------
>  tools/perf/tests/pmu-events.c    |  30 +++--
>  2 files changed, 154 insertions(+), 57 deletions(-)
> 
> diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> index aae5334099b1..1ad20140114c 100755
> --- a/tools/perf/pmu-events/jevents.py
> +++ b/tools/perf/pmu-events/jevents.py
> @@ -42,7 +42,7 @@ _metricgroups = {}
>  # Order specific JsonEvent attributes will be visited.
>  _json_event_attributes = [
>      # cmp_sevent related attributes.
> -    'name', 'pmu', 'topic', 'desc',
> +    'name', 'topic', 'desc',
>      # Seems useful, put it early.
>      'event',
>      # Short things in alphabetical order.
> @@ -53,7 +53,7 @@ _json_event_attributes = [
>  
>  # Attributes that are in pmu_metric rather than pmu_event.
>  _json_metric_attributes = [
> -    'pmu', 'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
> +    'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
>      'desc', 'long_desc', 'unit', 'compat', 'metricgroup_no_group',
>      'default_metricgroup_name', 'aggr_mode', 'event_grouping'
>  ]
> @@ -252,7 +252,7 @@ class JsonEvent:
>      def unit_to_pmu(unit: str) -> Optional[str]:
>        """Convert a JSON Unit to Linux PMU name."""
>        if not unit:
> -        return None
> +        return 'cpu'
>        # Comment brought over from jevents.c:
>        # it's not realistic to keep adding these, we need something more scalable ...
>        table = {
> @@ -343,10 +343,13 @@ class JsonEvent:
>        self.desc += extra_desc
>      if self.long_desc and extra_desc:
>        self.long_desc += extra_desc
> -    if self.pmu:
> -      if self.desc and not self.desc.endswith('. '):
> -        self.desc += '. '
> -      self.desc = (self.desc if self.desc else '') + ('Unit: ' + self.pmu + ' ')
> +    if self.pmu and self.pmu != 'cpu':
> +      if not self.desc:
> +        self.desc = 'Unit: ' + self.pmu
> +      else:
> +        if not self.desc.endswith('. '):
> +          self.desc += '. '
> +      self.desc += 'Unit: ' + self.pmu
>      if arch_std:
>        if arch_std.lower() in _arch_std_events:
>          event = _arch_std_events[arch_std.lower()].event
> @@ -437,13 +440,13 @@ def add_events_table_entries(item: os.DirEntry, topic: str) -> None:
>  def print_pending_events() -> None:
>    """Optionally close events table."""
>  
> -  def event_cmp_key(j: JsonEvent) -> Tuple[bool, str, str, str, str]:
> +  def event_cmp_key(j: JsonEvent) -> Tuple[str, str, bool, str, str]:
>      def fix_none(s: Optional[str]) -> str:
>        if s is None:
>          return ''
>        return s
>  
> -    return (j.desc is not None, fix_none(j.topic), fix_none(j.name), fix_none(j.pmu),
> +    return (fix_none(j.pmu).replace(',','_'), fix_none(j.name), j.desc is not None, fix_none(j.topic),
>              fix_none(j.metric_name))
>  
>    global _pending_events
> @@ -458,13 +461,36 @@ def print_pending_events() -> None:
>      global event_tables
>      _event_tables.append(_pending_events_tblname)
>  
> -  _args.output_file.write(
> -      f'static const struct compact_pmu_event {_pending_events_tblname}[] = {{\n')
> -
> +  first = True
> +  last_pmu = None
> +  pmus = set()
>    for event in sorted(_pending_events, key=event_cmp_key):
> +    if event.pmu != last_pmu:
> +      if not first:
> +        _args.output_file.write('};\n')
> +      pmu_name = event.pmu.replace(',', '_')
> +      _args.output_file.write(
> +          f'static const struct compact_pmu_event {_pending_events_tblname}_{pmu_name}[] = {{\n')
> +      first = False
> +      last_pmu = event.pmu
> +      pmus.add((event.pmu, pmu_name))
> +
>      _args.output_file.write(event.to_c_string(metric=False))
>    _pending_events = []
>  
> +  _args.output_file.write(f"""
> +}};
> +
> +const struct pmu_table_entry {_pending_events_tblname}[] = {{
> +""")
> +  for (pmu, tbl_pmu) in sorted(pmus):
> +    pmu_name = f"{pmu}\\000"
> +    _args.output_file.write(f"""{{
> +     .entries = {_pending_events_tblname}_{tbl_pmu},
> +     .num_entries = ARRAY_SIZE({_pending_events_tblname}_{tbl_pmu}),
> +     .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
> +}},
> +""")
>    _args.output_file.write('};\n\n')
>  
>  def print_pending_metrics() -> None:
> @@ -490,13 +516,36 @@ def print_pending_metrics() -> None:
>      global metric_tables
>      _metric_tables.append(_pending_metrics_tblname)
>  
> -  _args.output_file.write(
> -      f'static const struct compact_pmu_event {_pending_metrics_tblname}[] = {{\n')
> -
> +  first = True
> +  last_pmu = None
> +  pmus = set()
>    for metric in sorted(_pending_metrics, key=metric_cmp_key):
> +    if metric.pmu != last_pmu:
> +      if not first:
> +        _args.output_file.write('};\n')
> +      pmu_name = metric.pmu.replace(',', '_')
> +      _args.output_file.write(
> +          f'static const struct compact_pmu_event {_pending_metrics_tblname}_{pmu_name}[] = {{\n')
> +      first = False
> +      last_pmu = metric.pmu
> +      pmus.add((metric.pmu, pmu_name))
> +
>      _args.output_file.write(metric.to_c_string(metric=True))
>    _pending_metrics = []
>  
> +  _args.output_file.write(f"""
> +}};
> +
> +const struct pmu_table_entry {_pending_metrics_tblname}[] = {{
> +""")
> +  for (pmu, tbl_pmu) in sorted(pmus):
> +    pmu_name = f"{pmu}\\000"
> +    _args.output_file.write(f"""{{
> +     .entries = {_pending_metrics_tblname}_{tbl_pmu},
> +     .num_entries = ARRAY_SIZE({_pending_metrics_tblname}_{tbl_pmu}),
> +     .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
> +}},
> +""")
>    _args.output_file.write('};\n\n')
>  
>  def get_topic(topic: str) -> str:
> @@ -532,6 +581,8 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
>  
>    topic = get_topic(item.name)
>    for event in read_json_events(item.path, topic):
> +    pmu_name = f"{event.pmu}\\000"
> +    _bcs.add(pmu_name)
>      if event.name:
>        _bcs.add(event.build_c_string(metric=False))
>      if event.metric_name:
> @@ -577,14 +628,14 @@ def print_mapping_table(archs: Sequence[str]) -> None:
>    _args.output_file.write("""
>  /* Struct used to make the PMU event table implementation opaque to callers. */
>  struct pmu_events_table {
> -        const struct compact_pmu_event *entries;
> -        size_t length;
> +        const struct pmu_table_entry *pmus;
> +        uint32_t num_pmus;
>  };
>  
>  /* Struct used to make the PMU metric table implementation opaque to callers. */
>  struct pmu_metrics_table {
> -        const struct compact_pmu_event *entries;
> -        size_t length;
> +        const struct pmu_table_entry *pmus;
> +        uint32_t num_pmus;
>  };
>  
>  /*
> @@ -614,12 +665,12 @@ const struct pmu_events_map pmu_events_map[] = {
>  \t.arch = "testarch",
>  \t.cpuid = "testcpu",
>  \t.event_table = {
> -\t\t.entries = pmu_events__test_soc_cpu,
> -\t\t.length = ARRAY_SIZE(pmu_events__test_soc_cpu),
> +\t\t.pmus = pmu_events__test_soc_cpu,
> +\t\t.num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
>  \t},
>  \t.metric_table = {
> -\t\t.entries = pmu_metrics__test_soc_cpu,
> -\t\t.length = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
> +\t\t.pmus = pmu_metrics__test_soc_cpu,
> +\t\t.num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
>  \t}
>  },
>  """)
> @@ -649,12 +700,12 @@ const struct pmu_events_map pmu_events_map[] = {
>  \t.arch = "{arch}",
>  \t.cpuid = "{cpuid}",
>  \t.event_table = {{
> -\t\t.entries = {event_tblname},
> -\t\t.length = {event_size}
> +\t\t.pmus = {event_tblname},
> +\t\t.num_pmus = {event_size}
>  \t}},
>  \t.metric_table = {{
> -\t\t.entries = {metric_tblname},
> -\t\t.length = {metric_size}
> +\t\t.pmus = {metric_tblname},
> +\t\t.num_pmus = {metric_size}
>  \t}}
>  }},
>  """)
> @@ -685,15 +736,15 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = {
>    for tblname in _sys_event_tables:
>      _args.output_file.write(f"""\t{{
>  \t\t.event_table = {{
> -\t\t\t.entries = {tblname},
> -\t\t\t.length = ARRAY_SIZE({tblname})
> +\t\t\t.pmus = {tblname},
> +\t\t\t.num_pmus = ARRAY_SIZE({tblname})
>  \t\t}},""")
>      metric_tblname = _sys_event_table_to_metric_table_mapping[tblname]
>      if metric_tblname in _sys_metric_tables:
>        _args.output_file.write(f"""
>  \t\t.metric_table = {{
> -\t\t\t.entries = {metric_tblname},
> -\t\t\t.length = ARRAY_SIZE({metric_tblname})
> +\t\t\t.pmus = {metric_tblname},
> +\t\t\t.num_pmus = ARRAY_SIZE({metric_tblname})
>  \t\t}},""")
>        printed_metric_tables.append(metric_tblname)
>      _args.output_file.write(f"""
> @@ -753,18 +804,56 @@ static void decompress_metric(int offset, struct pmu_metric *pm)
>        _args.output_file.write('\twhile (*p++);')
>    _args.output_file.write("""}
>  
> +static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
> +                                                const struct pmu_table_entry *pmu,
> +                                                pmu_event_iter_fn fn,
> +                                                void *data)
> +{
> +        int ret;
> +        struct pmu_event pe = {
> +                .pmu = &big_c_string[pmu->pmu_name.offset],
> +        };
> +
> +        for (uint32_t i = 0; i < pmu->num_entries; i++) {
> +                decompress_event(pmu->entries[i].offset, &pe);
> +                if (!pe.name)
> +                        continue;
> +                ret = fn(&pe, table, data);
> +                if (ret)
> +                        return ret;
> +        }
> +        return 0;
> + }
> +
>  int pmu_events_table__for_each_event(const struct pmu_events_table *table,
>                                      pmu_event_iter_fn fn,
>                                      void *data)
>  {
> -        for (size_t i = 0; i < table->length; i++) {
> -                struct pmu_event pe;
> -                int ret;
> +        for (size_t i = 0; i < table->num_pmus; i++) {
> +                int ret = pmu_events_table__for_each_event_pmu(table, &table->pmus[i],
> +                                                               fn, data);
>  
> -                decompress_event(table->entries[i].offset, &pe);
> -                if (!pe.name)
> +                if (ret)
> +                        return ret;
> +        }
> +        return 0;
> +}
> +
> +static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
> +                                                const struct pmu_table_entry *pmu,
> +                                                pmu_metric_iter_fn fn,
> +                                                void *data)
> +{
> +        int ret;
> +        struct pmu_metric pm = {
> +                .pmu = &big_c_string[pmu->pmu_name.offset],
> +        };
> +
> +        for (uint32_t i = 0; i < pmu->num_entries; i++) {
> +                decompress_metric(pmu->entries[i].offset, &pm);
> +                if (!pm.metric_expr)
>                          continue;
> -                ret = fn(&pe, table, data);
> +                ret = fn(&pm, table, data);
>                  if (ret)
>                          return ret;
>          }
> @@ -775,14 +864,10 @@ int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
>                                       pmu_metric_iter_fn fn,
>                                       void *data)
>  {
> -        for (size_t i = 0; i < table->length; i++) {
> -                struct pmu_metric pm;
> -                int ret;
> +        for (size_t i = 0; i < table->num_pmus; i++) {
> +                int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
> +                                                                 fn, data);
>  
> -                decompress_metric(table->entries[i].offset, &pm);
> -                if (!pm.metric_expr)
> -                        continue;
> -                ret = fn(&pm, table, data);
>                  if (ret)
>                          return ret;
>          }
> @@ -1010,7 +1095,13 @@ such as "arm/cortex-a34".''',
>  #include <stddef.h>
>  
>  struct compact_pmu_event {
> -  int offset;
> +        int offset;
> +};
> +
> +struct pmu_table_entry {
> +        const struct compact_pmu_event *entries;
> +        uint32_t num_entries;
> +        struct compact_pmu_event pmu_name;
>  };
>  
>  """)
> diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
> index 5f541eadc088..0b6efabc3d20 100644
> --- a/tools/perf/tests/pmu-events.c
> +++ b/tools/perf/tests/pmu-events.c
> @@ -44,6 +44,7 @@ struct perf_pmu_test_pmu {
>  
>  static const struct perf_pmu_test_event bp_l1_btb_correct = {
>  	.event = {
> +		.pmu = "cpu",
>  		.name = "bp_l1_btb_correct",
>  		.event = "event=0x8a",
>  		.desc = "L1 BTB Correction",
> @@ -55,6 +56,7 @@ static const struct perf_pmu_test_event bp_l1_btb_correct = {
>  
>  static const struct perf_pmu_test_event bp_l2_btb_correct = {
>  	.event = {
> +		.pmu = "cpu",
>  		.name = "bp_l2_btb_correct",
>  		.event = "event=0x8b",
>  		.desc = "L2 BTB Correction",
> @@ -66,6 +68,7 @@ static const struct perf_pmu_test_event bp_l2_btb_correct = {
>  
>  static const struct perf_pmu_test_event segment_reg_loads_any = {
>  	.event = {
> +		.pmu = "cpu",
>  		.name = "segment_reg_loads.any",
>  		.event = "event=0x6,period=200000,umask=0x80",
>  		.desc = "Number of segment register loads",
> @@ -77,6 +80,7 @@ static const struct perf_pmu_test_event segment_reg_loads_any = {
>  
>  static const struct perf_pmu_test_event dispatch_blocked_any = {
>  	.event = {
> +		.pmu = "cpu",
>  		.name = "dispatch_blocked.any",
>  		.event = "event=0x9,period=200000,umask=0x20",
>  		.desc = "Memory cluster signals to block micro-op dispatch for any reason",
> @@ -88,6 +92,7 @@ static const struct perf_pmu_test_event dispatch_blocked_any = {
>  
>  static const struct perf_pmu_test_event eist_trans = {
>  	.event = {
> +		.pmu = "cpu",
>  		.name = "eist_trans",
>  		.event = "event=0x3a,period=200000,umask=0x0",
>  		.desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
> @@ -99,6 +104,7 @@ static const struct perf_pmu_test_event eist_trans = {
>  
>  static const struct perf_pmu_test_event l3_cache_rd = {
>  	.event = {
> +		.pmu = "cpu",
>  		.name = "l3_cache_rd",
>  		.event = "event=0x40",
>  		.desc = "L3 cache access, read",
> @@ -123,7 +129,7 @@ static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = {
>  	.event = {
>  		.name = "uncore_hisi_ddrc.flux_wcmd",
>  		.event = "event=0x2",
> -		.desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
> +		.desc = "DDRC write commands. Unit: hisi_sccl,ddrc",
>  		.topic = "uncore",
>  		.long_desc = "DDRC write commands",
>  		.pmu = "hisi_sccl,ddrc",
> @@ -137,7 +143,7 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = {
>  	.event = {
>  		.name = "unc_cbo_xsnp_response.miss_eviction",
>  		.event = "event=0x22,umask=0x81",
> -		.desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
> +		.desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox",
>  		.topic = "uncore",
>  		.long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
>  		.pmu = "uncore_cbox",
> @@ -151,7 +157,7 @@ static const struct perf_pmu_test_event uncore_hyphen = {
>  	.event = {
>  		.name = "event-hyphen",
>  		.event = "event=0xe0,umask=0x00",
> -		.desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
> +		.desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox",
>  		.topic = "uncore",
>  		.long_desc = "UNC_CBO_HYPHEN",
>  		.pmu = "uncore_cbox",
> @@ -165,7 +171,7 @@ static const struct perf_pmu_test_event uncore_two_hyph = {
>  	.event = {
>  		.name = "event-two-hyph",
>  		.event = "event=0xc0,umask=0x00",
> -		.desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
> +		.desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox",
>  		.topic = "uncore",
>  		.long_desc = "UNC_CBO_TWO_HYPH",
>  		.pmu = "uncore_cbox",
> @@ -179,7 +185,7 @@ static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = {
>  	.event = {
>  		.name = "uncore_hisi_l3c.rd_hit_cpipe",
>  		.event = "event=0x7",
> -		.desc = "Total read hits. Unit: hisi_sccl,l3c ",
> +		.desc = "Total read hits. Unit: hisi_sccl,l3c",
>  		.topic = "uncore",
>  		.long_desc = "Total read hits",
>  		.pmu = "hisi_sccl,l3c",
> @@ -193,7 +199,7 @@ static const struct perf_pmu_test_event uncore_imc_free_running_cache_miss = {
>  	.event = {
>  		.name = "uncore_imc_free_running.cache_miss",
>  		.event = "event=0x12",
> -		.desc = "Total cache misses. Unit: uncore_imc_free_running ",
> +		.desc = "Total cache misses. Unit: uncore_imc_free_running",
>  		.topic = "uncore",
>  		.long_desc = "Total cache misses",
>  		.pmu = "uncore_imc_free_running",
> @@ -207,7 +213,7 @@ static const struct perf_pmu_test_event uncore_imc_cache_hits = {
>  	.event = {
>  		.name = "uncore_imc.cache_hits",
>  		.event = "event=0x34",
> -		.desc = "Total cache hits. Unit: uncore_imc ",
> +		.desc = "Total cache hits. Unit: uncore_imc",
>  		.topic = "uncore",
>  		.long_desc = "Total cache hits",
>  		.pmu = "uncore_imc",
> @@ -232,13 +238,13 @@ static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = {
>  	.event = {
>  		.name = "sys_ddr_pmu.write_cycles",
>  		.event = "event=0x2b",
> -		.desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
> +		.desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu",
>  		.topic = "uncore",
>  		.pmu = "uncore_sys_ddr_pmu",
>  		.compat = "v8",
>  	},
>  	.alias_str = "event=0x2b",
> -	.alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
> +	.alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu",
>  	.matching_pmu = "uncore_sys_ddr_pmu",
>  };
>  
> @@ -246,13 +252,13 @@ static const struct perf_pmu_test_event sys_ccn_pmu_read_cycles = {
>  	.event = {
>  		.name = "sys_ccn_pmu.read_cycles",
>  		.event = "config=0x2c",
> -		.desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
> +		.desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu",
>  		.topic = "uncore",
>  		.pmu = "uncore_sys_ccn_pmu",
>  		.compat = "0x01",
>  	},
>  	.alias_str = "config=0x2c",
> -	.alias_long_desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
> +	.alias_long_desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu",
>  	.matching_pmu = "uncore_sys_ccn_pmu",
>  };
>  
> @@ -403,7 +409,7 @@ static int test__pmu_event_table_core_callback(const struct pmu_event *pe,
>  	struct perf_pmu_test_event const **test_event_table;
>  	bool found = false;
>  
> -	if (pe->pmu)
> +	if (strcmp(pe->pmu, "cpu"))
>  		test_event_table = &uncore_events[0];
>  	else
>  		test_event_table = &core_events[0];

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH v2 04/18] perf jevents: Group events by PMU
  2023-08-29 15:28   ` James Clark
@ 2023-08-29 15:34     ` Ian Rogers
  0 siblings, 0 replies; 39+ messages in thread
From: Ian Rogers @ 2023-08-29 15:34 UTC (permalink / raw)
  To: James Clark
  Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Adrian Hunter, Kan Liang, John Garry, Kajol Jain, Jing Zhang,
	Ravi Bangoria, Rob Herring, Gaosheng Cui, linux-perf-users,
	linux-kernel

On Tue, Aug 29, 2023 at 8:28 AM James Clark <james.clark@arm.com> wrote:
>
>
>
> On 24/08/2023 05:13, Ian Rogers wrote:
> > Prior to this change a cpuid would map to a list of events where the
> > PMU would be encoded alongside the event information. This change
> > breaks apart each group of events so that there is a group per PMU. A
> > new table is added with the PMU's name and the list of events, the
> > original table now holding an array of these per PMU tables.
> >
> > These changes are to make it easier to get per PMU information about
> > events, rather than the current approach of scanning all events. The
> > perf binary size with BPF skeletons on x86 is reduced by about 1%. The
> > unidentified PMU is now always expanded to "cpu".
> >
>
> Hi Ian,
>
> I noticed that after this commit in perf-tools-next, events and
> descriptions aren't printed by perf list anymore (on Arm). Only the
> metrics and builtin kernel events are printed.
>
> I'm not sure if this is something that's related to test failure that
> Arnaldo mentioned on the cover letter, or something else.
>
> I didn't look into the root cause yet, just thought I would mention it
> first.


Hi James,

There was a glitch in this patch assuming json events with no PMU were
defaulting to CPU, something that happens a lot in the perf code. The
later patch:
https://lore.kernel.org/lkml/20230826062203.1058041-1-irogers@google.com/
is supposed to address this.

Thanks,
Ian

> Thanks
> James
>
> > Signed-off-by: Ian Rogers <irogers@google.com>
> > ---
> >  tools/perf/pmu-events/jevents.py | 181 +++++++++++++++++++++++--------
> >  tools/perf/tests/pmu-events.c    |  30 +++--
> >  2 files changed, 154 insertions(+), 57 deletions(-)
> >
> > diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
> > index aae5334099b1..1ad20140114c 100755
> > --- a/tools/perf/pmu-events/jevents.py
> > +++ b/tools/perf/pmu-events/jevents.py
> > @@ -42,7 +42,7 @@ _metricgroups = {}
> >  # Order specific JsonEvent attributes will be visited.
> >  _json_event_attributes = [
> >      # cmp_sevent related attributes.
> > -    'name', 'pmu', 'topic', 'desc',
> > +    'name', 'topic', 'desc',
> >      # Seems useful, put it early.
> >      'event',
> >      # Short things in alphabetical order.
> > @@ -53,7 +53,7 @@ _json_event_attributes = [
> >
> >  # Attributes that are in pmu_metric rather than pmu_event.
> >  _json_metric_attributes = [
> > -    'pmu', 'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
> > +    'metric_name', 'metric_group', 'metric_expr', 'metric_threshold',
> >      'desc', 'long_desc', 'unit', 'compat', 'metricgroup_no_group',
> >      'default_metricgroup_name', 'aggr_mode', 'event_grouping'
> >  ]
> > @@ -252,7 +252,7 @@ class JsonEvent:
> >      def unit_to_pmu(unit: str) -> Optional[str]:
> >        """Convert a JSON Unit to Linux PMU name."""
> >        if not unit:
> > -        return None
> > +        return 'cpu'
> >        # Comment brought over from jevents.c:
> >        # it's not realistic to keep adding these, we need something more scalable ...
> >        table = {
> > @@ -343,10 +343,13 @@ class JsonEvent:
> >        self.desc += extra_desc
> >      if self.long_desc and extra_desc:
> >        self.long_desc += extra_desc
> > -    if self.pmu:
> > -      if self.desc and not self.desc.endswith('. '):
> > -        self.desc += '. '
> > -      self.desc = (self.desc if self.desc else '') + ('Unit: ' + self.pmu + ' ')
> > +    if self.pmu and self.pmu != 'cpu':
> > +      if not self.desc:
> > +        self.desc = 'Unit: ' + self.pmu
> > +      else:
> > +        if not self.desc.endswith('. '):
> > +          self.desc += '. '
> > +      self.desc += 'Unit: ' + self.pmu
> >      if arch_std:
> >        if arch_std.lower() in _arch_std_events:
> >          event = _arch_std_events[arch_std.lower()].event
> > @@ -437,13 +440,13 @@ def add_events_table_entries(item: os.DirEntry, topic: str) -> None:
> >  def print_pending_events() -> None:
> >    """Optionally close events table."""
> >
> > -  def event_cmp_key(j: JsonEvent) -> Tuple[bool, str, str, str, str]:
> > +  def event_cmp_key(j: JsonEvent) -> Tuple[str, str, bool, str, str]:
> >      def fix_none(s: Optional[str]) -> str:
> >        if s is None:
> >          return ''
> >        return s
> >
> > -    return (j.desc is not None, fix_none(j.topic), fix_none(j.name), fix_none(j.pmu),
> > +    return (fix_none(j.pmu).replace(',','_'), fix_none(j.name), j.desc is not None, fix_none(j.topic),
> >              fix_none(j.metric_name))
> >
> >    global _pending_events
> > @@ -458,13 +461,36 @@ def print_pending_events() -> None:
> >      global event_tables
> >      _event_tables.append(_pending_events_tblname)
> >
> > -  _args.output_file.write(
> > -      f'static const struct compact_pmu_event {_pending_events_tblname}[] = {{\n')
> > -
> > +  first = True
> > +  last_pmu = None
> > +  pmus = set()
> >    for event in sorted(_pending_events, key=event_cmp_key):
> > +    if event.pmu != last_pmu:
> > +      if not first:
> > +        _args.output_file.write('};\n')
> > +      pmu_name = event.pmu.replace(',', '_')
> > +      _args.output_file.write(
> > +          f'static const struct compact_pmu_event {_pending_events_tblname}_{pmu_name}[] = {{\n')
> > +      first = False
> > +      last_pmu = event.pmu
> > +      pmus.add((event.pmu, pmu_name))
> > +
> >      _args.output_file.write(event.to_c_string(metric=False))
> >    _pending_events = []
> >
> > +  _args.output_file.write(f"""
> > +}};
> > +
> > +const struct pmu_table_entry {_pending_events_tblname}[] = {{
> > +""")
> > +  for (pmu, tbl_pmu) in sorted(pmus):
> > +    pmu_name = f"{pmu}\\000"
> > +    _args.output_file.write(f"""{{
> > +     .entries = {_pending_events_tblname}_{tbl_pmu},
> > +     .num_entries = ARRAY_SIZE({_pending_events_tblname}_{tbl_pmu}),
> > +     .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
> > +}},
> > +""")
> >    _args.output_file.write('};\n\n')
> >
> >  def print_pending_metrics() -> None:
> > @@ -490,13 +516,36 @@ def print_pending_metrics() -> None:
> >      global metric_tables
> >      _metric_tables.append(_pending_metrics_tblname)
> >
> > -  _args.output_file.write(
> > -      f'static const struct compact_pmu_event {_pending_metrics_tblname}[] = {{\n')
> > -
> > +  first = True
> > +  last_pmu = None
> > +  pmus = set()
> >    for metric in sorted(_pending_metrics, key=metric_cmp_key):
> > +    if metric.pmu != last_pmu:
> > +      if not first:
> > +        _args.output_file.write('};\n')
> > +      pmu_name = metric.pmu.replace(',', '_')
> > +      _args.output_file.write(
> > +          f'static const struct compact_pmu_event {_pending_metrics_tblname}_{pmu_name}[] = {{\n')
> > +      first = False
> > +      last_pmu = metric.pmu
> > +      pmus.add((metric.pmu, pmu_name))
> > +
> >      _args.output_file.write(metric.to_c_string(metric=True))
> >    _pending_metrics = []
> >
> > +  _args.output_file.write(f"""
> > +}};
> > +
> > +const struct pmu_table_entry {_pending_metrics_tblname}[] = {{
> > +""")
> > +  for (pmu, tbl_pmu) in sorted(pmus):
> > +    pmu_name = f"{pmu}\\000"
> > +    _args.output_file.write(f"""{{
> > +     .entries = {_pending_metrics_tblname}_{tbl_pmu},
> > +     .num_entries = ARRAY_SIZE({_pending_metrics_tblname}_{tbl_pmu}),
> > +     .pmu_name = {{ {_bcs.offsets[pmu_name]} /* {pmu_name} */ }},
> > +}},
> > +""")
> >    _args.output_file.write('};\n\n')
> >
> >  def get_topic(topic: str) -> str:
> > @@ -532,6 +581,8 @@ def preprocess_one_file(parents: Sequence[str], item: os.DirEntry) -> None:
> >
> >    topic = get_topic(item.name)
> >    for event in read_json_events(item.path, topic):
> > +    pmu_name = f"{event.pmu}\\000"
> > +    _bcs.add(pmu_name)
> >      if event.name:
> >        _bcs.add(event.build_c_string(metric=False))
> >      if event.metric_name:
> > @@ -577,14 +628,14 @@ def print_mapping_table(archs: Sequence[str]) -> None:
> >    _args.output_file.write("""
> >  /* Struct used to make the PMU event table implementation opaque to callers. */
> >  struct pmu_events_table {
> > -        const struct compact_pmu_event *entries;
> > -        size_t length;
> > +        const struct pmu_table_entry *pmus;
> > +        uint32_t num_pmus;
> >  };
> >
> >  /* Struct used to make the PMU metric table implementation opaque to callers. */
> >  struct pmu_metrics_table {
> > -        const struct compact_pmu_event *entries;
> > -        size_t length;
> > +        const struct pmu_table_entry *pmus;
> > +        uint32_t num_pmus;
> >  };
> >
> >  /*
> > @@ -614,12 +665,12 @@ const struct pmu_events_map pmu_events_map[] = {
> >  \t.arch = "testarch",
> >  \t.cpuid = "testcpu",
> >  \t.event_table = {
> > -\t\t.entries = pmu_events__test_soc_cpu,
> > -\t\t.length = ARRAY_SIZE(pmu_events__test_soc_cpu),
> > +\t\t.pmus = pmu_events__test_soc_cpu,
> > +\t\t.num_pmus = ARRAY_SIZE(pmu_events__test_soc_cpu),
> >  \t},
> >  \t.metric_table = {
> > -\t\t.entries = pmu_metrics__test_soc_cpu,
> > -\t\t.length = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
> > +\t\t.pmus = pmu_metrics__test_soc_cpu,
> > +\t\t.num_pmus = ARRAY_SIZE(pmu_metrics__test_soc_cpu),
> >  \t}
> >  },
> >  """)
> > @@ -649,12 +700,12 @@ const struct pmu_events_map pmu_events_map[] = {
> >  \t.arch = "{arch}",
> >  \t.cpuid = "{cpuid}",
> >  \t.event_table = {{
> > -\t\t.entries = {event_tblname},
> > -\t\t.length = {event_size}
> > +\t\t.pmus = {event_tblname},
> > +\t\t.num_pmus = {event_size}
> >  \t}},
> >  \t.metric_table = {{
> > -\t\t.entries = {metric_tblname},
> > -\t\t.length = {metric_size}
> > +\t\t.pmus = {metric_tblname},
> > +\t\t.num_pmus = {metric_size}
> >  \t}}
> >  }},
> >  """)
> > @@ -685,15 +736,15 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = {
> >    for tblname in _sys_event_tables:
> >      _args.output_file.write(f"""\t{{
> >  \t\t.event_table = {{
> > -\t\t\t.entries = {tblname},
> > -\t\t\t.length = ARRAY_SIZE({tblname})
> > +\t\t\t.pmus = {tblname},
> > +\t\t\t.num_pmus = ARRAY_SIZE({tblname})
> >  \t\t}},""")
> >      metric_tblname = _sys_event_table_to_metric_table_mapping[tblname]
> >      if metric_tblname in _sys_metric_tables:
> >        _args.output_file.write(f"""
> >  \t\t.metric_table = {{
> > -\t\t\t.entries = {metric_tblname},
> > -\t\t\t.length = ARRAY_SIZE({metric_tblname})
> > +\t\t\t.pmus = {metric_tblname},
> > +\t\t\t.num_pmus = ARRAY_SIZE({metric_tblname})
> >  \t\t}},""")
> >        printed_metric_tables.append(metric_tblname)
> >      _args.output_file.write(f"""
> > @@ -753,18 +804,56 @@ static void decompress_metric(int offset, struct pmu_metric *pm)
> >        _args.output_file.write('\twhile (*p++);')
> >    _args.output_file.write("""}
> >
> > +static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *table,
> > +                                                const struct pmu_table_entry *pmu,
> > +                                                pmu_event_iter_fn fn,
> > +                                                void *data)
> > +{
> > +        int ret;
> > +        struct pmu_event pe = {
> > +                .pmu = &big_c_string[pmu->pmu_name.offset],
> > +        };
> > +
> > +        for (uint32_t i = 0; i < pmu->num_entries; i++) {
> > +                decompress_event(pmu->entries[i].offset, &pe);
> > +                if (!pe.name)
> > +                        continue;
> > +                ret = fn(&pe, table, data);
> > +                if (ret)
> > +                        return ret;
> > +        }
> > +        return 0;
> > + }
> > +
> >  int pmu_events_table__for_each_event(const struct pmu_events_table *table,
> >                                      pmu_event_iter_fn fn,
> >                                      void *data)
> >  {
> > -        for (size_t i = 0; i < table->length; i++) {
> > -                struct pmu_event pe;
> > -                int ret;
> > +        for (size_t i = 0; i < table->num_pmus; i++) {
> > +                int ret = pmu_events_table__for_each_event_pmu(table, &table->pmus[i],
> > +                                                               fn, data);
> >
> > -                decompress_event(table->entries[i].offset, &pe);
> > -                if (!pe.name)
> > +                if (ret)
> > +                        return ret;
> > +        }
> > +        return 0;
> > +}
> > +
> > +static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
> > +                                                const struct pmu_table_entry *pmu,
> > +                                                pmu_metric_iter_fn fn,
> > +                                                void *data)
> > +{
> > +        int ret;
> > +        struct pmu_metric pm = {
> > +                .pmu = &big_c_string[pmu->pmu_name.offset],
> > +        };
> > +
> > +        for (uint32_t i = 0; i < pmu->num_entries; i++) {
> > +                decompress_metric(pmu->entries[i].offset, &pm);
> > +                if (!pm.metric_expr)
> >                          continue;
> > -                ret = fn(&pe, table, data);
> > +                ret = fn(&pm, table, data);
> >                  if (ret)
> >                          return ret;
> >          }
> > @@ -775,14 +864,10 @@ int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table,
> >                                       pmu_metric_iter_fn fn,
> >                                       void *data)
> >  {
> > -        for (size_t i = 0; i < table->length; i++) {
> > -                struct pmu_metric pm;
> > -                int ret;
> > +        for (size_t i = 0; i < table->num_pmus; i++) {
> > +                int ret = pmu_metrics_table__for_each_metric_pmu(table, &table->pmus[i],
> > +                                                                 fn, data);
> >
> > -                decompress_metric(table->entries[i].offset, &pm);
> > -                if (!pm.metric_expr)
> > -                        continue;
> > -                ret = fn(&pm, table, data);
> >                  if (ret)
> >                          return ret;
> >          }
> > @@ -1010,7 +1095,13 @@ such as "arm/cortex-a34".''',
> >  #include <stddef.h>
> >
> >  struct compact_pmu_event {
> > -  int offset;
> > +        int offset;
> > +};
> > +
> > +struct pmu_table_entry {
> > +        const struct compact_pmu_event *entries;
> > +        uint32_t num_entries;
> > +        struct compact_pmu_event pmu_name;
> >  };
> >
> >  """)
> > diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
> > index 5f541eadc088..0b6efabc3d20 100644
> > --- a/tools/perf/tests/pmu-events.c
> > +++ b/tools/perf/tests/pmu-events.c
> > @@ -44,6 +44,7 @@ struct perf_pmu_test_pmu {
> >
> >  static const struct perf_pmu_test_event bp_l1_btb_correct = {
> >       .event = {
> > +             .pmu = "cpu",
> >               .name = "bp_l1_btb_correct",
> >               .event = "event=0x8a",
> >               .desc = "L1 BTB Correction",
> > @@ -55,6 +56,7 @@ static const struct perf_pmu_test_event bp_l1_btb_correct = {
> >
> >  static const struct perf_pmu_test_event bp_l2_btb_correct = {
> >       .event = {
> > +             .pmu = "cpu",
> >               .name = "bp_l2_btb_correct",
> >               .event = "event=0x8b",
> >               .desc = "L2 BTB Correction",
> > @@ -66,6 +68,7 @@ static const struct perf_pmu_test_event bp_l2_btb_correct = {
> >
> >  static const struct perf_pmu_test_event segment_reg_loads_any = {
> >       .event = {
> > +             .pmu = "cpu",
> >               .name = "segment_reg_loads.any",
> >               .event = "event=0x6,period=200000,umask=0x80",
> >               .desc = "Number of segment register loads",
> > @@ -77,6 +80,7 @@ static const struct perf_pmu_test_event segment_reg_loads_any = {
> >
> >  static const struct perf_pmu_test_event dispatch_blocked_any = {
> >       .event = {
> > +             .pmu = "cpu",
> >               .name = "dispatch_blocked.any",
> >               .event = "event=0x9,period=200000,umask=0x20",
> >               .desc = "Memory cluster signals to block micro-op dispatch for any reason",
> > @@ -88,6 +92,7 @@ static const struct perf_pmu_test_event dispatch_blocked_any = {
> >
> >  static const struct perf_pmu_test_event eist_trans = {
> >       .event = {
> > +             .pmu = "cpu",
> >               .name = "eist_trans",
> >               .event = "event=0x3a,period=200000,umask=0x0",
> >               .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
> > @@ -99,6 +104,7 @@ static const struct perf_pmu_test_event eist_trans = {
> >
> >  static const struct perf_pmu_test_event l3_cache_rd = {
> >       .event = {
> > +             .pmu = "cpu",
> >               .name = "l3_cache_rd",
> >               .event = "event=0x40",
> >               .desc = "L3 cache access, read",
> > @@ -123,7 +129,7 @@ static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = {
> >       .event = {
> >               .name = "uncore_hisi_ddrc.flux_wcmd",
> >               .event = "event=0x2",
> > -             .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
> > +             .desc = "DDRC write commands. Unit: hisi_sccl,ddrc",
> >               .topic = "uncore",
> >               .long_desc = "DDRC write commands",
> >               .pmu = "hisi_sccl,ddrc",
> > @@ -137,7 +143,7 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = {
> >       .event = {
> >               .name = "unc_cbo_xsnp_response.miss_eviction",
> >               .event = "event=0x22,umask=0x81",
> > -             .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
> > +             .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox",
> >               .topic = "uncore",
> >               .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
> >               .pmu = "uncore_cbox",
> > @@ -151,7 +157,7 @@ static const struct perf_pmu_test_event uncore_hyphen = {
> >       .event = {
> >               .name = "event-hyphen",
> >               .event = "event=0xe0,umask=0x00",
> > -             .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
> > +             .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox",
> >               .topic = "uncore",
> >               .long_desc = "UNC_CBO_HYPHEN",
> >               .pmu = "uncore_cbox",
> > @@ -165,7 +171,7 @@ static const struct perf_pmu_test_event uncore_two_hyph = {
> >       .event = {
> >               .name = "event-two-hyph",
> >               .event = "event=0xc0,umask=0x00",
> > -             .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
> > +             .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox",
> >               .topic = "uncore",
> >               .long_desc = "UNC_CBO_TWO_HYPH",
> >               .pmu = "uncore_cbox",
> > @@ -179,7 +185,7 @@ static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = {
> >       .event = {
> >               .name = "uncore_hisi_l3c.rd_hit_cpipe",
> >               .event = "event=0x7",
> > -             .desc = "Total read hits. Unit: hisi_sccl,l3c ",
> > +             .desc = "Total read hits. Unit: hisi_sccl,l3c",
> >               .topic = "uncore",
> >               .long_desc = "Total read hits",
> >               .pmu = "hisi_sccl,l3c",
> > @@ -193,7 +199,7 @@ static const struct perf_pmu_test_event uncore_imc_free_running_cache_miss = {
> >       .event = {
> >               .name = "uncore_imc_free_running.cache_miss",
> >               .event = "event=0x12",
> > -             .desc = "Total cache misses. Unit: uncore_imc_free_running ",
> > +             .desc = "Total cache misses. Unit: uncore_imc_free_running",
> >               .topic = "uncore",
> >               .long_desc = "Total cache misses",
> >               .pmu = "uncore_imc_free_running",
> > @@ -207,7 +213,7 @@ static const struct perf_pmu_test_event uncore_imc_cache_hits = {
> >       .event = {
> >               .name = "uncore_imc.cache_hits",
> >               .event = "event=0x34",
> > -             .desc = "Total cache hits. Unit: uncore_imc ",
> > +             .desc = "Total cache hits. Unit: uncore_imc",
> >               .topic = "uncore",
> >               .long_desc = "Total cache hits",
> >               .pmu = "uncore_imc",
> > @@ -232,13 +238,13 @@ static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = {
> >       .event = {
> >               .name = "sys_ddr_pmu.write_cycles",
> >               .event = "event=0x2b",
> > -             .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
> > +             .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu",
> >               .topic = "uncore",
> >               .pmu = "uncore_sys_ddr_pmu",
> >               .compat = "v8",
> >       },
> >       .alias_str = "event=0x2b",
> > -     .alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
> > +     .alias_long_desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu",
> >       .matching_pmu = "uncore_sys_ddr_pmu",
> >  };
> >
> > @@ -246,13 +252,13 @@ static const struct perf_pmu_test_event sys_ccn_pmu_read_cycles = {
> >       .event = {
> >               .name = "sys_ccn_pmu.read_cycles",
> >               .event = "config=0x2c",
> > -             .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
> > +             .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu",
> >               .topic = "uncore",
> >               .pmu = "uncore_sys_ccn_pmu",
> >               .compat = "0x01",
> >       },
> >       .alias_str = "config=0x2c",
> > -     .alias_long_desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
> > +     .alias_long_desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu",
> >       .matching_pmu = "uncore_sys_ccn_pmu",
> >  };
> >
> > @@ -403,7 +409,7 @@ static int test__pmu_event_table_core_callback(const struct pmu_event *pe,
> >       struct perf_pmu_test_event const **test_event_table;
> >       bool found = false;
> >
> > -     if (pe->pmu)
> > +     if (strcmp(pe->pmu, "cpu"))
> >               test_event_table = &uncore_events[0];
> >       else
> >               test_event_table = &core_events[0];

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2023-08-29 15:35 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-24  4:13 [PATCH v2 00/18] Lazily load PMU data Ian Rogers
2023-08-24  4:13 ` [PATCH v2 01/18] perf pmu: Make the loading of formats lazy Ian Rogers
2023-08-24  4:13 ` [PATCH v2 02/18] perf pmu: Abstract alias/event struct Ian Rogers
2023-08-24  4:13 ` [PATCH v2 03/18] perf pmu-events: Add extra underscore to function names Ian Rogers
2023-08-24  4:13 ` [PATCH v2 04/18] perf jevents: Group events by PMU Ian Rogers
2023-08-29 15:28   ` James Clark
2023-08-29 15:34     ` Ian Rogers
2023-08-24  4:13 ` [PATCH v2 05/18] perf parse-events: Improve error message for double setting Ian Rogers
2023-08-24  4:13 ` [PATCH v2 06/18] perf s390 s390_cpumcfdg_dump: Don't scan all PMUs Ian Rogers
2023-08-24 13:59   ` Arnaldo Carvalho de Melo
2023-08-24 17:31     ` Ian Rogers
2023-08-25  8:19     ` Thomas Richter
2023-08-25 13:14       ` Ian Rogers
2023-08-25 14:39         ` Thomas Richter
2023-08-25 20:56           ` Arnaldo Carvalho de Melo
2023-08-25 22:56             ` Ian Rogers
2023-08-26  1:38               ` Arnaldo Carvalho de Melo
2023-08-26  6:28                 ` Ian Rogers
2023-08-28 17:44               ` Arnaldo Carvalho de Melo
2023-08-28 17:53                 ` Arnaldo Carvalho de Melo
2023-08-28 21:39                   ` Arnaldo Carvalho de Melo
2023-08-29  0:59                   ` Ian Rogers
2023-08-29  9:20                     ` Jing Zhang
2023-08-29 13:20                       ` Arnaldo Carvalho de Melo
2023-08-29 11:28                     ` Arnaldo Carvalho de Melo
2023-08-24  4:13 ` [PATCH v2 07/18] perf pmu-events: Reduce processed events by passing PMU Ian Rogers
2023-08-24  4:13 ` [PATCH v2 08/18] perf pmu-events: Add pmu_events_table__find_event Ian Rogers
2023-08-24  4:13 ` [PATCH v2 09/18] perf pmu: Parse sysfs events directly from a file Ian Rogers
2023-08-24  4:13 ` [PATCH v2 10/18] perf pmu: Prefer passing pmu to aliases list Ian Rogers
2023-08-24  4:13 ` [PATCH v2 11/18] perf pmu: Merge json events with sysfs at load time Ian Rogers
2023-08-24  4:13 ` [PATCH v2 12/18] perf pmu: Cache json events table Ian Rogers
2023-08-24  4:13 ` [PATCH v2 13/18] perf pmu: Lazily add json events Ian Rogers
2023-08-24  4:13 ` [PATCH v2 14/18] perf pmu: Scan type early to fail an invalid PMU quickly Ian Rogers
2023-08-24  4:13 ` [PATCH v2 15/18] perf pmu: Be lazy about loading event info files from sysfs Ian Rogers
2023-08-24  4:13 ` [PATCH v2 16/18] perf pmu: Lazily load sysfs aliases Ian Rogers
2023-08-24  4:13 ` [PATCH v2 17/18] perf jevents: Sort strings in the big C string to reduce faults Ian Rogers
2023-08-24  4:13 ` [PATCH v2 18/18] perf jevents: Don't append Unit to desc Ian Rogers
2023-08-24 14:52 ` [PATCH v2 00/18] Lazily load PMU data Arnaldo Carvalho de Melo
2023-08-24 18:01   ` Ian Rogers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).