Merge branches 'clk-baikal', 'clk-broadcom', 'clk-vc5' and 'clk-versaclock' into...
[platform/kernel/linux-starfive.git] / tools / lib / perf / tests / test-evsel.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <linux/perf_event.h>
6 #include <linux/kernel.h>
7 #include <perf/cpumap.h>
8 #include <perf/threadmap.h>
9 #include <perf/evsel.h>
10 #include <internal/evsel.h>
11 #include <internal/tests.h>
12 #include "tests.h"
13
14 static int libperf_print(enum libperf_print_level level,
15                          const char *fmt, va_list ap)
16 {
17         return vfprintf(stderr, fmt, ap);
18 }
19
20 static int test_stat_cpu(void)
21 {
22         struct perf_cpu_map *cpus;
23         struct perf_evsel *evsel;
24         struct perf_event_attr attr = {
25                 .type   = PERF_TYPE_SOFTWARE,
26                 .config = PERF_COUNT_SW_CPU_CLOCK,
27         };
28         int err, idx;
29
30         cpus = perf_cpu_map__new(NULL);
31         __T("failed to create cpus", cpus);
32
33         evsel = perf_evsel__new(&attr);
34         __T("failed to create evsel", evsel);
35
36         err = perf_evsel__open(evsel, cpus, NULL);
37         __T("failed to open evsel", err == 0);
38
39         for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
40                 struct perf_counts_values counts = { .val = 0 };
41
42                 perf_evsel__read(evsel, idx, 0, &counts);
43                 __T("failed to read value for evsel", counts.val != 0);
44         }
45
46         perf_evsel__close(evsel);
47         perf_evsel__delete(evsel);
48
49         perf_cpu_map__put(cpus);
50         return 0;
51 }
52
53 static int test_stat_thread(void)
54 {
55         struct perf_counts_values counts = { .val = 0 };
56         struct perf_thread_map *threads;
57         struct perf_evsel *evsel;
58         struct perf_event_attr attr = {
59                 .type   = PERF_TYPE_SOFTWARE,
60                 .config = PERF_COUNT_SW_TASK_CLOCK,
61         };
62         int err;
63
64         threads = perf_thread_map__new_dummy();
65         __T("failed to create threads", threads);
66
67         perf_thread_map__set_pid(threads, 0, 0);
68
69         evsel = perf_evsel__new(&attr);
70         __T("failed to create evsel", evsel);
71
72         err = perf_evsel__open(evsel, NULL, threads);
73         __T("failed to open evsel", err == 0);
74
75         perf_evsel__read(evsel, 0, 0, &counts);
76         __T("failed to read value for evsel", counts.val != 0);
77
78         perf_evsel__close(evsel);
79         perf_evsel__delete(evsel);
80
81         perf_thread_map__put(threads);
82         return 0;
83 }
84
85 static int test_stat_thread_enable(void)
86 {
87         struct perf_counts_values counts = { .val = 0 };
88         struct perf_thread_map *threads;
89         struct perf_evsel *evsel;
90         struct perf_event_attr attr = {
91                 .type     = PERF_TYPE_SOFTWARE,
92                 .config   = PERF_COUNT_SW_TASK_CLOCK,
93                 .disabled = 1,
94         };
95         int err;
96
97         threads = perf_thread_map__new_dummy();
98         __T("failed to create threads", threads);
99
100         perf_thread_map__set_pid(threads, 0, 0);
101
102         evsel = perf_evsel__new(&attr);
103         __T("failed to create evsel", evsel);
104
105         err = perf_evsel__open(evsel, NULL, threads);
106         __T("failed to open evsel", err == 0);
107
108         perf_evsel__read(evsel, 0, 0, &counts);
109         __T("failed to read value for evsel", counts.val == 0);
110
111         err = perf_evsel__enable(evsel);
112         __T("failed to enable evsel", err == 0);
113
114         perf_evsel__read(evsel, 0, 0, &counts);
115         __T("failed to read value for evsel", counts.val != 0);
116
117         err = perf_evsel__disable(evsel);
118         __T("failed to enable evsel", err == 0);
119
120         perf_evsel__close(evsel);
121         perf_evsel__delete(evsel);
122
123         perf_thread_map__put(threads);
124         return 0;
125 }
126
127 static int test_stat_user_read(int event)
128 {
129         struct perf_counts_values counts = { .val = 0 };
130         struct perf_thread_map *threads;
131         struct perf_evsel *evsel;
132         struct perf_event_mmap_page *pc;
133         struct perf_event_attr attr = {
134                 .type   = PERF_TYPE_HARDWARE,
135                 .config = event,
136 #ifdef __aarch64__
137                 .config1 = 0x2,         /* Request user access */
138 #endif
139         };
140         int err, i;
141
142         threads = perf_thread_map__new_dummy();
143         __T("failed to create threads", threads);
144
145         perf_thread_map__set_pid(threads, 0, 0);
146
147         evsel = perf_evsel__new(&attr);
148         __T("failed to create evsel", evsel);
149
150         err = perf_evsel__open(evsel, NULL, threads);
151         __T("failed to open evsel", err == 0);
152
153         err = perf_evsel__mmap(evsel, 0);
154         __T("failed to mmap evsel", err == 0);
155
156         pc = perf_evsel__mmap_base(evsel, 0, 0);
157         __T("failed to get mmapped address", pc);
158
159 #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
160         __T("userspace counter access not supported", pc->cap_user_rdpmc);
161         __T("userspace counter access not enabled", pc->index);
162         __T("userspace counter width not set", pc->pmc_width >= 32);
163 #endif
164
165         perf_evsel__read(evsel, 0, 0, &counts);
166         __T("failed to read value for evsel", counts.val != 0);
167
168         for (i = 0; i < 5; i++) {
169                 volatile int count = 0x10000 << i;
170                 __u64 start, end, last = 0;
171
172                 __T_VERBOSE("\tloop = %u, ", count);
173
174                 perf_evsel__read(evsel, 0, 0, &counts);
175                 start = counts.val;
176
177                 while (count--) ;
178
179                 perf_evsel__read(evsel, 0, 0, &counts);
180                 end = counts.val;
181
182                 __T("invalid counter data", (end - start) > last);
183                 last = end - start;
184                 __T_VERBOSE("count = %llu\n", end - start);
185         }
186
187         perf_evsel__munmap(evsel);
188         perf_evsel__close(evsel);
189         perf_evsel__delete(evsel);
190
191         perf_thread_map__put(threads);
192         return 0;
193 }
194
195 static int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads)
196 {
197         struct perf_evsel *evsel;
198         struct perf_counts_values counts;
199         volatile int count = 0x100000;
200         int err;
201
202         evsel = perf_evsel__new(attr);
203         __T("failed to create evsel", evsel);
204
205         /* skip old kernels that don't support the format */
206         err = perf_evsel__open(evsel, NULL, threads);
207         if (err < 0)
208                 return 0;
209
210         while (count--) ;
211
212         memset(&counts, -1, sizeof(counts));
213         perf_evsel__read(evsel, 0, 0, &counts);
214
215         __T("failed to read value", counts.val);
216         if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
217                 __T("failed to read TOTAL_TIME_ENABLED", counts.ena);
218         if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
219                 __T("failed to read TOTAL_TIME_RUNNING", counts.run);
220         if (attr->read_format & PERF_FORMAT_ID)
221                 __T("failed to read ID", counts.id);
222         if (attr->read_format & PERF_FORMAT_LOST)
223                 __T("failed to read LOST", counts.lost == 0);
224
225         perf_evsel__close(evsel);
226         perf_evsel__delete(evsel);
227         return 0;
228 }
229
230 static int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads)
231 {
232         struct perf_evsel *leader, *member;
233         struct perf_counts_values counts;
234         volatile int count = 0x100000;
235         int err;
236
237         attr->read_format |= PERF_FORMAT_GROUP;
238         leader = perf_evsel__new(attr);
239         __T("failed to create leader", leader);
240
241         attr->read_format &= ~PERF_FORMAT_GROUP;
242         member = perf_evsel__new(attr);
243         __T("failed to create member", member);
244
245         member->leader = leader;
246         leader->nr_members = 2;
247
248         /* skip old kernels that don't support the format */
249         err = perf_evsel__open(leader, NULL, threads);
250         if (err < 0)
251                 return 0;
252         err = perf_evsel__open(member, NULL, threads);
253         if (err < 0)
254                 return 0;
255
256         while (count--) ;
257
258         memset(&counts, -1, sizeof(counts));
259         perf_evsel__read(leader, 0, 0, &counts);
260
261         __T("failed to read leader value", counts.val);
262         if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
263                 __T("failed to read leader TOTAL_TIME_ENABLED", counts.ena);
264         if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
265                 __T("failed to read leader TOTAL_TIME_RUNNING", counts.run);
266         if (attr->read_format & PERF_FORMAT_ID)
267                 __T("failed to read leader ID", counts.id);
268         if (attr->read_format & PERF_FORMAT_LOST)
269                 __T("failed to read leader LOST", counts.lost == 0);
270
271         memset(&counts, -1, sizeof(counts));
272         perf_evsel__read(member, 0, 0, &counts);
273
274         __T("failed to read member value", counts.val);
275         if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
276                 __T("failed to read member TOTAL_TIME_ENABLED", counts.ena);
277         if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
278                 __T("failed to read member TOTAL_TIME_RUNNING", counts.run);
279         if (attr->read_format & PERF_FORMAT_ID)
280                 __T("failed to read member ID", counts.id);
281         if (attr->read_format & PERF_FORMAT_LOST)
282                 __T("failed to read member LOST", counts.lost == 0);
283
284         perf_evsel__close(member);
285         perf_evsel__close(leader);
286         perf_evsel__delete(member);
287         perf_evsel__delete(leader);
288         return 0;
289 }
290
291 static int test_stat_read_format(void)
292 {
293         struct perf_thread_map *threads;
294         struct perf_event_attr attr = {
295                 .type   = PERF_TYPE_SOFTWARE,
296                 .config = PERF_COUNT_SW_TASK_CLOCK,
297         };
298         int err, i;
299
300 #define FMT(_fmt)  PERF_FORMAT_ ## _fmt
301 #define FMT_TIME  (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING))
302
303         uint64_t test_formats [] = {
304                 0,
305                 FMT_TIME,
306                 FMT(ID),
307                 FMT(LOST),
308                 FMT_TIME | FMT(ID),
309                 FMT_TIME | FMT(LOST),
310                 FMT_TIME | FMT(ID) | FMT(LOST),
311                 FMT(ID) | FMT(LOST),
312         };
313
314 #undef FMT
315 #undef FMT_TIME
316
317         threads = perf_thread_map__new_dummy();
318         __T("failed to create threads", threads);
319
320         perf_thread_map__set_pid(threads, 0, 0);
321
322         for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
323                 attr.read_format = test_formats[i];
324                 __T_VERBOSE("testing single read with read_format: %lx\n",
325                             (unsigned long)test_formats[i]);
326
327                 err = test_stat_read_format_single(&attr, threads);
328                 __T("failed to read single format", err == 0);
329         }
330
331         perf_thread_map__put(threads);
332
333         threads = perf_thread_map__new_array(2, NULL);
334         __T("failed to create threads", threads);
335
336         perf_thread_map__set_pid(threads, 0, 0);
337         perf_thread_map__set_pid(threads, 1, 0);
338
339         for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
340                 attr.read_format = test_formats[i];
341                 __T_VERBOSE("testing group read with read_format: %lx\n",
342                             (unsigned long)test_formats[i]);
343
344                 err = test_stat_read_format_group(&attr, threads);
345                 __T("failed to read group format", err == 0);
346         }
347
348         perf_thread_map__put(threads);
349         return 0;
350 }
351
352 int test_evsel(int argc, char **argv)
353 {
354         __T_START;
355
356         libperf_init(libperf_print);
357
358         test_stat_cpu();
359         test_stat_thread();
360         test_stat_thread_enable();
361         test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
362         test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
363         test_stat_read_format();
364
365         __T_END;
366         return tests_failed == 0 ? 0 : -1;
367 }