1 // SPDX-License-Identifier: GPL-2.0
2 #include "arch-tests.h"
3 #include "../util/topdown.h"
4 #include "evlist.h"
5 #include "parse-events.h"
6 #include "pmu.h"
7 #include "pmus.h"
8
event_cb(void * state,struct pmu_event_info * info)9 static int event_cb(void *state, struct pmu_event_info *info)
10 {
11 char buf[256];
12 struct parse_events_error parse_err;
13 int *ret = state, err;
14 struct evlist *evlist = evlist__new();
15 struct evsel *evsel;
16
17 if (!evlist)
18 return -ENOMEM;
19
20 parse_events_error__init(&parse_err);
21 snprintf(buf, sizeof(buf), "%s/%s/", info->pmu->name, info->name);
22 err = parse_events(evlist, buf, &parse_err);
23 if (err) {
24 parse_events_error__print(&parse_err, buf);
25 *ret = TEST_FAIL;
26 }
27 parse_events_error__exit(&parse_err);
28 evlist__for_each_entry(evlist, evsel) {
29 bool fail = false;
30 bool p_core_pmu = evsel->pmu->type == PERF_TYPE_RAW;
31 const char *name = evsel__name(evsel);
32
33 if (strcasestr(name, "uops_retired.slots") ||
34 strcasestr(name, "topdown.backend_bound_slots") ||
35 strcasestr(name, "topdown.br_mispredict_slots") ||
36 strcasestr(name, "topdown.memory_bound_slots") ||
37 strcasestr(name, "topdown.bad_spec_slots") ||
38 strcasestr(name, "topdown.slots_p")) {
39 if (arch_is_topdown_slots(evsel) || arch_is_topdown_metrics(evsel))
40 fail = true;
41 } else if (strcasestr(name, "slots")) {
42 if (arch_is_topdown_slots(evsel) != p_core_pmu ||
43 arch_is_topdown_metrics(evsel))
44 fail = true;
45 } else if (strcasestr(name, "topdown")) {
46 if (arch_is_topdown_slots(evsel) ||
47 arch_is_topdown_metrics(evsel) != p_core_pmu)
48 fail = true;
49 } else if (arch_is_topdown_slots(evsel) || arch_is_topdown_metrics(evsel)) {
50 fail = true;
51 }
52 if (fail) {
53 pr_debug("Broken topdown information for '%s'\n", evsel__name(evsel));
54 *ret = TEST_FAIL;
55 }
56 }
57 evlist__delete(evlist);
58 return 0;
59 }
60
test__x86_topdown(struct test_suite * test __maybe_unused,int subtest __maybe_unused)61 static int test__x86_topdown(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
62 {
63 int ret = TEST_OK;
64 struct perf_pmu *pmu = NULL;
65
66 if (!topdown_sys_has_perf_metrics())
67 return TEST_OK;
68
69 while ((pmu = perf_pmus__scan_core(pmu)) != NULL) {
70 if (perf_pmu__for_each_event(pmu, /*skip_duplicate_pmus=*/false, &ret, event_cb))
71 break;
72 }
73 return ret;
74 }
75
76 DEFINE_SUITE("x86 topdown", x86_topdown);
77