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