1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <test_progs.h> 4 5 #include "atomics.skel.h" 6 7 static void test_add(struct atomics *skel) 8 { 9 int err, prog_fd; 10 __u32 duration = 0, retval; 11 struct bpf_link *link; 12 13 link = bpf_program__attach(skel->progs.add); 14 if (CHECK(IS_ERR(link), "attach(add)", "err: %ld\n", PTR_ERR(link))) 15 return; 16 17 prog_fd = bpf_program__fd(skel->progs.add); 18 err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 19 NULL, NULL, &retval, &duration); 20 if (CHECK(err || retval, "test_run add", 21 "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) 22 goto cleanup; 23 24 ASSERT_EQ(skel->data->add64_value, 3, "add64_value"); 25 ASSERT_EQ(skel->bss->add64_result, 1, "add64_result"); 26 27 ASSERT_EQ(skel->data->add32_value, 3, "add32_value"); 28 ASSERT_EQ(skel->bss->add32_result, 1, "add32_result"); 29 30 ASSERT_EQ(skel->bss->add_stack_value_copy, 3, "add_stack_value"); 31 ASSERT_EQ(skel->bss->add_stack_result, 1, "add_stack_result"); 32 33 ASSERT_EQ(skel->data->add_noreturn_value, 3, "add_noreturn_value"); 34 35 cleanup: 36 bpf_link__destroy(link); 37 } 38 39 static void test_sub(struct atomics *skel) 40 { 41 int err, prog_fd; 42 __u32 duration = 0, retval; 43 struct bpf_link *link; 44 45 link = bpf_program__attach(skel->progs.sub); 46 if (CHECK(IS_ERR(link), "attach(sub)", "err: %ld\n", PTR_ERR(link))) 47 return; 48 49 prog_fd = bpf_program__fd(skel->progs.sub); 50 err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 51 NULL, NULL, &retval, &duration); 52 if (CHECK(err || retval, "test_run sub", 53 "err %d errno %d retval %d duration %d\n", 54 err, errno, retval, duration)) 55 goto cleanup; 56 57 ASSERT_EQ(skel->data->sub64_value, -1, "sub64_value"); 58 ASSERT_EQ(skel->bss->sub64_result, 1, "sub64_result"); 59 60 ASSERT_EQ(skel->data->sub32_value, -1, "sub32_value"); 61 ASSERT_EQ(skel->bss->sub32_result, 1, "sub32_result"); 62 63 ASSERT_EQ(skel->bss->sub_stack_value_copy, -1, "sub_stack_value"); 64 ASSERT_EQ(skel->bss->sub_stack_result, 1, "sub_stack_result"); 65 66 ASSERT_EQ(skel->data->sub_noreturn_value, -1, "sub_noreturn_value"); 67 68 cleanup: 69 bpf_link__destroy(link); 70 } 71 72 static void test_and(struct atomics *skel) 73 { 74 int err, prog_fd; 75 __u32 duration = 0, retval; 76 struct bpf_link *link; 77 78 link = bpf_program__attach(skel->progs.and); 79 if (CHECK(IS_ERR(link), "attach(and)", "err: %ld\n", PTR_ERR(link))) 80 return; 81 82 prog_fd = bpf_program__fd(skel->progs.and); 83 err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 84 NULL, NULL, &retval, &duration); 85 if (CHECK(err || retval, "test_run and", 86 "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) 87 goto cleanup; 88 89 ASSERT_EQ(skel->data->and64_value, 0x010ull << 32, "and64_value"); 90 ASSERT_EQ(skel->bss->and64_result, 0x110ull << 32, "and64_result"); 91 92 ASSERT_EQ(skel->data->and32_value, 0x010, "and32_value"); 93 ASSERT_EQ(skel->bss->and32_result, 0x110, "and32_result"); 94 95 ASSERT_EQ(skel->data->and_noreturn_value, 0x010ull << 32, "and_noreturn_value"); 96 cleanup: 97 bpf_link__destroy(link); 98 } 99 100 static void test_or(struct atomics *skel) 101 { 102 int err, prog_fd; 103 __u32 duration = 0, retval; 104 struct bpf_link *link; 105 106 link = bpf_program__attach(skel->progs.or); 107 if (CHECK(IS_ERR(link), "attach(or)", "err: %ld\n", PTR_ERR(link))) 108 return; 109 110 prog_fd = bpf_program__fd(skel->progs.or); 111 err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 112 NULL, NULL, &retval, &duration); 113 if (CHECK(err || retval, "test_run or", 114 "err %d errno %d retval %d duration %d\n", 115 err, errno, retval, duration)) 116 goto cleanup; 117 118 ASSERT_EQ(skel->data->or64_value, 0x111ull << 32, "or64_value"); 119 ASSERT_EQ(skel->bss->or64_result, 0x110ull << 32, "or64_result"); 120 121 ASSERT_EQ(skel->data->or32_value, 0x111, "or32_value"); 122 ASSERT_EQ(skel->bss->or32_result, 0x110, "or32_result"); 123 124 ASSERT_EQ(skel->data->or_noreturn_value, 0x111ull << 32, "or_noreturn_value"); 125 cleanup: 126 bpf_link__destroy(link); 127 } 128 129 static void test_xor(struct atomics *skel) 130 { 131 int err, prog_fd; 132 __u32 duration = 0, retval; 133 struct bpf_link *link; 134 135 link = bpf_program__attach(skel->progs.xor); 136 if (CHECK(IS_ERR(link), "attach(xor)", "err: %ld\n", PTR_ERR(link))) 137 return; 138 139 prog_fd = bpf_program__fd(skel->progs.xor); 140 err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 141 NULL, NULL, &retval, &duration); 142 if (CHECK(err || retval, "test_run xor", 143 "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) 144 goto cleanup; 145 146 ASSERT_EQ(skel->data->xor64_value, 0x101ull << 32, "xor64_value"); 147 ASSERT_EQ(skel->bss->xor64_result, 0x110ull << 32, "xor64_result"); 148 149 ASSERT_EQ(skel->data->xor32_value, 0x101, "xor32_value"); 150 ASSERT_EQ(skel->bss->xor32_result, 0x110, "xor32_result"); 151 152 ASSERT_EQ(skel->data->xor_noreturn_value, 0x101ull << 32, "xor_nxoreturn_value"); 153 cleanup: 154 bpf_link__destroy(link); 155 } 156 157 static void test_cmpxchg(struct atomics *skel) 158 { 159 int err, prog_fd; 160 __u32 duration = 0, retval; 161 struct bpf_link *link; 162 163 link = bpf_program__attach(skel->progs.cmpxchg); 164 if (CHECK(IS_ERR(link), "attach(cmpxchg)", "err: %ld\n", PTR_ERR(link))) 165 return; 166 167 prog_fd = bpf_program__fd(skel->progs.cmpxchg); 168 err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 169 NULL, NULL, &retval, &duration); 170 if (CHECK(err || retval, "test_run add", 171 "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) 172 goto cleanup; 173 174 ASSERT_EQ(skel->data->cmpxchg64_value, 2, "cmpxchg64_value"); 175 ASSERT_EQ(skel->bss->cmpxchg64_result_fail, 1, "cmpxchg_result_fail"); 176 ASSERT_EQ(skel->bss->cmpxchg64_result_succeed, 1, "cmpxchg_result_succeed"); 177 178 ASSERT_EQ(skel->data->cmpxchg32_value, 2, "lcmpxchg32_value"); 179 ASSERT_EQ(skel->bss->cmpxchg32_result_fail, 1, "cmpxchg_result_fail"); 180 ASSERT_EQ(skel->bss->cmpxchg32_result_succeed, 1, "cmpxchg_result_succeed"); 181 182 cleanup: 183 bpf_link__destroy(link); 184 } 185 186 static void test_xchg(struct atomics *skel) 187 { 188 int err, prog_fd; 189 __u32 duration = 0, retval; 190 struct bpf_link *link; 191 192 link = bpf_program__attach(skel->progs.xchg); 193 if (CHECK(IS_ERR(link), "attach(xchg)", "err: %ld\n", PTR_ERR(link))) 194 return; 195 196 prog_fd = bpf_program__fd(skel->progs.xchg); 197 err = bpf_prog_test_run(prog_fd, 1, NULL, 0, 198 NULL, NULL, &retval, &duration); 199 if (CHECK(err || retval, "test_run add", 200 "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) 201 goto cleanup; 202 203 ASSERT_EQ(skel->data->xchg64_value, 2, "xchg64_value"); 204 ASSERT_EQ(skel->bss->xchg64_result, 1, "xchg64_result"); 205 206 ASSERT_EQ(skel->data->xchg32_value, 2, "xchg32_value"); 207 ASSERT_EQ(skel->bss->xchg32_result, 1, "xchg32_result"); 208 209 cleanup: 210 bpf_link__destroy(link); 211 } 212 213 void test_atomics(void) 214 { 215 struct atomics *skel; 216 __u32 duration = 0; 217 218 skel = atomics__open_and_load(); 219 if (CHECK(!skel, "skel_load", "atomics skeleton failed\n")) 220 return; 221 222 if (skel->data->skip_tests) { 223 printf("%s:SKIP:no ENABLE_ATOMICS_TESTS (missing Clang BPF atomics support)", 224 __func__); 225 test__skip(); 226 goto cleanup; 227 } 228 229 if (test__start_subtest("add")) 230 test_add(skel); 231 if (test__start_subtest("sub")) 232 test_sub(skel); 233 if (test__start_subtest("and")) 234 test_and(skel); 235 if (test__start_subtest("or")) 236 test_or(skel); 237 if (test__start_subtest("xor")) 238 test_xor(skel); 239 if (test__start_subtest("cmpxchg")) 240 test_cmpxchg(skel); 241 if (test__start_subtest("xchg")) 242 test_xchg(skel); 243 244 cleanup: 245 atomics__destroy(skel); 246 } 247