xref: /linux/tools/perf/arch/x86/tests/topdown.c (revision 07d9df80082b8d1f37e05658371b087cb6738770)
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