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