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