GNU Linux-libre 4.9.309-gnu1
[releases.git] / tools / perf / tests / bpf.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/epoll.h>
4 #include <util/util.h>
5 #include <util/bpf-loader.h>
6 #include <util/evlist.h>
7 #include <linux/bpf.h>
8 #include <linux/filter.h>
9 #include <bpf/bpf.h>
10 #include "tests.h"
11 #include "llvm.h"
12 #include "debug.h"
13 #define NR_ITERS       111
14
15 #ifdef HAVE_LIBBPF_SUPPORT
16
17 static int epoll_wait_loop(void)
18 {
19         int i;
20
21         /* Should fail NR_ITERS times */
22         for (i = 0; i < NR_ITERS; i++)
23                 epoll_wait(-(i + 1), NULL, 0, 0);
24         return 0;
25 }
26
27 #ifdef HAVE_BPF_PROLOGUE
28
29 static int llseek_loop(void)
30 {
31         int fds[2], i;
32
33         fds[0] = open("/dev/null", O_RDONLY);
34         fds[1] = open("/dev/null", O_RDWR);
35
36         if (fds[0] < 0 || fds[1] < 0)
37                 return -1;
38
39         for (i = 0; i < NR_ITERS; i++) {
40                 lseek(fds[i % 2], i, (i / 2) % 2 ? SEEK_CUR : SEEK_SET);
41                 lseek(fds[(i + 1) % 2], i, (i / 2) % 2 ? SEEK_CUR : SEEK_SET);
42         }
43         close(fds[0]);
44         close(fds[1]);
45         return 0;
46 }
47
48 #endif
49
50 static struct {
51         enum test_llvm__testcase prog_id;
52         const char *desc;
53         const char *name;
54         const char *msg_compile_fail;
55         const char *msg_load_fail;
56         int (*target_func)(void);
57         int expect_result;
58 } bpf_testcase_table[] = {
59         {
60                 LLVM_TESTCASE_BASE,
61                 "Test basic BPF filtering",
62                 "[basic_bpf_test]",
63                 "fix 'perf test LLVM' first",
64                 "load bpf object failed",
65                 &epoll_wait_loop,
66                 (NR_ITERS + 1) / 2,
67         },
68 #ifdef HAVE_BPF_PROLOGUE
69         {
70                 LLVM_TESTCASE_BPF_PROLOGUE,
71                 "Test BPF prologue generation",
72                 "[bpf_prologue_test]",
73                 "fix kbuild first",
74                 "check your vmlinux setting?",
75                 &llseek_loop,
76                 (NR_ITERS + 1) / 4,
77         },
78 #endif
79         {
80                 LLVM_TESTCASE_BPF_RELOCATION,
81                 "Test BPF relocation checker",
82                 "[bpf_relocation_test]",
83                 "fix 'perf test LLVM' first",
84                 "libbpf error when dealing with relocation",
85                 NULL,
86                 0,
87         },
88 };
89
90 static int do_test(struct bpf_object *obj, int (*func)(void),
91                    int expect)
92 {
93         struct record_opts opts = {
94                 .target = {
95                         .uid = UINT_MAX,
96                         .uses_mmap = true,
97                 },
98                 .freq         = 0,
99                 .mmap_pages   = 256,
100                 .default_interval = 1,
101         };
102
103         char pid[16];
104         char sbuf[STRERR_BUFSIZE];
105         struct perf_evlist *evlist;
106         int i, ret = TEST_FAIL, err = 0, count = 0;
107
108         struct parse_events_evlist parse_evlist;
109         struct parse_events_error parse_error;
110
111         bzero(&parse_error, sizeof(parse_error));
112         bzero(&parse_evlist, sizeof(parse_evlist));
113         parse_evlist.error = &parse_error;
114         INIT_LIST_HEAD(&parse_evlist.list);
115
116         err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj, NULL);
117         if (err || list_empty(&parse_evlist.list)) {
118                 pr_debug("Failed to add events selected by BPF\n");
119                 return TEST_FAIL;
120         }
121
122         snprintf(pid, sizeof(pid), "%d", getpid());
123         pid[sizeof(pid) - 1] = '\0';
124         opts.target.tid = opts.target.pid = pid;
125
126         /* Instead of perf_evlist__new_default, don't add default events */
127         evlist = perf_evlist__new();
128         if (!evlist) {
129                 pr_debug("No enough memory to create evlist\n");
130                 return TEST_FAIL;
131         }
132
133         err = perf_evlist__create_maps(evlist, &opts.target);
134         if (err < 0) {
135                 pr_debug("Not enough memory to create thread/cpu maps\n");
136                 goto out_delete_evlist;
137         }
138
139         perf_evlist__splice_list_tail(evlist, &parse_evlist.list);
140         evlist->nr_groups = parse_evlist.nr_groups;
141
142         perf_evlist__config(evlist, &opts, NULL);
143
144         err = perf_evlist__open(evlist);
145         if (err < 0) {
146                 pr_debug("perf_evlist__open: %s\n",
147                          str_error_r(errno, sbuf, sizeof(sbuf)));
148                 goto out_delete_evlist;
149         }
150
151         err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
152         if (err < 0) {
153                 pr_debug("perf_evlist__mmap: %s\n",
154                          str_error_r(errno, sbuf, sizeof(sbuf)));
155                 goto out_delete_evlist;
156         }
157
158         perf_evlist__enable(evlist);
159         (*func)();
160         perf_evlist__disable(evlist);
161
162         for (i = 0; i < evlist->nr_mmaps; i++) {
163                 union perf_event *event;
164
165                 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
166                         const u32 type = event->header.type;
167
168                         if (type == PERF_RECORD_SAMPLE)
169                                 count ++;
170                 }
171         }
172
173         if (count != expect) {
174                 pr_debug("BPF filter result incorrect\n");
175                 goto out_delete_evlist;
176         }
177
178         ret = TEST_OK;
179
180 out_delete_evlist:
181         perf_evlist__delete(evlist);
182         return ret;
183 }
184
185 static struct bpf_object *
186 prepare_bpf(void *obj_buf, size_t obj_buf_sz, const char *name)
187 {
188         struct bpf_object *obj;
189
190         obj = bpf__prepare_load_buffer(obj_buf, obj_buf_sz, name);
191         if (IS_ERR(obj)) {
192                 pr_debug("Compile BPF program failed.\n");
193                 return NULL;
194         }
195         return obj;
196 }
197
198 static int __test__bpf(int idx)
199 {
200         int ret;
201         void *obj_buf;
202         size_t obj_buf_sz;
203         struct bpf_object *obj;
204
205         ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
206                                        bpf_testcase_table[idx].prog_id,
207                                        true, NULL);
208         if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
209                 pr_debug("Unable to get BPF object, %s\n",
210                          bpf_testcase_table[idx].msg_compile_fail);
211                 if (idx == 0)
212                         return TEST_SKIP;
213                 else
214                         return TEST_FAIL;
215         }
216
217         obj = prepare_bpf(obj_buf, obj_buf_sz,
218                           bpf_testcase_table[idx].name);
219         if ((!!bpf_testcase_table[idx].target_func) != (!!obj)) {
220                 if (!obj)
221                         pr_debug("Fail to load BPF object: %s\n",
222                                  bpf_testcase_table[idx].msg_load_fail);
223                 else
224                         pr_debug("Success unexpectedly: %s\n",
225                                  bpf_testcase_table[idx].msg_load_fail);
226                 ret = TEST_FAIL;
227                 goto out;
228         }
229
230         if (obj)
231                 ret = do_test(obj,
232                               bpf_testcase_table[idx].target_func,
233                               bpf_testcase_table[idx].expect_result);
234 out:
235         free(obj_buf);
236         bpf__clear();
237         return ret;
238 }
239
240 int test__bpf_subtest_get_nr(void)
241 {
242         return (int)ARRAY_SIZE(bpf_testcase_table);
243 }
244
245 const char *test__bpf_subtest_get_desc(int i)
246 {
247         if (i < 0 || i >= (int)ARRAY_SIZE(bpf_testcase_table))
248                 return NULL;
249         return bpf_testcase_table[i].desc;
250 }
251
252 static int check_env(void)
253 {
254         int err;
255         unsigned int kver_int;
256         char license[] = "GPL";
257
258         struct bpf_insn insns[] = {
259                 BPF_MOV64_IMM(BPF_REG_0, 1),
260                 BPF_EXIT_INSN(),
261         };
262
263         err = fetch_kernel_version(&kver_int, NULL, 0);
264         if (err) {
265                 pr_debug("Unable to get kernel version\n");
266                 return err;
267         }
268
269         err = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
270                                sizeof(insns) / sizeof(insns[0]),
271                                license, kver_int, NULL, 0);
272         if (err < 0) {
273                 pr_err("Missing basic BPF support, skip this test: %s\n",
274                        strerror(errno));
275                 return err;
276         }
277         close(err);
278
279         return 0;
280 }
281
282 int test__bpf(int i)
283 {
284         int err;
285
286         if (i < 0 || i >= (int)ARRAY_SIZE(bpf_testcase_table))
287                 return TEST_FAIL;
288
289         if (geteuid() != 0) {
290                 pr_debug("Only root can run BPF test\n");
291                 return TEST_SKIP;
292         }
293
294         if (check_env())
295                 return TEST_SKIP;
296
297         err = __test__bpf(i);
298         return err;
299 }
300
301 #else
302 int test__bpf_subtest_get_nr(void)
303 {
304         return 0;
305 }
306
307 const char *test__bpf_subtest_get_desc(int i __maybe_unused)
308 {
309         return NULL;
310 }
311
312 int test__bpf(int i __maybe_unused)
313 {
314         pr_debug("Skip BPF test because BPF support is not compiled\n");
315         return TEST_SKIP;
316 }
317 #endif