15b546de9SIan Rogers // SPDX-License-Identifier: GPL-2.0
25b546de9SIan Rogers #include "arch-tests.h"
35b546de9SIan Rogers #include "../util/topdown.h"
4*22ec0faaSNamhyung Kim #include "debug.h"
55b546de9SIan Rogers #include "evlist.h"
65b546de9SIan Rogers #include "parse-events.h"
75b546de9SIan Rogers #include "pmu.h"
85b546de9SIan Rogers #include "pmus.h"
95b546de9SIan Rogers
event_cb(void * state,struct pmu_event_info * info)105b546de9SIan Rogers static int event_cb(void *state, struct pmu_event_info *info)
115b546de9SIan Rogers {
125b546de9SIan Rogers char buf[256];
135b546de9SIan Rogers struct parse_events_error parse_err;
145b546de9SIan Rogers int *ret = state, err;
155b546de9SIan Rogers struct evlist *evlist = evlist__new();
165b546de9SIan Rogers struct evsel *evsel;
175b546de9SIan Rogers
185b546de9SIan Rogers if (!evlist)
195b546de9SIan Rogers return -ENOMEM;
205b546de9SIan Rogers
215b546de9SIan Rogers parse_events_error__init(&parse_err);
225b546de9SIan Rogers snprintf(buf, sizeof(buf), "%s/%s/", info->pmu->name, info->name);
235b546de9SIan Rogers err = parse_events(evlist, buf, &parse_err);
245b546de9SIan Rogers if (err) {
255b546de9SIan Rogers parse_events_error__print(&parse_err, buf);
265b546de9SIan Rogers *ret = TEST_FAIL;
275b546de9SIan Rogers }
285b546de9SIan Rogers parse_events_error__exit(&parse_err);
295b546de9SIan Rogers evlist__for_each_entry(evlist, evsel) {
305b546de9SIan Rogers bool fail = false;
315b546de9SIan Rogers bool p_core_pmu = evsel->pmu->type == PERF_TYPE_RAW;
325b546de9SIan Rogers const char *name = evsel__name(evsel);
335b546de9SIan Rogers
345b546de9SIan Rogers if (strcasestr(name, "uops_retired.slots") ||
355b546de9SIan Rogers strcasestr(name, "topdown.backend_bound_slots") ||
365b546de9SIan Rogers strcasestr(name, "topdown.br_mispredict_slots") ||
375b546de9SIan Rogers strcasestr(name, "topdown.memory_bound_slots") ||
385b546de9SIan Rogers strcasestr(name, "topdown.bad_spec_slots") ||
395b546de9SIan Rogers strcasestr(name, "topdown.slots_p")) {
405b546de9SIan Rogers if (arch_is_topdown_slots(evsel) || arch_is_topdown_metrics(evsel))
415b546de9SIan Rogers fail = true;
425b546de9SIan Rogers } else if (strcasestr(name, "slots")) {
435b546de9SIan Rogers if (arch_is_topdown_slots(evsel) != p_core_pmu ||
445b546de9SIan Rogers arch_is_topdown_metrics(evsel))
455b546de9SIan Rogers fail = true;
465b546de9SIan Rogers } else if (strcasestr(name, "topdown")) {
475b546de9SIan Rogers if (arch_is_topdown_slots(evsel) ||
485b546de9SIan Rogers arch_is_topdown_metrics(evsel) != p_core_pmu)
495b546de9SIan Rogers fail = true;
505b546de9SIan Rogers } else if (arch_is_topdown_slots(evsel) || arch_is_topdown_metrics(evsel)) {
515b546de9SIan Rogers fail = true;
525b546de9SIan Rogers }
535b546de9SIan Rogers if (fail) {
545b546de9SIan Rogers pr_debug("Broken topdown information for '%s'\n", evsel__name(evsel));
555b546de9SIan Rogers *ret = TEST_FAIL;
565b546de9SIan Rogers }
575b546de9SIan Rogers }
585b546de9SIan Rogers evlist__delete(evlist);
595b546de9SIan Rogers return 0;
605b546de9SIan Rogers }
615b546de9SIan Rogers
test__x86_topdown(struct test_suite * test __maybe_unused,int subtest __maybe_unused)625b546de9SIan Rogers static int test__x86_topdown(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
635b546de9SIan Rogers {
645b546de9SIan Rogers int ret = TEST_OK;
655b546de9SIan Rogers struct perf_pmu *pmu = NULL;
665b546de9SIan Rogers
675b546de9SIan Rogers if (!topdown_sys_has_perf_metrics())
685b546de9SIan Rogers return TEST_OK;
695b546de9SIan Rogers
705b546de9SIan Rogers while ((pmu = perf_pmus__scan_core(pmu)) != NULL) {
715b546de9SIan Rogers if (perf_pmu__for_each_event(pmu, /*skip_duplicate_pmus=*/false, &ret, event_cb))
725b546de9SIan Rogers break;
735b546de9SIan Rogers }
745b546de9SIan Rogers return ret;
755b546de9SIan Rogers }
765b546de9SIan Rogers
775b546de9SIan Rogers DEFINE_SUITE("x86 topdown", x86_topdown);
78