Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2021 Facebook */
3#define _GNU_SOURCE
4#include <linux/compiler.h>
5#include <test_progs.h>
6#include "testing_helpers.h"
7#include "test_perf_link.skel.h"
8
9#define BURN_TIMEOUT_MS 100
10#define BURN_TIMEOUT_NS BURN_TIMEOUT_MS * 1000000
11
12static void burn_cpu(void)
13{
14 int i;
15
16 /* spin the loop for a while (random high number) */
17 for (i = 0; i < 1000000; ++i)
18 barrier();
19}
20
21void test_perf_link(void)
22{
23 struct test_perf_link *skel = NULL;
24 struct perf_event_attr attr;
25 int pfd = -1, link_fd = -1, err;
26 int run_cnt_before, run_cnt_after;
27 struct bpf_link_info info;
28 __u32 info_len = sizeof(info);
29 __u64 timeout_time_ns;
30
31 /* create perf event */
32 memset(&attr, 0, sizeof(attr));
33 attr.size = sizeof(attr);
34 attr.type = PERF_TYPE_SOFTWARE;
35 attr.config = PERF_COUNT_SW_CPU_CLOCK;
36 attr.freq = 1;
37 attr.sample_freq = 1000;
38 pfd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC);
39 if (!ASSERT_GE(pfd, 0, "perf_fd"))
40 goto cleanup;
41
42 skel = test_perf_link__open_and_load();
43 if (!ASSERT_OK_PTR(skel, "skel_load"))
44 goto cleanup;
45
46 link_fd = bpf_link_create(bpf_program__fd(skel->progs.handler), pfd,
47 BPF_PERF_EVENT, NULL);
48 if (!ASSERT_GE(link_fd, 0, "link_fd"))
49 goto cleanup;
50
51 memset(&info, 0, sizeof(info));
52 err = bpf_link_get_info_by_fd(link_fd, &info, &info_len);
53 if (!ASSERT_OK(err, "link_get_info"))
54 goto cleanup;
55
56 ASSERT_EQ(info.type, BPF_LINK_TYPE_PERF_EVENT, "link_type");
57 ASSERT_GT(info.id, 0, "link_id");
58 ASSERT_GT(info.prog_id, 0, "link_prog_id");
59
60 /* ensure we get at least one perf_event prog execution */
61 timeout_time_ns = get_time_ns() + BURN_TIMEOUT_NS;
62 while (true) {
63 burn_cpu();
64 if (skel->bss->run_cnt > 0)
65 break;
66 if (!ASSERT_LT(get_time_ns(), timeout_time_ns, "run_cnt_timeout"))
67 break;
68 }
69
70 /* perf_event is still active, but we close link and BPF program
71 * shouldn't be executed anymore
72 */
73 close(link_fd);
74 link_fd = -1;
75
76 /* make sure there are no stragglers */
77 kern_sync_rcu();
78
79 run_cnt_before = skel->bss->run_cnt;
80 burn_cpu();
81 run_cnt_after = skel->bss->run_cnt;
82
83 ASSERT_EQ(run_cnt_before, run_cnt_after, "run_cnt_before_after");
84
85cleanup:
86 if (link_fd >= 0)
87 close(link_fd);
88 if (pfd >= 0)
89 close(pfd);
90 test_perf_link__destroy(skel);
91}