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