xref: /openbmc/linux/tools/testing/selftests/bpf/prog_tests/tp_attach_query.c (revision 8f8d5745bb520c76b81abef4a2cb3023d0313bfd)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 
4 void test_tp_attach_query(void)
5 {
6 	const int num_progs = 3;
7 	int i, j, bytes, efd, err, prog_fd[num_progs], pmu_fd[num_progs];
8 	__u32 duration = 0, info_len, saved_prog_ids[num_progs];
9 	const char *file = "./test_tracepoint.o";
10 	struct perf_event_query_bpf *query;
11 	struct perf_event_attr attr = {};
12 	struct bpf_object *obj[num_progs];
13 	struct bpf_prog_info prog_info;
14 	char buf[256];
15 
16 	snprintf(buf, sizeof(buf),
17 		 "/sys/kernel/debug/tracing/events/sched/sched_switch/id");
18 	efd = open(buf, O_RDONLY, 0);
19 	if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
20 		return;
21 	bytes = read(efd, buf, sizeof(buf));
22 	close(efd);
23 	if (CHECK(bytes <= 0 || bytes >= sizeof(buf),
24 		  "read", "bytes %d errno %d\n", bytes, errno))
25 		return;
26 
27 	attr.config = strtol(buf, NULL, 0);
28 	attr.type = PERF_TYPE_TRACEPOINT;
29 	attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
30 	attr.sample_period = 1;
31 	attr.wakeup_events = 1;
32 
33 	query = malloc(sizeof(*query) + sizeof(__u32) * num_progs);
34 	for (i = 0; i < num_progs; i++) {
35 		err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj[i],
36 				    &prog_fd[i]);
37 		if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
38 			goto cleanup1;
39 
40 		bzero(&prog_info, sizeof(prog_info));
41 		prog_info.jited_prog_len = 0;
42 		prog_info.xlated_prog_len = 0;
43 		prog_info.nr_map_ids = 0;
44 		info_len = sizeof(prog_info);
45 		err = bpf_obj_get_info_by_fd(prog_fd[i], &prog_info, &info_len);
46 		if (CHECK(err, "bpf_obj_get_info_by_fd", "err %d errno %d\n",
47 			  err, errno))
48 			goto cleanup1;
49 		saved_prog_ids[i] = prog_info.id;
50 
51 		pmu_fd[i] = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
52 				    0 /* cpu 0 */, -1 /* group id */,
53 				    0 /* flags */);
54 		if (CHECK(pmu_fd[i] < 0, "perf_event_open", "err %d errno %d\n",
55 			  pmu_fd[i], errno))
56 			goto cleanup2;
57 		err = ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0);
58 		if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
59 			  err, errno))
60 			goto cleanup3;
61 
62 		if (i == 0) {
63 			/* check NULL prog array query */
64 			query->ids_len = num_progs;
65 			err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
66 			if (CHECK(err || query->prog_cnt != 0,
67 				  "perf_event_ioc_query_bpf",
68 				  "err %d errno %d query->prog_cnt %u\n",
69 				  err, errno, query->prog_cnt))
70 				goto cleanup3;
71 		}
72 
73 		err = ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF, prog_fd[i]);
74 		if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
75 			  err, errno))
76 			goto cleanup3;
77 
78 		if (i == 1) {
79 			/* try to get # of programs only */
80 			query->ids_len = 0;
81 			err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
82 			if (CHECK(err || query->prog_cnt != 2,
83 				  "perf_event_ioc_query_bpf",
84 				  "err %d errno %d query->prog_cnt %u\n",
85 				  err, errno, query->prog_cnt))
86 				goto cleanup3;
87 
88 			/* try a few negative tests */
89 			/* invalid query pointer */
90 			err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF,
91 				    (struct perf_event_query_bpf *)0x1);
92 			if (CHECK(!err || errno != EFAULT,
93 				  "perf_event_ioc_query_bpf",
94 				  "err %d errno %d\n", err, errno))
95 				goto cleanup3;
96 
97 			/* no enough space */
98 			query->ids_len = 1;
99 			err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
100 			if (CHECK(!err || errno != ENOSPC || query->prog_cnt != 2,
101 				  "perf_event_ioc_query_bpf",
102 				  "err %d errno %d query->prog_cnt %u\n",
103 				  err, errno, query->prog_cnt))
104 				goto cleanup3;
105 		}
106 
107 		query->ids_len = num_progs;
108 		err = ioctl(pmu_fd[i], PERF_EVENT_IOC_QUERY_BPF, query);
109 		if (CHECK(err || query->prog_cnt != (i + 1),
110 			  "perf_event_ioc_query_bpf",
111 			  "err %d errno %d query->prog_cnt %u\n",
112 			  err, errno, query->prog_cnt))
113 			goto cleanup3;
114 		for (j = 0; j < i + 1; j++)
115 			if (CHECK(saved_prog_ids[j] != query->ids[j],
116 				  "perf_event_ioc_query_bpf",
117 				  "#%d saved_prog_id %x query prog_id %x\n",
118 				  j, saved_prog_ids[j], query->ids[j]))
119 				goto cleanup3;
120 	}
121 
122 	i = num_progs - 1;
123 	for (; i >= 0; i--) {
124  cleanup3:
125 		ioctl(pmu_fd[i], PERF_EVENT_IOC_DISABLE);
126  cleanup2:
127 		close(pmu_fd[i]);
128  cleanup1:
129 		bpf_object__close(obj[i]);
130 	}
131 	free(query);
132 }
133