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