609f59295326034d1a07662872068ed7ce358fa2
[platform/adaptation/renesas_rcar/renesas_kernel.git] / tools / perf / tests / builtin-test.c
1 /*
2  * builtin-test.c
3  *
4  * Builtin regression testing command: ever growing number of sanity tests
5  */
6 #include "builtin.h"
7
8 #include "util/cache.h"
9 #include "util/color.h"
10 #include "util/debug.h"
11 #include "util/debugfs.h"
12 #include "util/evlist.h"
13 #include "util/machine.h"
14 #include "util/parse-options.h"
15 #include "util/parse-events.h"
16 #include "util/symbol.h"
17 #include "util/thread_map.h"
18 #include "util/pmu.h"
19 #include "event-parse.h"
20 #include "../../include/linux/hw_breakpoint.h"
21
22 #include <sys/mman.h>
23
24 #include "util/cpumap.h"
25 #include "util/evsel.h"
26 #include <sys/types.h>
27
28 #include "tests.h"
29
30 #include <sched.h>
31
32
33
34 static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp)
35 {
36         int i, cpu = -1, nrcpus = 1024;
37 realloc:
38         CPU_ZERO(maskp);
39
40         if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) {
41                 if (errno == EINVAL && nrcpus < (1024 << 8)) {
42                         nrcpus = nrcpus << 2;
43                         goto realloc;
44                 }
45                 perror("sched_getaffinity");
46                         return -1;
47         }
48
49         for (i = 0; i < nrcpus; i++) {
50                 if (CPU_ISSET(i, maskp)) {
51                         if (cpu == -1)
52                                 cpu = i;
53                         else
54                                 CPU_CLR(i, maskp);
55                 }
56         }
57
58         return cpu;
59 }
60
61 static int test__PERF_RECORD(void)
62 {
63         struct perf_record_opts opts = {
64                 .target = {
65                         .uid = UINT_MAX,
66                         .uses_mmap = true,
67                 },
68                 .no_delay   = true,
69                 .freq       = 10,
70                 .mmap_pages = 256,
71         };
72         cpu_set_t cpu_mask;
73         size_t cpu_mask_size = sizeof(cpu_mask);
74         struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
75         struct perf_evsel *evsel;
76         struct perf_sample sample;
77         const char *cmd = "sleep";
78         const char *argv[] = { cmd, "1", NULL, };
79         char *bname;
80         u64 prev_time = 0;
81         bool found_cmd_mmap = false,
82              found_libc_mmap = false,
83              found_vdso_mmap = false,
84              found_ld_mmap = false;
85         int err = -1, errs = 0, i, wakeups = 0;
86         u32 cpu;
87         int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
88
89         if (evlist == NULL || argv == NULL) {
90                 pr_debug("Not enough memory to create evlist\n");
91                 goto out;
92         }
93
94         /*
95          * We need at least one evsel in the evlist, use the default
96          * one: "cycles".
97          */
98         err = perf_evlist__add_default(evlist);
99         if (err < 0) {
100                 pr_debug("Not enough memory to create evsel\n");
101                 goto out_delete_evlist;
102         }
103
104         /*
105          * Create maps of threads and cpus to monitor. In this case
106          * we start with all threads and cpus (-1, -1) but then in
107          * perf_evlist__prepare_workload we'll fill in the only thread
108          * we're monitoring, the one forked there.
109          */
110         err = perf_evlist__create_maps(evlist, &opts.target);
111         if (err < 0) {
112                 pr_debug("Not enough memory to create thread/cpu maps\n");
113                 goto out_delete_evlist;
114         }
115
116         /*
117          * Prepare the workload in argv[] to run, it'll fork it, and then wait
118          * for perf_evlist__start_workload() to exec it. This is done this way
119          * so that we have time to open the evlist (calling sys_perf_event_open
120          * on all the fds) and then mmap them.
121          */
122         err = perf_evlist__prepare_workload(evlist, &opts, argv);
123         if (err < 0) {
124                 pr_debug("Couldn't run the workload!\n");
125                 goto out_delete_evlist;
126         }
127
128         /*
129          * Config the evsels, setting attr->comm on the first one, etc.
130          */
131         evsel = perf_evlist__first(evlist);
132         evsel->attr.sample_type |= PERF_SAMPLE_CPU;
133         evsel->attr.sample_type |= PERF_SAMPLE_TID;
134         evsel->attr.sample_type |= PERF_SAMPLE_TIME;
135         perf_evlist__config_attrs(evlist, &opts);
136
137         err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
138         if (err < 0) {
139                 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
140                 goto out_delete_evlist;
141         }
142
143         cpu = err;
144
145         /*
146          * So that we can check perf_sample.cpu on all the samples.
147          */
148         if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
149                 pr_debug("sched_setaffinity: %s\n", strerror(errno));
150                 goto out_delete_evlist;
151         }
152
153         /*
154          * Call sys_perf_event_open on all the fds on all the evsels,
155          * grouping them if asked to.
156          */
157         err = perf_evlist__open(evlist);
158         if (err < 0) {
159                 pr_debug("perf_evlist__open: %s\n", strerror(errno));
160                 goto out_delete_evlist;
161         }
162
163         /*
164          * mmap the first fd on a given CPU and ask for events for the other
165          * fds in the same CPU to be injected in the same mmap ring buffer
166          * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)).
167          */
168         err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
169         if (err < 0) {
170                 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
171                 goto out_delete_evlist;
172         }
173
174         /*
175          * Now that all is properly set up, enable the events, they will
176          * count just on workload.pid, which will start...
177          */
178         perf_evlist__enable(evlist);
179
180         /*
181          * Now!
182          */
183         perf_evlist__start_workload(evlist);
184
185         while (1) {
186                 int before = total_events;
187
188                 for (i = 0; i < evlist->nr_mmaps; i++) {
189                         union perf_event *event;
190
191                         while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
192                                 const u32 type = event->header.type;
193                                 const char *name = perf_event__name(type);
194
195                                 ++total_events;
196                                 if (type < PERF_RECORD_MAX)
197                                         nr_events[type]++;
198
199                                 err = perf_evlist__parse_sample(evlist, event, &sample);
200                                 if (err < 0) {
201                                         if (verbose)
202                                                 perf_event__fprintf(event, stderr);
203                                         pr_debug("Couldn't parse sample\n");
204                                         goto out_err;
205                                 }
206
207                                 if (verbose) {
208                                         pr_info("%" PRIu64" %d ", sample.time, sample.cpu);
209                                         perf_event__fprintf(event, stderr);
210                                 }
211
212                                 if (prev_time > sample.time) {
213                                         pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n",
214                                                  name, prev_time, sample.time);
215                                         ++errs;
216                                 }
217
218                                 prev_time = sample.time;
219
220                                 if (sample.cpu != cpu) {
221                                         pr_debug("%s with unexpected cpu, expected %d, got %d\n",
222                                                  name, cpu, sample.cpu);
223                                         ++errs;
224                                 }
225
226                                 if ((pid_t)sample.pid != evlist->workload.pid) {
227                                         pr_debug("%s with unexpected pid, expected %d, got %d\n",
228                                                  name, evlist->workload.pid, sample.pid);
229                                         ++errs;
230                                 }
231
232                                 if ((pid_t)sample.tid != evlist->workload.pid) {
233                                         pr_debug("%s with unexpected tid, expected %d, got %d\n",
234                                                  name, evlist->workload.pid, sample.tid);
235                                         ++errs;
236                                 }
237
238                                 if ((type == PERF_RECORD_COMM ||
239                                      type == PERF_RECORD_MMAP ||
240                                      type == PERF_RECORD_FORK ||
241                                      type == PERF_RECORD_EXIT) &&
242                                      (pid_t)event->comm.pid != evlist->workload.pid) {
243                                         pr_debug("%s with unexpected pid/tid\n", name);
244                                         ++errs;
245                                 }
246
247                                 if ((type == PERF_RECORD_COMM ||
248                                      type == PERF_RECORD_MMAP) &&
249                                      event->comm.pid != event->comm.tid) {
250                                         pr_debug("%s with different pid/tid!\n", name);
251                                         ++errs;
252                                 }
253
254                                 switch (type) {
255                                 case PERF_RECORD_COMM:
256                                         if (strcmp(event->comm.comm, cmd)) {
257                                                 pr_debug("%s with unexpected comm!\n", name);
258                                                 ++errs;
259                                         }
260                                         break;
261                                 case PERF_RECORD_EXIT:
262                                         goto found_exit;
263                                 case PERF_RECORD_MMAP:
264                                         bname = strrchr(event->mmap.filename, '/');
265                                         if (bname != NULL) {
266                                                 if (!found_cmd_mmap)
267                                                         found_cmd_mmap = !strcmp(bname + 1, cmd);
268                                                 if (!found_libc_mmap)
269                                                         found_libc_mmap = !strncmp(bname + 1, "libc", 4);
270                                                 if (!found_ld_mmap)
271                                                         found_ld_mmap = !strncmp(bname + 1, "ld", 2);
272                                         } else if (!found_vdso_mmap)
273                                                 found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
274                                         break;
275
276                                 case PERF_RECORD_SAMPLE:
277                                         /* Just ignore samples for now */
278                                         break;
279                                 default:
280                                         pr_debug("Unexpected perf_event->header.type %d!\n",
281                                                  type);
282                                         ++errs;
283                                 }
284                         }
285                 }
286
287                 /*
288                  * We don't use poll here because at least at 3.1 times the
289                  * PERF_RECORD_{!SAMPLE} events don't honour
290                  * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
291                  */
292                 if (total_events == before && false)
293                         poll(evlist->pollfd, evlist->nr_fds, -1);
294
295                 sleep(1);
296                 if (++wakeups > 5) {
297                         pr_debug("No PERF_RECORD_EXIT event!\n");
298                         break;
299                 }
300         }
301
302 found_exit:
303         if (nr_events[PERF_RECORD_COMM] > 1) {
304                 pr_debug("Excessive number of PERF_RECORD_COMM events!\n");
305                 ++errs;
306         }
307
308         if (nr_events[PERF_RECORD_COMM] == 0) {
309                 pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd);
310                 ++errs;
311         }
312
313         if (!found_cmd_mmap) {
314                 pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd);
315                 ++errs;
316         }
317
318         if (!found_libc_mmap) {
319                 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc");
320                 ++errs;
321         }
322
323         if (!found_ld_mmap) {
324                 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld");
325                 ++errs;
326         }
327
328         if (!found_vdso_mmap) {
329                 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
330                 ++errs;
331         }
332 out_err:
333         perf_evlist__munmap(evlist);
334 out_delete_evlist:
335         perf_evlist__delete(evlist);
336 out:
337         return (err < 0 || errs > 0) ? -1 : 0;
338 }
339
340
341 #if defined(__x86_64__) || defined(__i386__)
342
343 #define barrier() asm volatile("" ::: "memory")
344
345 static u64 rdpmc(unsigned int counter)
346 {
347         unsigned int low, high;
348
349         asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
350
351         return low | ((u64)high) << 32;
352 }
353
354 static u64 rdtsc(void)
355 {
356         unsigned int low, high;
357
358         asm volatile("rdtsc" : "=a" (low), "=d" (high));
359
360         return low | ((u64)high) << 32;
361 }
362
363 static u64 mmap_read_self(void *addr)
364 {
365         struct perf_event_mmap_page *pc = addr;
366         u32 seq, idx, time_mult = 0, time_shift = 0;
367         u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
368
369         do {
370                 seq = pc->lock;
371                 barrier();
372
373                 enabled = pc->time_enabled;
374                 running = pc->time_running;
375
376                 if (enabled != running) {
377                         cyc = rdtsc();
378                         time_mult = pc->time_mult;
379                         time_shift = pc->time_shift;
380                         time_offset = pc->time_offset;
381                 }
382
383                 idx = pc->index;
384                 count = pc->offset;
385                 if (idx)
386                         count += rdpmc(idx - 1);
387
388                 barrier();
389         } while (pc->lock != seq);
390
391         if (enabled != running) {
392                 u64 quot, rem;
393
394                 quot = (cyc >> time_shift);
395                 rem = cyc & ((1 << time_shift) - 1);
396                 delta = time_offset + quot * time_mult +
397                         ((rem * time_mult) >> time_shift);
398
399                 enabled += delta;
400                 if (idx)
401                         running += delta;
402
403                 quot = count / running;
404                 rem = count % running;
405                 count = quot * enabled + (rem * enabled) / running;
406         }
407
408         return count;
409 }
410
411 /*
412  * If the RDPMC instruction faults then signal this back to the test parent task:
413  */
414 static void segfault_handler(int sig __maybe_unused,
415                              siginfo_t *info __maybe_unused,
416                              void *uc __maybe_unused)
417 {
418         exit(-1);
419 }
420
421 static int __test__rdpmc(void)
422 {
423         volatile int tmp = 0;
424         u64 i, loops = 1000;
425         int n;
426         int fd;
427         void *addr;
428         struct perf_event_attr attr = {
429                 .type = PERF_TYPE_HARDWARE,
430                 .config = PERF_COUNT_HW_INSTRUCTIONS,
431                 .exclude_kernel = 1,
432         };
433         u64 delta_sum = 0;
434         struct sigaction sa;
435
436         sigfillset(&sa.sa_mask);
437         sa.sa_sigaction = segfault_handler;
438         sigaction(SIGSEGV, &sa, NULL);
439
440         fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
441         if (fd < 0) {
442                 pr_err("Error: sys_perf_event_open() syscall returned "
443                        "with %d (%s)\n", fd, strerror(errno));
444                 return -1;
445         }
446
447         addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
448         if (addr == (void *)(-1)) {
449                 pr_err("Error: mmap() syscall returned with (%s)\n",
450                        strerror(errno));
451                 goto out_close;
452         }
453
454         for (n = 0; n < 6; n++) {
455                 u64 stamp, now, delta;
456
457                 stamp = mmap_read_self(addr);
458
459                 for (i = 0; i < loops; i++)
460                         tmp++;
461
462                 now = mmap_read_self(addr);
463                 loops *= 10;
464
465                 delta = now - stamp;
466                 pr_debug("%14d: %14Lu\n", n, (long long)delta);
467
468                 delta_sum += delta;
469         }
470
471         munmap(addr, page_size);
472         pr_debug("   ");
473 out_close:
474         close(fd);
475
476         if (!delta_sum)
477                 return -1;
478
479         return 0;
480 }
481
482 static int test__rdpmc(void)
483 {
484         int status = 0;
485         int wret = 0;
486         int ret;
487         int pid;
488
489         pid = fork();
490         if (pid < 0)
491                 return -1;
492
493         if (!pid) {
494                 ret = __test__rdpmc();
495
496                 exit(ret);
497         }
498
499         wret = waitpid(pid, &status, 0);
500         if (wret < 0 || status)
501                 return -1;
502
503         return 0;
504 }
505
506 #endif
507
508 static int test__perf_pmu(void)
509 {
510         return perf_pmu__test();
511 }
512
513 static int perf_evsel__roundtrip_cache_name_test(void)
514 {
515         char name[128];
516         int type, op, err = 0, ret = 0, i, idx;
517         struct perf_evsel *evsel;
518         struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
519
520         if (evlist == NULL)
521                 return -ENOMEM;
522
523         for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
524                 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
525                         /* skip invalid cache type */
526                         if (!perf_evsel__is_cache_op_valid(type, op))
527                                 continue;
528
529                         for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
530                                 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
531                                                                         name, sizeof(name));
532                                 err = parse_events(evlist, name, 0);
533                                 if (err)
534                                         ret = err;
535                         }
536                 }
537         }
538
539         idx = 0;
540         evsel = perf_evlist__first(evlist);
541
542         for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
543                 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
544                         /* skip invalid cache type */
545                         if (!perf_evsel__is_cache_op_valid(type, op))
546                                 continue;
547
548                         for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
549                                 __perf_evsel__hw_cache_type_op_res_name(type, op, i,
550                                                                         name, sizeof(name));
551                                 if (evsel->idx != idx)
552                                         continue;
553
554                                 ++idx;
555
556                                 if (strcmp(perf_evsel__name(evsel), name)) {
557                                         pr_debug("%s != %s\n", perf_evsel__name(evsel), name);
558                                         ret = -1;
559                                 }
560
561                                 evsel = perf_evsel__next(evsel);
562                         }
563                 }
564         }
565
566         perf_evlist__delete(evlist);
567         return ret;
568 }
569
570 static int __perf_evsel__name_array_test(const char *names[], int nr_names)
571 {
572         int i, err;
573         struct perf_evsel *evsel;
574         struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
575
576         if (evlist == NULL)
577                 return -ENOMEM;
578
579         for (i = 0; i < nr_names; ++i) {
580                 err = parse_events(evlist, names[i], 0);
581                 if (err) {
582                         pr_debug("failed to parse event '%s', err %d\n",
583                                  names[i], err);
584                         goto out_delete_evlist;
585                 }
586         }
587
588         err = 0;
589         list_for_each_entry(evsel, &evlist->entries, node) {
590                 if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
591                         --err;
592                         pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
593                 }
594         }
595
596 out_delete_evlist:
597         perf_evlist__delete(evlist);
598         return err;
599 }
600
601 #define perf_evsel__name_array_test(names) \
602         __perf_evsel__name_array_test(names, ARRAY_SIZE(names))
603
604 static int perf_evsel__roundtrip_name_test(void)
605 {
606         int err = 0, ret = 0;
607
608         err = perf_evsel__name_array_test(perf_evsel__hw_names);
609         if (err)
610                 ret = err;
611
612         err = perf_evsel__name_array_test(perf_evsel__sw_names);
613         if (err)
614                 ret = err;
615
616         err = perf_evsel__roundtrip_cache_name_test();
617         if (err)
618                 ret = err;
619
620         return ret;
621 }
622
623 static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
624                                   int size, bool should_be_signed)
625 {
626         struct format_field *field = perf_evsel__field(evsel, name);
627         int is_signed;
628         int ret = 0;
629
630         if (field == NULL) {
631                 pr_debug("%s: \"%s\" field not found!\n", evsel->name, name);
632                 return -1;
633         }
634
635         is_signed = !!(field->flags | FIELD_IS_SIGNED);
636         if (should_be_signed && !is_signed) {
637                 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
638                          evsel->name, name, is_signed, should_be_signed);
639                 ret = -1;
640         }
641
642         if (field->size != size) {
643                 pr_debug("%s: \"%s\" size (%d) should be %d!\n",
644                          evsel->name, name, field->size, size);
645                 ret = -1;
646         }
647
648         return ret;
649 }
650
651 static int perf_evsel__tp_sched_test(void)
652 {
653         struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0);
654         int ret = 0;
655
656         if (evsel == NULL) {
657                 pr_debug("perf_evsel__new\n");
658                 return -1;
659         }
660
661         if (perf_evsel__test_field(evsel, "prev_comm", 16, true))
662                 ret = -1;
663
664         if (perf_evsel__test_field(evsel, "prev_pid", 4, true))
665                 ret = -1;
666
667         if (perf_evsel__test_field(evsel, "prev_prio", 4, true))
668                 ret = -1;
669
670         if (perf_evsel__test_field(evsel, "prev_state", 8, true))
671                 ret = -1;
672
673         if (perf_evsel__test_field(evsel, "next_comm", 16, true))
674                 ret = -1;
675
676         if (perf_evsel__test_field(evsel, "next_pid", 4, true))
677                 ret = -1;
678
679         if (perf_evsel__test_field(evsel, "next_prio", 4, true))
680                 ret = -1;
681
682         perf_evsel__delete(evsel);
683
684         evsel = perf_evsel__newtp("sched", "sched_wakeup", 0);
685
686         if (perf_evsel__test_field(evsel, "comm", 16, true))
687                 ret = -1;
688
689         if (perf_evsel__test_field(evsel, "pid", 4, true))
690                 ret = -1;
691
692         if (perf_evsel__test_field(evsel, "prio", 4, true))
693                 ret = -1;
694
695         if (perf_evsel__test_field(evsel, "success", 4, true))
696                 ret = -1;
697
698         if (perf_evsel__test_field(evsel, "target_cpu", 4, true))
699                 ret = -1;
700
701         return ret;
702 }
703
704 static int test__syscall_open_tp_fields(void)
705 {
706         struct perf_record_opts opts = {
707                 .target = {
708                         .uid = UINT_MAX,
709                         .uses_mmap = true,
710                 },
711                 .no_delay   = true,
712                 .freq       = 1,
713                 .mmap_pages = 256,
714                 .raw_samples = true,
715         };
716         const char *filename = "/etc/passwd";
717         int flags = O_RDONLY | O_DIRECTORY;
718         struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
719         struct perf_evsel *evsel;
720         int err = -1, i, nr_events = 0, nr_polls = 0;
721
722         if (evlist == NULL) {
723                 pr_debug("%s: perf_evlist__new\n", __func__);
724                 goto out;
725         }
726
727         evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
728         if (evsel == NULL) {
729                 pr_debug("%s: perf_evsel__newtp\n", __func__);
730                 goto out_delete_evlist;
731         }
732
733         perf_evlist__add(evlist, evsel);
734
735         err = perf_evlist__create_maps(evlist, &opts.target);
736         if (err < 0) {
737                 pr_debug("%s: perf_evlist__create_maps\n", __func__);
738                 goto out_delete_evlist;
739         }
740
741         perf_evsel__config(evsel, &opts, evsel);
742
743         evlist->threads->map[0] = getpid();
744
745         err = perf_evlist__open(evlist);
746         if (err < 0) {
747                 pr_debug("perf_evlist__open: %s\n", strerror(errno));
748                 goto out_delete_evlist;
749         }
750
751         err = perf_evlist__mmap(evlist, UINT_MAX, false);
752         if (err < 0) {
753                 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
754                 goto out_delete_evlist;
755         }
756
757         perf_evlist__enable(evlist);
758
759         /*
760          * Generate the event:
761          */
762         open(filename, flags);
763
764         while (1) {
765                 int before = nr_events;
766
767                 for (i = 0; i < evlist->nr_mmaps; i++) {
768                         union perf_event *event;
769
770                         while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
771                                 const u32 type = event->header.type;
772                                 int tp_flags;
773                                 struct perf_sample sample;
774
775                                 ++nr_events;
776
777                                 if (type != PERF_RECORD_SAMPLE)
778                                         continue;
779
780                                 err = perf_evsel__parse_sample(evsel, event, &sample);
781                                 if (err) {
782                                         pr_err("Can't parse sample, err = %d\n", err);
783                                         goto out_munmap;
784                                 }
785
786                                 tp_flags = perf_evsel__intval(evsel, &sample, "flags");
787
788                                 if (flags != tp_flags) {
789                                         pr_debug("%s: Expected flags=%#x, got %#x\n",
790                                                  __func__, flags, tp_flags);
791                                         goto out_munmap;
792                                 }
793
794                                 goto out_ok;
795                         }
796                 }
797
798                 if (nr_events == before)
799                         poll(evlist->pollfd, evlist->nr_fds, 10);
800
801                 if (++nr_polls > 5) {
802                         pr_debug("%s: no events!\n", __func__);
803                         goto out_munmap;
804                 }
805         }
806 out_ok:
807         err = 0;
808 out_munmap:
809         perf_evlist__munmap(evlist);
810 out_delete_evlist:
811         perf_evlist__delete(evlist);
812 out:
813         return err;
814 }
815
816 static struct test {
817         const char *desc;
818         int (*func)(void);
819 } tests[] = {
820         {
821                 .desc = "vmlinux symtab matches kallsyms",
822                 .func = test__vmlinux_matches_kallsyms,
823         },
824         {
825                 .desc = "detect open syscall event",
826                 .func = test__open_syscall_event,
827         },
828         {
829                 .desc = "detect open syscall event on all cpus",
830                 .func = test__open_syscall_event_on_all_cpus,
831         },
832         {
833                 .desc = "read samples using the mmap interface",
834                 .func = test__basic_mmap,
835         },
836         {
837                 .desc = "parse events tests",
838                 .func = parse_events__test,
839         },
840 #if defined(__x86_64__) || defined(__i386__)
841         {
842                 .desc = "x86 rdpmc test",
843                 .func = test__rdpmc,
844         },
845 #endif
846         {
847                 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
848                 .func = test__PERF_RECORD,
849         },
850         {
851                 .desc = "Test perf pmu format parsing",
852                 .func = test__perf_pmu,
853         },
854         {
855                 .desc = "Test dso data interface",
856                 .func = dso__test_data,
857         },
858         {
859                 .desc = "roundtrip evsel->name check",
860                 .func = perf_evsel__roundtrip_name_test,
861         },
862         {
863                 .desc = "Check parsing of sched tracepoints fields",
864                 .func = perf_evsel__tp_sched_test,
865         },
866         {
867                 .desc = "Generate and check syscalls:sys_enter_open event fields",
868                 .func = test__syscall_open_tp_fields,
869         },
870         {
871                 .desc = "struct perf_event_attr setup",
872                 .func = test_attr__run,
873         },
874         {
875                 .func = NULL,
876         },
877 };
878
879 static bool perf_test__matches(int curr, int argc, const char *argv[])
880 {
881         int i;
882
883         if (argc == 0)
884                 return true;
885
886         for (i = 0; i < argc; ++i) {
887                 char *end;
888                 long nr = strtoul(argv[i], &end, 10);
889
890                 if (*end == '\0') {
891                         if (nr == curr + 1)
892                                 return true;
893                         continue;
894                 }
895
896                 if (strstr(tests[curr].desc, argv[i]))
897                         return true;
898         }
899
900         return false;
901 }
902
903 static int __cmd_test(int argc, const char *argv[])
904 {
905         int i = 0;
906         int width = 0;
907
908         while (tests[i].func) {
909                 int len = strlen(tests[i].desc);
910
911                 if (width < len)
912                         width = len;
913                 ++i;
914         }
915
916         i = 0;
917         while (tests[i].func) {
918                 int curr = i++, err;
919
920                 if (!perf_test__matches(curr, argc, argv))
921                         continue;
922
923                 pr_info("%2d: %-*s:", i, width, tests[curr].desc);
924                 pr_debug("\n--- start ---\n");
925                 err = tests[curr].func();
926                 pr_debug("---- end ----\n%s:", tests[curr].desc);
927                 if (err)
928                         color_fprintf(stderr, PERF_COLOR_RED, " FAILED!\n");
929                 else
930                         pr_info(" Ok\n");
931         }
932
933         return 0;
934 }
935
936 static int perf_test__list(int argc, const char **argv)
937 {
938         int i = 0;
939
940         while (tests[i].func) {
941                 int curr = i++;
942
943                 if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
944                         continue;
945
946                 pr_info("%2d: %s\n", i, tests[curr].desc);
947         }
948
949         return 0;
950 }
951
952 int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
953 {
954         const char * const test_usage[] = {
955         "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
956         NULL,
957         };
958         const struct option test_options[] = {
959         OPT_INCR('v', "verbose", &verbose,
960                     "be more verbose (show symbol address, etc)"),
961         OPT_END()
962         };
963
964         argc = parse_options(argc, argv, test_options, test_usage, 0);
965         if (argc >= 1 && !strcmp(argv[0], "list"))
966                 return perf_test__list(argc, argv);
967
968         symbol_conf.priv_size = sizeof(int);
969         symbol_conf.sort_by_name = true;
970         symbol_conf.try_vmlinux_path = true;
971
972         if (symbol__init() < 0)
973                 return -1;
974
975         return __cmd_test(argc, argv);
976 }