Merge tag 'pm-6.9-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-2.6-microblaze.git] / tools / perf / tests / backward-ring-buffer.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test backward bit in event attribute, read ring buffer from end to
4  * beginning
5  */
6
7 #include <evlist.h>
8 #include <sys/prctl.h>
9 #include "record.h"
10 #include "tests.h"
11 #include "debug.h"
12 #include "parse-events.h"
13 #include "util/mmap.h"
14 #include <errno.h>
15 #include <linux/string.h>
16 #include <perf/mmap.h>
17
18 #define NR_ITERS 111
19
20 static void testcase(void)
21 {
22         int i;
23
24         for (i = 0; i < NR_ITERS; i++) {
25                 char proc_name[15];
26
27                 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i);
28                 prctl(PR_SET_NAME, proc_name);
29         }
30 }
31
32 static int count_samples(struct evlist *evlist, int *sample_count,
33                          int *comm_count)
34 {
35         int i;
36
37         for (i = 0; i < evlist->core.nr_mmaps; i++) {
38                 struct mmap *map = &evlist->overwrite_mmap[i];
39                 union perf_event *event;
40
41                 perf_mmap__read_init(&map->core);
42                 while ((event = perf_mmap__read_event(&map->core)) != NULL) {
43                         const u32 type = event->header.type;
44
45                         switch (type) {
46                         case PERF_RECORD_SAMPLE:
47                                 (*sample_count)++;
48                                 break;
49                         case PERF_RECORD_COMM:
50                                 (*comm_count)++;
51                                 break;
52                         default:
53                                 pr_err("Unexpected record of type %d\n", type);
54                                 return TEST_FAIL;
55                         }
56                 }
57                 perf_mmap__read_done(&map->core);
58         }
59         return TEST_OK;
60 }
61
62 static int do_test(struct evlist *evlist, int mmap_pages,
63                    int *sample_count, int *comm_count)
64 {
65         int err;
66         char sbuf[STRERR_BUFSIZE];
67
68         err = evlist__mmap(evlist, mmap_pages);
69         if (err < 0) {
70                 pr_debug("evlist__mmap: %s\n",
71                          str_error_r(errno, sbuf, sizeof(sbuf)));
72                 return TEST_FAIL;
73         }
74
75         evlist__enable(evlist);
76         testcase();
77         evlist__disable(evlist);
78
79         err = count_samples(evlist, sample_count, comm_count);
80         evlist__munmap(evlist);
81         return err;
82 }
83
84
85 static int test__backward_ring_buffer(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
86 {
87         int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
88         char pid[16], sbuf[STRERR_BUFSIZE];
89         struct evlist *evlist;
90         struct evsel *evsel __maybe_unused;
91         struct parse_events_error parse_error;
92         struct record_opts opts = {
93                 .target = {
94                         .uid = UINT_MAX,
95                         .uses_mmap = true,
96                 },
97                 .freq         = 0,
98                 .mmap_pages   = 256,
99                 .default_interval = 1,
100         };
101
102         snprintf(pid, sizeof(pid), "%d", getpid());
103         pid[sizeof(pid) - 1] = '\0';
104         opts.target.tid = opts.target.pid = pid;
105
106         evlist = evlist__new();
107         if (!evlist) {
108                 pr_debug("Not enough memory to create evlist\n");
109                 return TEST_FAIL;
110         }
111
112         err = evlist__create_maps(evlist, &opts.target);
113         if (err < 0) {
114                 pr_debug("Not enough memory to create thread/cpu maps\n");
115                 goto out_delete_evlist;
116         }
117
118         parse_events_error__init(&parse_error);
119         /*
120          * Set backward bit, ring buffer should be writing from end. Record
121          * it in aux evlist
122          */
123         err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error);
124         parse_events_error__exit(&parse_error);
125         if (err) {
126                 pr_debug("Failed to parse tracepoint event, try use root\n");
127                 ret = TEST_SKIP;
128                 goto out_delete_evlist;
129         }
130
131         evlist__config(evlist, &opts, NULL);
132
133         err = evlist__open(evlist);
134         if (err < 0) {
135                 pr_debug("perf_evlist__open: %s\n",
136                          str_error_r(errno, sbuf, sizeof(sbuf)));
137                 goto out_delete_evlist;
138         }
139
140         ret = TEST_FAIL;
141         err = do_test(evlist, opts.mmap_pages, &sample_count,
142                       &comm_count);
143         if (err != TEST_OK)
144                 goto out_delete_evlist;
145
146         if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) {
147                 pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n",
148                        sample_count, comm_count);
149                 goto out_delete_evlist;
150         }
151
152         evlist__close(evlist);
153
154         err = evlist__open(evlist);
155         if (err < 0) {
156                 pr_debug("perf_evlist__open: %s\n",
157                          str_error_r(errno, sbuf, sizeof(sbuf)));
158                 goto out_delete_evlist;
159         }
160
161         err = do_test(evlist, 1, &sample_count, &comm_count);
162         if (err != TEST_OK)
163                 goto out_delete_evlist;
164
165         ret = TEST_OK;
166 out_delete_evlist:
167         evlist__delete(evlist);
168         return ret;
169 }
170
171 DEFINE_SUITE("Read backward ring buffer", backward_ring_buffer);