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