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 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 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