--- tools/include/uapi/linux/perf_event.h | 23 ++++++++++ .../selftests/bpf/prog_tests/attach_probe.c | 43 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index 7198ddd0c6b1..4a5e18606baf 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -447,6 +447,28 @@ struct perf_event_query_bpf { __u32 ids[0]; }; +/* + * Structure used by below PERF_EVENT_IOC_QUERY_KPROE command + * to query information about the kprobe attached to the perf + * event. + */ +struct perf_event_query_kprobe { + /* + * Size of structure for forward/backward compatibility + */ + __u32 size; + /* + * Set by the kernel to indicate number of times this kprobe + * was temporarily disabled + */ + __u64 nmissed; + /* + * Set by the kernel to indicate number of times this kprobe + * was hit + */ + __u64 nhit; +}; + /* * Ioctls that can be done on a perf event fd: */ @@ -462,6 +484,7 @@ struct perf_event_query_bpf { #define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) #define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *) #define PERF_EVENT_IOC_MODIFY_ATTRIBUTES _IOW('$', 11, struct perf_event_attr *) +#define PERF_EVENT_IOC_QUERY_KPROBE _IOWR('$', 12, struct perf_event_query_kprobe *) enum perf_event_ioc_flags { PERF_IOC_FLAG_GROUP = 1U << 0, diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c index 5ecc267d98b0..5f118e9a1469 100644 --- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c +++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c @@ -38,9 +38,12 @@ void test_attach_probe(void) struct bpf_link *kretprobe_link = NULL; struct bpf_link *uprobe_link = NULL; struct bpf_link *uretprobe_link = NULL; + int kprobe_fd, kretprobe_fd; int results_map_fd; size_t uprobe_offset; ssize_t base_addr; + struct perf_event_query_kprobe kprobe_query; + struct perf_event_query_kprobe kretprobe_query; base_addr = get_base_addr(); if (CHECK(base_addr < 0, "get_base_addr", @@ -116,6 +119,46 @@ void test_attach_probe(void) /* trigger & validate kprobe && kretprobe */ usleep(1); + kprobe_fd = bpf_link__get_perf_fd(kprobe_link); + if (CHECK(kprobe_fd < 0, "kprobe_get_perf_fd", + "failed to get perf fd from kprobe link\n")) + goto cleanup; + + kretprobe_fd = bpf_link__get_perf_fd(kretprobe_link); + if (CHECK(kprobe_fd < 0, "kprobe_get_perf_fd", + "failed to get perf fd from kprobe link\n")) + goto cleanup; + + memset(&kprobe_query, 0, sizeof(kprobe_query)); + kprobe_query.size = sizeof(kprobe_query); + err = ioctl(kprobe_fd, PERF_EVENT_IOC_QUERY_KPROBE, &kprobe_query); + if (CHECK(err, "get_kprobe_ioctl", + "failed to issue kprobe query ioctl\n")) + goto cleanup; + if (CHECK(kprobe_query.nmissed > 0, "get_kprobe_ioctl", + "read incorect nmissed from kprobe_ioctl: %llu\n", + kprobe_query.nmissed)) + goto cleanup; + if (CHECK(kprobe_query.nhit <= 0, "get_kprobe_ioctl", + "read incorect nhit from kprobe_ioctl: %llu\n", + kprobe_query.nhit)) + goto cleanup; + + memset(&kretprobe_query, 0, sizeof(kretprobe_query)); + kretprobe_query.size = sizeof(kretprobe_query); + err = ioctl(kretprobe_fd, PERF_EVENT_IOC_QUERY_KPROBE, &kretprobe_query); + if (CHECK(err, "get_kretprobe_ioctl", + "failed to issue kprobe query ioctl\n")) + goto cleanup; + if (CHECK(kretprobe_query.nmissed > 0, "get_kretprobe_ioctl", + "read incorect nmissed from kretprobe_ioctl: %llu\n", + kretprobe_query.nmissed)) + goto cleanup; + if (CHECK(kretprobe_query.nhit <= 0, "get_kretprobe_ioctl", + "read incorect nhit from kretprobe_ioctl: %llu\n", + kretprobe_query.nhit)) + goto cleanup; + err = bpf_map_lookup_elem(results_map_fd, &kprobe_idx, &res); if (CHECK(err, "get_kprobe_res", "failed to get kprobe res: %d\n", err)) -- 2.20.1