1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
4 void test_tp_attach_query(void)
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
;
16 for (i
= 0; i
< num_progs
; i
++)
19 snprintf(buf
, sizeof(buf
),
20 "/sys/kernel/debug/tracing/events/sched/sched_switch/id");
21 efd
= open(buf
, O_RDONLY
, 0);
22 if (CHECK(efd
< 0, "open", "err %d errno %d\n", efd
, errno
))
24 bytes
= read(efd
, buf
, sizeof(buf
));
26 if (CHECK(bytes
<= 0 || bytes
>= sizeof(buf
),
27 "read", "bytes %d errno %d\n", bytes
, errno
))
30 attr
.config
= strtol(buf
, NULL
, 0);
31 attr
.type
= PERF_TYPE_TRACEPOINT
;
32 attr
.sample_type
= PERF_SAMPLE_RAW
| PERF_SAMPLE_CALLCHAIN
;
33 attr
.sample_period
= 1;
34 attr
.wakeup_events
= 1;
36 query
= malloc(sizeof(*query
) + sizeof(__u32
) * num_progs
);
37 for (i
= 0; i
< num_progs
; i
++) {
38 err
= bpf_prog_load(file
, BPF_PROG_TYPE_TRACEPOINT
, &obj
[i
],
40 if (CHECK(err
, "prog_load", "err %d errno %d\n", err
, errno
))
43 bzero(&prog_info
, sizeof(prog_info
));
44 prog_info
.jited_prog_len
= 0;
45 prog_info
.xlated_prog_len
= 0;
46 prog_info
.nr_map_ids
= 0;
47 info_len
= sizeof(prog_info
);
48 err
= bpf_obj_get_info_by_fd(prog_fd
[i
], &prog_info
, &info_len
);
49 if (CHECK(err
, "bpf_obj_get_info_by_fd", "err %d errno %d\n",
52 saved_prog_ids
[i
] = prog_info
.id
;
54 pmu_fd
[i
] = syscall(__NR_perf_event_open
, &attr
, -1 /* pid */,
55 0 /* cpu 0 */, -1 /* group id */,
57 if (CHECK(pmu_fd
[i
] < 0, "perf_event_open", "err %d errno %d\n",
60 err
= ioctl(pmu_fd
[i
], PERF_EVENT_IOC_ENABLE
, 0);
61 if (CHECK(err
, "perf_event_ioc_enable", "err %d errno %d\n",
66 /* check NULL prog array query */
67 query
->ids_len
= num_progs
;
68 err
= ioctl(pmu_fd
[i
], PERF_EVENT_IOC_QUERY_BPF
, query
);
69 if (CHECK(err
|| query
->prog_cnt
!= 0,
70 "perf_event_ioc_query_bpf",
71 "err %d errno %d query->prog_cnt %u\n",
72 err
, errno
, query
->prog_cnt
))
76 err
= ioctl(pmu_fd
[i
], PERF_EVENT_IOC_SET_BPF
, prog_fd
[i
]);
77 if (CHECK(err
, "perf_event_ioc_set_bpf", "err %d errno %d\n",
82 /* try to get # of programs only */
84 err
= ioctl(pmu_fd
[i
], PERF_EVENT_IOC_QUERY_BPF
, query
);
85 if (CHECK(err
|| query
->prog_cnt
!= 2,
86 "perf_event_ioc_query_bpf",
87 "err %d errno %d query->prog_cnt %u\n",
88 err
, errno
, query
->prog_cnt
))
91 /* try a few negative tests */
92 /* invalid query pointer */
93 err
= ioctl(pmu_fd
[i
], PERF_EVENT_IOC_QUERY_BPF
,
94 (struct perf_event_query_bpf
*)0x1);
95 if (CHECK(!err
|| errno
!= EFAULT
,
96 "perf_event_ioc_query_bpf",
97 "err %d errno %d\n", err
, errno
))
100 /* no enough space */
102 err
= ioctl(pmu_fd
[i
], PERF_EVENT_IOC_QUERY_BPF
, query
);
103 if (CHECK(!err
|| errno
!= ENOSPC
|| query
->prog_cnt
!= 2,
104 "perf_event_ioc_query_bpf",
105 "err %d errno %d query->prog_cnt %u\n",
106 err
, errno
, query
->prog_cnt
))
110 query
->ids_len
= num_progs
;
111 err
= ioctl(pmu_fd
[i
], PERF_EVENT_IOC_QUERY_BPF
, query
);
112 if (CHECK(err
|| query
->prog_cnt
!= (i
+ 1),
113 "perf_event_ioc_query_bpf",
114 "err %d errno %d query->prog_cnt %u\n",
115 err
, errno
, query
->prog_cnt
))
117 for (j
= 0; j
< i
+ 1; j
++)
118 if (CHECK(saved_prog_ids
[j
] != query
->ids
[j
],
119 "perf_event_ioc_query_bpf",
120 "#%d saved_prog_id %x query prog_id %x\n",
121 j
, saved_prog_ids
[j
], query
->ids
[j
]))
126 for (; i
>= 0; i
--) {
128 ioctl(pmu_fd
[i
], PERF_EVENT_IOC_DISABLE
);
132 bpf_object__close(obj
[i
]);