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