1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 #include <string.h> 3 4 #include "debug.h" 5 #include "evlist.h" 6 #include "parse-events.h" 7 #include "pmu.h" 8 #include "pmus.h" 9 #include "tests.h" 10 11 struct match_state { 12 char *event1; 13 char *event2; 14 }; 15 16 static char *clean_event_name(struct pmu_event_info *info) 17 { 18 const char *name = info->name; 19 const char *pmu_name = info->pmu->name; 20 size_t pmu_len = strlen(pmu_name); 21 char *res; 22 size_t len; 23 24 if (!strncmp(name, pmu_name, pmu_len) && name[pmu_len] == '/') 25 name += pmu_len + 1; 26 27 res = strdup(name); 28 if (!res) 29 return NULL; 30 31 len = strlen(res); 32 if (len > 0 && res[len - 1] == '/') 33 res[len - 1] = '\0'; 34 35 return res; 36 } 37 38 static int event_cb(void *state, struct pmu_event_info *info) 39 { 40 struct match_state *m = state; 41 char *clean_name; 42 43 if (m->event1 && m->event2) 44 return 1; 45 46 clean_name = clean_event_name(info); 47 if (!clean_name) 48 return 0; 49 50 if (!m->event1) { 51 m->event1 = clean_name; 52 } else { 53 if (strcmp(m->event1, clean_name)) { 54 m->event2 = clean_name; 55 return 1; 56 } 57 free(clean_name); 58 } 59 return 0; 60 } 61 62 #define CHECK_COND(cond, text) \ 63 do { \ 64 if (!(cond)) { \ 65 pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ 66 ret = TEST_FAIL; \ 67 goto out_err; \ 68 } \ 69 } while (0) 70 71 #define CHECK_EQUAL(val, expected, text) \ 72 do { \ 73 if ((val) != (expected)) { \ 74 pr_debug("FAILED %s:%d %s (%d != %d)\n", \ 75 __FILE__, __LINE__, text, (val), (expected)); \ 76 ret = TEST_FAIL; \ 77 goto out_err; \ 78 } \ 79 } while (0) 80 81 static int test__uncore_event_sorting(struct test_suite *test __maybe_unused, 82 int subtest __maybe_unused) 83 { 84 struct evlist *evlist = NULL; 85 struct parse_events_error err; 86 struct evsel *evsel; 87 struct perf_pmu *pmu = NULL; 88 char *pmu_prefix = NULL; 89 struct match_state m = { NULL, NULL }; 90 char buf[1024]; 91 int ret; 92 93 parse_events_error__init(&err); 94 95 while ((pmu = perf_pmus__scan(pmu)) != NULL) { 96 size_t len; 97 struct perf_pmu *sibling; 98 99 if (pmu->is_core) 100 continue; 101 102 len = pmu_name_len_no_suffix(pmu->name); 103 if (len == strlen(pmu->name)) 104 continue; 105 106 sibling = pmu; 107 while ((sibling = perf_pmus__scan(sibling)) != NULL) { 108 if (sibling->is_core) 109 continue; 110 if (pmu_name_len_no_suffix(sibling->name) == len && 111 !strncmp(pmu->name, sibling->name, len)) 112 break; 113 } 114 115 if (!sibling) 116 continue; 117 118 m.event1 = m.event2 = NULL; 119 perf_pmu__for_each_event(pmu, false, &m, event_cb); 120 121 if (m.event1 && m.event2) { 122 pmu_prefix = strndup(pmu->name, len); 123 break; 124 } 125 zfree(&m.event1); 126 } 127 128 if (!pmu_prefix) { 129 pr_debug("No suitable uncore PMU found\n"); 130 ret = TEST_SKIP; 131 goto out_err; 132 } 133 134 evlist = evlist__new(); 135 if (!evlist) { 136 ret = TEST_FAIL; 137 goto out_err; 138 } 139 140 snprintf(buf, sizeof(buf), "{%s/%s/,%s/%s/}", pmu_prefix, m.event1, pmu_prefix, m.event2); 141 pr_debug("Parsing: %s\n", buf); 142 143 ret = parse_events(evlist, buf, &err); 144 if (ret) { 145 pr_debug("parse_events failed\n"); 146 ret = TEST_FAIL; 147 goto out_err; 148 } 149 150 CHECK_COND(evlist->core.nr_entries >= 4, "Number of events is >= 4"); 151 CHECK_EQUAL(evlist->core.nr_entries % 2, 0, "Number of events is a multiple of 2"); 152 153 evlist__for_each_entry(evlist, evsel) { 154 struct evsel *next; 155 156 if (!evsel__is_group_leader(evsel)) 157 continue; 158 159 next = evsel__next(evsel); 160 CHECK_EQUAL(evsel->core.nr_members, 2, "Group size is 2"); 161 CHECK_COND(evsel->pmu == next->pmu, "PMU match"); 162 CHECK_COND(strstr(evsel__name(evsel), m.event1) != NULL, "First event name"); 163 CHECK_COND(strstr(evsel__name(next), m.event2) != NULL, "Second event name"); 164 } 165 ret = TEST_OK; 166 167 out_err: 168 evlist__delete(evlist); 169 parse_events_error__exit(&err); 170 zfree(&pmu_prefix); 171 zfree(&m.event1); 172 zfree(&m.event2); 173 return ret; 174 } 175 176 DEFINE_SUITE("Uncore event sorting", uncore_event_sorting); 177