~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/arch/x86/tests/hybrid.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include "arch-tests.h"
  3 #include "debug.h"
  4 #include "evlist.h"
  5 #include "evsel.h"
  6 #include "pmu.h"
  7 #include "pmus.h"
  8 #include "tests/tests.h"
  9 
 10 static bool test_config(const struct evsel *evsel, __u64 expected_config)
 11 {
 12         return (evsel->core.attr.config & PERF_HW_EVENT_MASK) == expected_config;
 13 }
 14 
 15 static bool test_perf_config(const struct perf_evsel *evsel, __u64 expected_config)
 16 {
 17         return (evsel->attr.config & PERF_HW_EVENT_MASK) == expected_config;
 18 }
 19 
 20 static bool test_hybrid_type(const struct evsel *evsel, __u64 expected_config)
 21 {
 22         return (evsel->core.attr.config >> PERF_PMU_TYPE_SHIFT) == expected_config;
 23 }
 24 
 25 static int test__hybrid_hw_event_with_pmu(struct evlist *evlist)
 26 {
 27         struct evsel *evsel = evlist__first(evlist);
 28 
 29         TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
 30         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
 31         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
 32         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES));
 33         return TEST_OK;
 34 }
 35 
 36 static int test__hybrid_hw_group_event(struct evlist *evlist)
 37 {
 38         struct evsel *evsel, *leader;
 39 
 40         evsel = leader = evlist__first(evlist);
 41         TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
 42         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
 43         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
 44         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES));
 45         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
 46 
 47         evsel = evsel__next(evsel);
 48         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
 49         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
 50         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_BRANCH_INSTRUCTIONS));
 51         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
 52         return TEST_OK;
 53 }
 54 
 55 static int test__hybrid_sw_hw_group_event(struct evlist *evlist)
 56 {
 57         struct evsel *evsel, *leader;
 58 
 59         evsel = leader = evlist__first(evlist);
 60         TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
 61         TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type);
 62         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
 63 
 64         evsel = evsel__next(evsel);
 65         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
 66         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
 67         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES));
 68         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
 69         return TEST_OK;
 70 }
 71 
 72 static int test__hybrid_hw_sw_group_event(struct evlist *evlist)
 73 {
 74         struct evsel *evsel, *leader;
 75 
 76         evsel = leader = evlist__first(evlist);
 77         TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
 78         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
 79         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
 80         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES));
 81         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
 82 
 83         evsel = evsel__next(evsel);
 84         TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->core.attr.type);
 85         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
 86         return TEST_OK;
 87 }
 88 
 89 static int test__hybrid_group_modifier1(struct evlist *evlist)
 90 {
 91         struct evsel *evsel, *leader;
 92 
 93         evsel = leader = evlist__first(evlist);
 94         TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
 95         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
 96         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
 97         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES));
 98         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
 99         TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user);
