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