312 lines
9.0 KiB
Diff
312 lines
9.0 KiB
Diff
From 44fb932a73686d9d773162e3a9c912b1caf4ce3c Mon Sep 17 00:00:00 2001
|
|
From: Ian Rogers <irogers@google.com>
|
|
Date: Wed, 13 May 2020 14:29:33 -0700
|
|
Subject: [PATCH 075/201] perf test: Improve pmu event metric testing
|
|
|
|
mainline inclusion
|
|
from mainline-v5.8-rc1
|
|
commit 06392aaad592cadf4335617a2bb8e45722e3df33
|
|
category: feature
|
|
bugzilla: https://gitee.com/openeuler/kernel/issues/I8C0CX
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=06392aaad592cadf4335617a2bb8e45722e3df33
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
Break pmu-events test into 2 and add a test to verify that all pmu
|
|
metric expressions simply parse. Try to parse all metric ids/events,
|
|
skip/warn if metrics for the current architecture fail to parse. To
|
|
support warning for a skip, and an ability for a subtest to describe why
|
|
it skips.
|
|
|
|
Tested on power9, skylakex, haswell, broadwell, westmere, sandybridge and
|
|
ivybridge.
|
|
|
|
May skip/warn on other architectures if metrics are invalid. In
|
|
particular s390 is untested, but its expressions are trivial. The
|
|
untested architectures with expressions are power8, cascadelakex,
|
|
tremontx, skylake, jaketown, ivytown and variants of haswell and
|
|
broadwell.
|
|
|
|
v3. addresses review comments from John Garry <john.garry@huawei.com>,
|
|
Jiri Olsa <jolsa@redhat.com> and Arnaldo Carvalho de Melo
|
|
<acme@kernel.org>.
|
|
v2. changes the commit message as event parsing errors no longer cause
|
|
the test to fail.
|
|
|
|
Committer notes:
|
|
|
|
Check the return value of strtod() to fix the build in systems where
|
|
that function is declared with attribute warn_unused_result.
|
|
|
|
Signed-off-by: Ian Rogers <irogers@google.com>
|
|
Cc: Adrian Hunter <adrian.hunter@intel.com>
|
|
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
|
Cc: Andi Kleen <ak@linux.intel.com>
|
|
Cc: Jin Yao <yao.jin@linux.intel.com>
|
|
Cc: Jiri Olsa <jolsa@redhat.com>
|
|
Cc: John Garry <john.garry@huawei.com>
|
|
Cc: Kajol Jain <kjain@linux.ibm.com>
|
|
Cc: Kan Liang <kan.liang@linux.intel.com>
|
|
Cc: Leo Yan <leo.yan@linaro.org>
|
|
Cc: Mark Rutland <mark.rutland@arm.com>
|
|
Cc: Namhyung Kim <namhyung@kernel.org>
|
|
Cc: Paul Clarke <pc@us.ibm.com>
|
|
Cc: Peter Zijlstra <peterz@infradead.org>
|
|
Cc: Stephane Eranian <eranian@google.com>
|
|
Link: http://lore.kernel.org/lkml/20200513212933.41273-1-irogers@google.com
|
|
[ split from a larger patch ]
|
|
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
|
|
Signed-off-by: hongrongxuan <hongrongxuan@huawei.com>
|
|
|
|
Conflicts:
|
|
tools/perf/tests/pmu-events.c
|
|
---
|
|
tools/perf/tests/builtin-test.c | 7 ++
|
|
tools/perf/tests/pmu-events.c | 170 ++++++++++++++++++++++++++++++--
|
|
tools/perf/tests/tests.h | 3 +
|
|
3 files changed, 174 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
|
|
index 729b6235ae43..1925f170478c 100644
|
|
--- a/tools/perf/tests/builtin-test.c
|
|
+++ b/tools/perf/tests/builtin-test.c
|
|
@@ -72,6 +72,13 @@ static struct test generic_tests[] = {
|
|
{
|
|
.desc = "PMU events",
|
|
.func = test__pmu_events,
|
|
+ .subtest = {
|
|
+ .skip_if_fail = false,
|
|
+ .get_nr = test__pmu_events_subtest_get_nr,
|
|
+ .get_desc = test__pmu_events_subtest_get_desc,
|
|
+ .skip_reason = test__pmu_events_subtest_skip_reason,
|
|
+ },
|
|
+
|
|
},
|
|
{
|
|
.desc = "DSO data read",
|
|
diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
|
|
index c1f5aeec3a41..233806382300 100644
|
|
--- a/tools/perf/tests/pmu-events.c
|
|
+++ b/tools/perf/tests/pmu-events.c
|
|
@@ -1,4 +1,5 @@
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
+#include "math.h"
|
|
#include "parse-events.h"
|
|
#include "pmu.h"
|
|
#include "tests.h"
|
|
@@ -8,6 +9,9 @@
|
|
#include "util.h"
|
|
#include "debug.h"
|
|
#include "../pmu-events/pmu-events.h"
|
|
+#include "util/evlist.h"
|
|
+#include "util/expr.h"
|
|
+#include "util/parse-events.h"
|
|
|
|
struct perf_pmu_test_event {
|
|
struct pmu_event event;
|
|
@@ -144,7 +148,7 @@ static struct pmu_events_map *__test_pmu_get_events_map(void)
|
|
}
|
|
|
|
/* Verify generated events from pmu-events.c is as expected */
|
|
-static int __test_pmu_event_table(void)
|
|
+static int test_pmu_event_table(void)
|
|
{
|
|
struct pmu_events_map *map = __test_pmu_get_events_map();
|
|
struct pmu_event *table;
|
|
@@ -347,14 +351,11 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count)
|
|
return res;
|
|
}
|
|
|
|
-int test__pmu_events(struct test *test __maybe_unused,
|
|
- int subtest __maybe_unused)
|
|
+
|
|
+static int test_aliases(void)
|
|
{
|
|
struct perf_pmu *pmu = NULL;
|
|
|
|
- if (__test_pmu_event_table())
|
|
- return -1;
|
|
-
|
|
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
|
|
int count = 0;
|
|
|
|
@@ -377,3 +378,160 @@ int test__pmu_events(struct test *test __maybe_unused,
|
|
|
|
return 0;
|
|
}
|
|
+
|
|
+static bool is_number(const char *str)
|
|
+{
|
|
+ char *end_ptr;
|
|
+ double v;
|
|
+
|
|
+ errno = 0;
|
|
+ v = strtod(str, &end_ptr);
|
|
+ (void)v; // We're not interested in this value, only if it is valid
|
|
+ return errno == 0 && end_ptr != str;
|
|
+}
|
|
+
|
|
+static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe)
|
|
+{
|
|
+ struct parse_events_error error;
|
|
+ struct perf_evlist *evlist;
|
|
+ int ret;
|
|
+
|
|
+ /* Numbers are always valid. */
|
|
+ if (is_number(id))
|
|
+ return 0;
|
|
+
|
|
+ evlist = perf_evlist__new();
|
|
+ memset(&error, 0, sizeof(error));
|
|
+ ret = parse_events(evlist, id, &error);
|
|
+ if (ret && same_cpu) {
|
|
+ pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n",
|
|
+ pe->metric_name, id, pe->metric_expr);
|
|
+ pr_warning("Error string '%s' help '%s'\n", error.str,
|
|
+ error.help);
|
|
+ } else if (ret) {
|
|
+ pr_debug3("Parse event failed, but for an event that may not be supported by this CPU.\nid '%s' metric '%s' expr '%s'\n",
|
|
+ id, pe->metric_name, pe->metric_expr);
|
|
+ ret = 0;
|
|
+ }
|
|
+ perf_evlist__delete(evlist);
|
|
+ free(error.str);
|
|
+ free(error.help);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void expr_failure(const char *msg,
|
|
+ const struct pmu_events_map *map,
|
|
+ const struct pmu_event *pe)
|
|
+{
|
|
+ pr_debug("%s for map %s %s %s\n",
|
|
+ msg, map->cpuid, map->version, map->type);
|
|
+ pr_debug("On metric %s\n", pe->metric_name);
|
|
+ pr_debug("On expression %s\n", pe->metric_expr);
|
|
+}
|
|
+
|
|
+static int test_parsing(void)
|
|
+{
|
|
+ struct pmu_events_map *cpus_map = perf_pmu__find_map(NULL);
|
|
+ struct pmu_events_map *map;
|
|
+ struct pmu_event *pe;
|
|
+ int i, j, k;
|
|
+ const char **ids;
|
|
+ int idnum;
|
|
+ int ret = 0;
|
|
+ struct expr_parse_ctx ctx;
|
|
+ double result;
|
|
+
|
|
+ i = 0;
|
|
+ for (;;) {
|
|
+ map = &pmu_events_map[i++];
|
|
+ if (!map->table)
|
|
+ break;
|
|
+ j = 0;
|
|
+ for (;;) {
|
|
+ pe = &map->table[j++];
|
|
+ if (!pe->name && !pe->metric_group && !pe->metric_name)
|
|
+ break;
|
|
+ if (!pe->metric_expr)
|
|
+ continue;
|
|
+ if (expr__find_other(pe->metric_expr, NULL,
|
|
+ &ids, &idnum, 0) < 0) {
|
|
+ expr_failure("Parse other failed", map, pe);
|
|
+ ret++;
|
|
+ continue;
|
|
+ }
|
|
+ expr__ctx_init(&ctx);
|
|
+
|
|
+ /*
|
|
+ * Add all ids with a made up value. The value may
|
|
+ * trigger divide by zero when subtracted and so try to
|
|
+ * make them unique.
|
|
+ */
|
|
+ for (k = 0; k < idnum; k++)
|
|
+ expr__add_id(&ctx, ids[k], k + 1);
|
|
+
|
|
+ for (k = 0; k < idnum; k++) {
|
|
+ if (check_parse_id(ids[k], map == cpus_map, pe))
|
|
+ ret++;
|
|
+ }
|
|
+
|
|
+ if (expr__parse(&result, &ctx, pe->metric_expr, 0)) {
|
|
+ expr_failure("Parse failed", map, pe);
|
|
+ ret++;
|
|
+ }
|
|
+ for (k = 0; k < idnum; k++)
|
|
+ zfree(&ids[k]);
|
|
+ free(ids);
|
|
+ }
|
|
+ }
|
|
+ /* TODO: fail when not ok */
|
|
+ return ret == 0 ? TEST_OK : TEST_SKIP;
|
|
+}
|
|
+
|
|
+static const struct {
|
|
+ int (*func)(void);
|
|
+ const char *desc;
|
|
+} pmu_events_testcase_table[] = {
|
|
+ {
|
|
+ .func = test_pmu_event_table,
|
|
+ .desc = "PMU event table sanity",
|
|
+ },
|
|
+ {
|
|
+ .func = test_aliases,
|
|
+ .desc = "PMU event map aliases",
|
|
+ },
|
|
+ {
|
|
+ .func = test_parsing,
|
|
+ .desc = "Parsing of PMU event table metrics",
|
|
+ },
|
|
+};
|
|
+
|
|
+const char *test__pmu_events_subtest_get_desc(int subtest)
|
|
+{
|
|
+ if (subtest < 0 ||
|
|
+ subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table))
|
|
+ return NULL;
|
|
+ return pmu_events_testcase_table[subtest].desc;
|
|
+}
|
|
+
|
|
+const char *test__pmu_events_subtest_skip_reason(int subtest)
|
|
+{
|
|
+ if (subtest < 0 ||
|
|
+ subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table))
|
|
+ return NULL;
|
|
+ if (pmu_events_testcase_table[subtest].func != test_parsing)
|
|
+ return NULL;
|
|
+ return "some metrics failed";
|
|
+}
|
|
+
|
|
+int test__pmu_events_subtest_get_nr(void)
|
|
+{
|
|
+ return (int)ARRAY_SIZE(pmu_events_testcase_table);
|
|
+}
|
|
+
|
|
+int test__pmu_events(struct test *test __maybe_unused, int subtest)
|
|
+{
|
|
+ if (subtest < 0 ||
|
|
+ subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table))
|
|
+ return TEST_FAIL;
|
|
+ return pmu_events_testcase_table[subtest].func();
|
|
+}
|
|
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
|
|
index 7c01a7812d21..7d2997c9fca7 100644
|
|
--- a/tools/perf/tests/tests.h
|
|
+++ b/tools/perf/tests/tests.h
|
|
@@ -50,6 +50,9 @@ int test__perf_evsel__tp_sched_test(struct test *test, int subtest);
|
|
int test__syscall_openat_tp_fields(struct test *test, int subtest);
|
|
int test__pmu(struct test *test, int subtest);
|
|
int test__pmu_events(struct test *test, int subtest);
|
|
+const char *test__pmu_events_subtest_get_desc(int subtest);
|
|
+const char *test__pmu_events_subtest_skip_reason(int subtest);
|
|
+int test__pmu_events_subtest_get_nr(void);
|
|
int test__attr(struct test *test, int subtest);
|
|
int test__dso_data(struct test *test, int subtest);
|
|
int test__dso_data_cache(struct test *test, int subtest);
|
|
--
|
|
2.27.0
|
|
|