100         TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel);
101 
102         evsel = evsel__next(evsel);
103         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
104         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
105         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_BRANCH_INSTRUCTIONS));
106         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
107         TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user);
108         TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel);
109         return TEST_OK;
110 }
111 
112 static int test__hybrid_raw1(struct evlist *evlist)
113 {
114         struct perf_evsel *evsel;
115 
116         perf_evlist__for_each_evsel(&evlist->core, evsel) {
117                 struct perf_pmu *pmu = perf_pmus__find_by_type(evsel->attr.type);
118 
119                 TEST_ASSERT_VAL("missing pmu", pmu);
120                 TEST_ASSERT_VAL("unexpected pmu", !strncmp(pmu->name, "cpu_", 4));
121                 TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, 0x1a));
122         }
123         return TEST_OK;
124 }
125 
126 static int test__hybrid_raw2(struct evlist *evlist)
127 {
128         struct evsel *evsel = evlist__first(evlist);
129 
130         TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
131         TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
132         TEST_ASSERT_VAL("wrong config", test_config(evsel, 0x1a));
133         return TEST_OK;
134 }
135 
136 static int test__hybrid_cache_event(struct evlist *evlist)
137 {
138         struct evsel *evsel = evlist__first(evlist);
139 
140         TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
141         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->core.attr.type);
142         TEST_ASSERT_VAL("wrong config", 0x2 == (evsel->core.attr.config & 0xffffffff));
143         return TEST_OK;
144 }
145 
146 static int test__checkevent_pmu(struct evlist *evlist)
147 {
148 
149         struct evsel *evsel = evlist__first(evlist);
150 
151         TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries);
152         TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
153         TEST_ASSERT_VAL("wrong config",    10 == evsel->core.attr.config);
154         TEST_ASSERT_VAL("wrong config1",    1 == evsel->core.attr.config1);
155         TEST_ASSERT_VAL("wrong config2",    3 == evsel->core.attr.config2);
156         TEST_ASSERT_VAL("wrong config3",    0 == evsel->core.attr.config3);
157         /*
158          * The period value gets configured within evlist__config,
159          * while this test executes only parse events method.
160          */
161         TEST_ASSERT_VAL("wrong period",     0 == evsel->core.attr.sample_period);
162 
163         return TEST_OK;
164 }
165 
166 static int test__hybrid_hw_group_event_2(struct evlist *evlist)
167 {
168         struct evsel *evsel, *leader;
169 
170         evsel = leader = evlist__first(evlist);
171         TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->core.nr_entries);
172         TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type);
173         TEST_ASSERT_VAL("wrong hybrid type", test_hybrid_type(evsel, PERF_TYPE_RAW));
174         TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES));
175         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
176 
177         evsel = evsel__next(evsel);
178         TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type);
179         TEST_ASSERT_VAL("wrong config", evsel->core.attr.config == 0x3c);
180         TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader));
181         return TEST_OK;
182 }
183 
184 struct evlist_test {
185         const char *name;
186         bool (*valid)(void);
187         int (*check)(struct evlist *evlist);
188 };
189 
190 static const struct evlist_test test__hybrid_events[] = {
191         {
192                 .name  = "cpu_core/cycles/",
193                 .check = test__hybrid_hw_event_with_pmu,
194                 /* 0 */
195         },
196         {
197                 .name  = "{cpu_core/cycles/,cpu_core/branches/}",
198                 .check = test__hybrid_hw_group_event,
199                 /* 1 */
200         },
201         {
202                 .name  = "{cpu-clock,cpu_core/cycles/}",
203                 .check = test__hybrid_sw_hw_group_event,
204                 /* 2 */
205         },
206         {
207                 .name  = "{cpu_core/cycles/,cpu-clock}",
208                 .check = test__hybrid_hw_sw_group_event,
209                 /* 3 */
210         },
211         {
212                 .name  = "{cpu_core/cycles/k,cpu_core/branches/u}",
213                 .check = test__hybrid_group_modifier1,
214                 /* 4 */
215         },
216         {
217                 .name  = "r1a",
218                 .check = test__hybrid_raw1,
219                 /* 5 */
220         },
221         {
222                 .name  = "cpu_core/r1a/",
223                 .check = test__hybrid_raw2,
224                 /* 6 */
225         },
226         {
227                 .name  = "cpu_core/config=10,config1,config2=3,period=1000/u",
228                 .check = test__checkevent_pmu,
229                 /* 7 */
230         },
231         {
232                 .name  = "cpu_core/LLC-loads/",
233                 .check = test__hybrid_cache_event,
234                 /* 8 */
235         },
236         {
237                 .name  = "{cpu_core/cycles/,cpu_core/cpu-cycles/}",
238                 .check = test__hybrid_hw_group_event_2,
239                 /* 9 */
240         },
241 };
242 
243 static int test_event(const struct evlist_test *e)
244 {
245         struct parse_events_error err;
246         struct evlist *evlist;
247         int ret;
248 
249         if (e->valid && !e->valid()) {
250                 pr_debug("... SKIP\n");
251                 return TEST_OK;
252         }
253 
254         evlist = evlist__new();
255         if (evlist == NULL) {
256                 pr_err("Failed allocation");
257                 return TEST_FAIL;
258         }
259         parse_events_error__init(&err);
260         ret = parse_events(evlist, e->name, &err);
261         if (ret) {
262                 pr_debug("failed to parse event '%s', err %d\n", e->name, ret);
263                 parse_events_error__print(&err, e->name);
264                 ret = TEST_FAIL;
265                 if (parse_events_error__contains(&err, "can't access trace events"))
266                         ret = TEST_SKIP;
267         } else {
268                 ret = e->check(evlist);
269         }
270         parse_events_error__exit(&err);
271         evlist__delete(evlist);
272 
273         return ret;
274 }
275 
276 static int combine_test_results(int existing, int latest)
277 {
278         if (existing == TEST_FAIL)
279                 return TEST_FAIL;
280         if (existing == TEST_SKIP)
281                 return latest == TEST_OK ? TEST_SKIP : latest;
282         return latest;
283 }
284 
285 static int test_events(const struct evlist_test *events, int cnt)
286 {
287         int ret = TEST_OK;
288 
289         for (int i = 0; i < cnt; i++) {
290                 const struct evlist_test *e = &events[i];
291                 int test_ret;
292 
293                 pr_debug("running test %d '%s'\n", i, e->name);
294                 test_ret = test_event(e);
295                 if (test_ret != TEST_OK) {
296                         pr_debug("Event test failure: test %d '%s'", i, e->name);
297                         ret = combine_test_results(ret, test_ret);
298                 }
299         }
300 
301         return ret;
302 }
303 
304 int test__hybrid(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
305 {
306         if (perf_pmus__num_core_pmus() == 1)
307                 return TEST_SKIP;
308 
309         return test_events(test__hybrid_events, ARRAY_SIZE(test__hybrid_events));
310 }
311 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php