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