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