1 1.3 alnsn /* $NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn Exp $ */ 2 1.1 alnsn 3 1.1 alnsn /*- 4 1.1 alnsn * Copyright (c) 2014 Alexander Nasonov. 5 1.1 alnsn * All rights reserved. 6 1.1 alnsn * 7 1.1 alnsn * Redistribution and use in source and binary forms, with or without 8 1.1 alnsn * modification, are permitted provided that the following conditions 9 1.1 alnsn * are met: 10 1.1 alnsn * 11 1.1 alnsn * 1. Redistributions of source code must retain the above copyright 12 1.1 alnsn * notice, this list of conditions and the following disclaimer. 13 1.1 alnsn * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 alnsn * notice, this list of conditions and the following disclaimer in 15 1.1 alnsn * the documentation and/or other materials provided with the 16 1.1 alnsn * distribution. 17 1.1 alnsn * 18 1.1 alnsn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 1.1 alnsn * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 1.1 alnsn * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 1.1 alnsn * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 1.1 alnsn * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 alnsn * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 1.1 alnsn * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 1.1 alnsn * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 1.1 alnsn * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 1.1 alnsn * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 1.1 alnsn * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 alnsn * SUCH DAMAGE. 30 1.1 alnsn */ 31 1.1 alnsn 32 1.1 alnsn #include <sys/cdefs.h> 33 1.3 alnsn __RCSID("$NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn Exp $"); 34 1.1 alnsn 35 1.1 alnsn #include <atf-c.h> 36 1.1 alnsn #include <stdint.h> 37 1.1 alnsn #include <string.h> 38 1.1 alnsn 39 1.1 alnsn #define __BPF_PRIVATE 40 1.1 alnsn #include <net/bpf.h> 41 1.1 alnsn #include <net/bpfjit.h> 42 1.1 alnsn 43 1.1 alnsn static uint32_t retM(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 44 1.1 alnsn 45 1.1 alnsn static const bpf_copfunc_t copfuncs[] = { 46 1.1 alnsn &retM 47 1.1 alnsn }; 48 1.1 alnsn 49 1.1 alnsn static const bpf_ctx_t ctx = { 50 1.1 alnsn .copfuncs = copfuncs, 51 1.1 alnsn .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]), 52 1.1 alnsn .extwords = 4, 53 1.1 alnsn .preinited = BPF_MEMWORD_INIT(0) | BPF_MEMWORD_INIT(3), 54 1.1 alnsn }; 55 1.1 alnsn 56 1.1 alnsn static uint32_t 57 1.1 alnsn retM(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 58 1.1 alnsn { 59 1.1 alnsn 60 1.1 alnsn return args->mem[(uintptr_t)args->arg]; 61 1.1 alnsn } 62 1.1 alnsn 63 1.1 alnsn 64 1.2 alnsn ATF_TC(libbpfjit_extmem_load_default); 65 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_load_default, tc) 66 1.1 alnsn { 67 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that external memory " 68 1.1 alnsn "is zero initialized by default"); 69 1.1 alnsn } 70 1.1 alnsn 71 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_load_default, tc) 72 1.1 alnsn { 73 1.1 alnsn static struct bpf_insn insns[] = { 74 1.1 alnsn BPF_STMT(BPF_LD+BPF_MEM, 1), 75 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 76 1.1 alnsn }; 77 1.1 alnsn 78 1.1 alnsn bpfjit_func_t code; 79 1.1 alnsn uint8_t pkt[1] = { 0 }; 80 1.1 alnsn uint32_t mem[ctx.extwords]; 81 1.1 alnsn 82 1.1 alnsn /* Pre-inited words. */ 83 1.1 alnsn mem[0] = 0; 84 1.1 alnsn mem[3] = 3; 85 1.1 alnsn 86 1.1 alnsn bpf_args_t args = { 87 1.1 alnsn .pkt = pkt, 88 1.1 alnsn .buflen = sizeof(pkt), 89 1.1 alnsn .wirelen = sizeof(pkt), 90 1.1 alnsn .mem = mem, 91 1.1 alnsn }; 92 1.1 alnsn 93 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 94 1.1 alnsn 95 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 96 1.1 alnsn ATF_REQUIRE(code != NULL); 97 1.1 alnsn 98 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 0); 99 1.1 alnsn 100 1.1 alnsn bpfjit_free_code(code); 101 1.1 alnsn } 102 1.1 alnsn 103 1.2 alnsn ATF_TC(libbpfjit_extmem_load_preinited); 104 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_load_preinited, tc) 105 1.1 alnsn { 106 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test a load of external " 107 1.1 alnsn "pre-initialized memory"); 108 1.1 alnsn } 109 1.1 alnsn 110 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_load_preinited, tc) 111 1.1 alnsn { 112 1.1 alnsn static struct bpf_insn insns[] = { 113 1.1 alnsn BPF_STMT(BPF_LD+BPF_MEM, 3), 114 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 115 1.1 alnsn }; 116 1.1 alnsn 117 1.1 alnsn bpfjit_func_t code; 118 1.1 alnsn uint8_t pkt[1] = { 0 }; 119 1.1 alnsn uint32_t mem[ctx.extwords]; 120 1.1 alnsn 121 1.1 alnsn /* Pre-inited words. */ 122 1.1 alnsn mem[0] = 0; 123 1.1 alnsn mem[3] = 3; 124 1.1 alnsn 125 1.1 alnsn bpf_args_t args = { 126 1.1 alnsn .pkt = pkt, 127 1.1 alnsn .buflen = sizeof(pkt), 128 1.1 alnsn .wirelen = sizeof(pkt), 129 1.1 alnsn .mem = mem, 130 1.1 alnsn }; 131 1.1 alnsn 132 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 133 1.1 alnsn 134 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 135 1.1 alnsn ATF_REQUIRE(code != NULL); 136 1.1 alnsn 137 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3); 138 1.1 alnsn 139 1.1 alnsn bpfjit_free_code(code); 140 1.1 alnsn } 141 1.1 alnsn 142 1.2 alnsn ATF_TC(libbpfjit_extmem_invalid_load); 143 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_invalid_load, tc) 144 1.1 alnsn { 145 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that out-of-range load " 146 1.1 alnsn "fails validation"); 147 1.1 alnsn } 148 1.1 alnsn 149 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_invalid_load, tc) 150 1.1 alnsn { 151 1.1 alnsn static struct bpf_insn insns[] = { 152 1.1 alnsn BPF_STMT(BPF_LD+BPF_MEM, 4), 153 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 154 1.1 alnsn }; 155 1.1 alnsn 156 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 157 1.1 alnsn 158 1.1 alnsn ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL); 159 1.1 alnsn } 160 1.1 alnsn 161 1.2 alnsn ATF_TC(libbpfjit_extmem_store); 162 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_store, tc) 163 1.1 alnsn { 164 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test stores to external memory"); 165 1.1 alnsn } 166 1.1 alnsn 167 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_store, tc) 168 1.1 alnsn { 169 1.1 alnsn static struct bpf_insn insns[] = { 170 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 1), /* A <- 1 */ 171 1.1 alnsn BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2), /* X <- 2 */ 172 1.1 alnsn BPF_STMT(BPF_ST, 1), /* M[1] <- A */ 173 1.1 alnsn BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0), /* A <- A + X */ 174 1.1 alnsn BPF_STMT(BPF_STX, 2), /* M[2] <- X */ 175 1.1 alnsn BPF_STMT(BPF_ST, 3), /* M[3] <- A */ 176 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) /* ret A */ 177 1.1 alnsn }; 178 1.1 alnsn 179 1.1 alnsn bpfjit_func_t code; 180 1.1 alnsn uint8_t pkt[1] = { 0 }; 181 1.1 alnsn uint32_t mem[ctx.extwords]; 182 1.1 alnsn 183 1.1 alnsn /* Pre-inited words. */ 184 1.1 alnsn mem[0] = 0; 185 1.1 alnsn mem[3] = 7; 186 1.1 alnsn 187 1.1 alnsn mem[1] = mem[2] = 0xdeadbeef; 188 1.1 alnsn 189 1.1 alnsn bpf_args_t args = { 190 1.1 alnsn .pkt = pkt, 191 1.1 alnsn .buflen = sizeof(pkt), 192 1.1 alnsn .wirelen = sizeof(pkt), 193 1.1 alnsn .mem = mem, 194 1.1 alnsn }; 195 1.1 alnsn 196 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 197 1.1 alnsn 198 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 199 1.1 alnsn ATF_REQUIRE(code != NULL); 200 1.1 alnsn 201 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3); 202 1.1 alnsn 203 1.1 alnsn bpfjit_free_code(code); 204 1.1 alnsn 205 1.1 alnsn ATF_CHECK(mem[0] == 0); 206 1.1 alnsn ATF_CHECK(mem[1] == 1); 207 1.1 alnsn ATF_CHECK(mem[2] == 2); 208 1.1 alnsn ATF_CHECK(mem[3] == 3); 209 1.1 alnsn } 210 1.1 alnsn 211 1.2 alnsn ATF_TC(libbpfjit_extmem_side_effect); 212 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_side_effect, tc) 213 1.1 alnsn { 214 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that ABC optimization doesn\'t " 215 1.1 alnsn "skip stores to external memory"); 216 1.1 alnsn } 217 1.1 alnsn 218 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_side_effect, tc) 219 1.1 alnsn { 220 1.1 alnsn static struct bpf_insn insns[] = { 221 1.1 alnsn BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A <- P[0] */ 222 1.1 alnsn BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2), /* X <- 2 */ 223 1.1 alnsn BPF_STMT(BPF_ST, 1), /* M[1] <- A */ 224 1.1 alnsn BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0), /* A <- A + X */ 225 1.1 alnsn BPF_STMT(BPF_STX, 2), /* M[2] <- X */ 226 1.1 alnsn BPF_STMT(BPF_ST, 3), /* M[3] <- A */ 227 1.1 alnsn BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99), /* A <- P[99] */ 228 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) /* ret A */ 229 1.1 alnsn }; 230 1.1 alnsn 231 1.1 alnsn bpfjit_func_t code; 232 1.1 alnsn uint8_t pkt[1] = { 1 }; 233 1.1 alnsn uint32_t mem[ctx.extwords]; 234 1.1 alnsn 235 1.1 alnsn /* Pre-inited words. */ 236 1.1 alnsn mem[0] = 0; 237 1.1 alnsn mem[3] = 7; 238 1.1 alnsn 239 1.1 alnsn mem[1] = mem[2] = 0xdeadbeef; 240 1.1 alnsn 241 1.1 alnsn bpf_args_t args = { 242 1.1 alnsn .pkt = pkt, 243 1.1 alnsn .buflen = sizeof(pkt), 244 1.1 alnsn .wirelen = sizeof(pkt), 245 1.1 alnsn .mem = mem, 246 1.1 alnsn }; 247 1.1 alnsn 248 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 249 1.1 alnsn 250 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 251 1.1 alnsn ATF_REQUIRE(code != NULL); 252 1.1 alnsn 253 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 0); 254 1.1 alnsn 255 1.1 alnsn bpfjit_free_code(code); 256 1.1 alnsn 257 1.1 alnsn ATF_CHECK(mem[0] == 0); 258 1.1 alnsn ATF_CHECK(mem[1] == 1); 259 1.1 alnsn ATF_CHECK(mem[2] == 2); 260 1.1 alnsn ATF_CHECK(mem[3] == 3); 261 1.1 alnsn } 262 1.1 alnsn 263 1.2 alnsn ATF_TC(libbpfjit_extmem_invalid_store); 264 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_invalid_store, tc) 265 1.1 alnsn { 266 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that out-of-range store " 267 1.1 alnsn "fails validation"); 268 1.1 alnsn } 269 1.1 alnsn 270 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_invalid_store, tc) 271 1.1 alnsn { 272 1.1 alnsn static struct bpf_insn insns[] = { 273 1.1 alnsn BPF_STMT(BPF_ST, 4), 274 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 275 1.1 alnsn }; 276 1.1 alnsn 277 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 278 1.1 alnsn 279 1.1 alnsn ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL); 280 1.1 alnsn } 281 1.1 alnsn 282 1.2 alnsn ATF_TC(libbpfjit_cop_ret_mem); 283 1.2 alnsn ATF_TC_HEAD(libbpfjit_cop_ret_mem, tc) 284 1.1 alnsn { 285 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 286 1.1 alnsn "that returns a content of external memory word"); 287 1.1 alnsn } 288 1.1 alnsn 289 1.2 alnsn ATF_TC_BODY(libbpfjit_cop_ret_mem, tc) 290 1.1 alnsn { 291 1.1 alnsn static struct bpf_insn insns[] = { 292 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13), 293 1.1 alnsn BPF_STMT(BPF_ST, 2), 294 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137), 295 1.1 alnsn BPF_STMT(BPF_ST, 1), 296 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COP, 0), // retM 297 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 298 1.1 alnsn }; 299 1.1 alnsn 300 1.1 alnsn bpfjit_func_t code; 301 1.1 alnsn uint8_t pkt[1] = { 0 }; 302 1.1 alnsn uint32_t mem[ctx.extwords]; 303 1.1 alnsn void *arg = (void*)(uintptr_t)2; 304 1.1 alnsn 305 1.1 alnsn /* Pre-inited words. */ 306 1.1 alnsn mem[0] = 0; 307 1.1 alnsn mem[3] = 3; 308 1.1 alnsn 309 1.1 alnsn bpf_args_t args = { 310 1.1 alnsn .pkt = pkt, 311 1.1 alnsn .buflen = sizeof(pkt), 312 1.1 alnsn .wirelen = sizeof(pkt), 313 1.1 alnsn .arg = arg, 314 1.1 alnsn .mem = mem, 315 1.1 alnsn }; 316 1.1 alnsn 317 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 318 1.1 alnsn 319 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 320 1.1 alnsn ATF_REQUIRE(code != NULL); 321 1.1 alnsn 322 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 13); 323 1.1 alnsn 324 1.1 alnsn bpfjit_free_code(code); 325 1.1 alnsn } 326 1.1 alnsn 327 1.2 alnsn ATF_TC(libbpfjit_cop_ret_preinited_mem); 328 1.2 alnsn ATF_TC_HEAD(libbpfjit_cop_ret_preinited_mem, tc) 329 1.1 alnsn { 330 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function that " 331 1.1 alnsn "returns a content of external pre-initialized memory word"); 332 1.1 alnsn } 333 1.1 alnsn 334 1.2 alnsn ATF_TC_BODY(libbpfjit_cop_ret_preinited_mem, tc) 335 1.1 alnsn { 336 1.1 alnsn static struct bpf_insn insns[] = { 337 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13), 338 1.1 alnsn BPF_STMT(BPF_ST, 2), 339 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137), 340 1.1 alnsn BPF_STMT(BPF_ST, 1), 341 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COP, 0), // retM 342 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 343 1.1 alnsn }; 344 1.1 alnsn 345 1.1 alnsn bpfjit_func_t code; 346 1.1 alnsn uint8_t pkt[1] = { 0 }; 347 1.1 alnsn uint32_t mem[ctx.extwords]; 348 1.1 alnsn void *arg = (void*)(uintptr_t)3; 349 1.1 alnsn 350 1.1 alnsn /* Pre-inited words. */ 351 1.1 alnsn mem[0] = 0; 352 1.1 alnsn mem[3] = 3; 353 1.1 alnsn 354 1.1 alnsn bpf_args_t args = { 355 1.1 alnsn .pkt = pkt, 356 1.1 alnsn .buflen = sizeof(pkt), 357 1.1 alnsn .wirelen = sizeof(pkt), 358 1.1 alnsn .arg = arg, 359 1.1 alnsn .mem = mem, 360 1.1 alnsn }; 361 1.1 alnsn 362 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 363 1.1 alnsn 364 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 365 1.1 alnsn ATF_REQUIRE(code != NULL); 366 1.1 alnsn 367 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3); 368 1.1 alnsn 369 1.1 alnsn bpfjit_free_code(code); 370 1.1 alnsn } 371 1.1 alnsn 372 1.2 alnsn ATF_TC(libbpfjit_copx_ret_mem); 373 1.2 alnsn ATF_TC_HEAD(libbpfjit_copx_ret_mem, tc) 374 1.1 alnsn { 375 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 376 1.1 alnsn "that returns a content of external memory word"); 377 1.1 alnsn } 378 1.1 alnsn 379 1.2 alnsn ATF_TC_BODY(libbpfjit_copx_ret_mem, tc) 380 1.1 alnsn { 381 1.1 alnsn static struct bpf_insn insns[] = { 382 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13), 383 1.1 alnsn BPF_STMT(BPF_ST, 2), 384 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137), 385 1.1 alnsn BPF_STMT(BPF_ST, 1), 386 1.1 alnsn BPF_STMT(BPF_LDX+BPF_IMM, 0), // retM 387 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COPX, 0), 388 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 389 1.1 alnsn }; 390 1.1 alnsn 391 1.1 alnsn bpfjit_func_t code; 392 1.1 alnsn uint8_t pkt[1] = { 0 }; 393 1.1 alnsn uint32_t mem[ctx.extwords]; 394 1.1 alnsn void *arg = (void*)(uintptr_t)2; 395 1.1 alnsn 396 1.1 alnsn /* Pre-inited words. */ 397 1.1 alnsn mem[0] = 0; 398 1.1 alnsn mem[3] = 3; 399 1.1 alnsn 400 1.1 alnsn bpf_args_t args = { 401 1.1 alnsn .pkt = pkt, 402 1.1 alnsn .buflen = sizeof(pkt), 403 1.1 alnsn .wirelen = sizeof(pkt), 404 1.1 alnsn .arg = arg, 405 1.1 alnsn .mem = mem, 406 1.1 alnsn }; 407 1.1 alnsn 408 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 409 1.1 alnsn 410 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 411 1.1 alnsn ATF_REQUIRE(code != NULL); 412 1.1 alnsn 413 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 13); 414 1.1 alnsn 415 1.1 alnsn bpfjit_free_code(code); 416 1.1 alnsn } 417 1.1 alnsn 418 1.2 alnsn ATF_TC(libbpfjit_copx_ret_preinited_mem); 419 1.2 alnsn ATF_TC_HEAD(libbpfjit_copx_ret_preinited_mem, tc) 420 1.1 alnsn { 421 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function that " 422 1.1 alnsn "returns a content of external pre-initialized memory word"); 423 1.1 alnsn } 424 1.1 alnsn 425 1.2 alnsn ATF_TC_BODY(libbpfjit_copx_ret_preinited_mem, tc) 426 1.1 alnsn { 427 1.1 alnsn static struct bpf_insn insns[] = { 428 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13), 429 1.1 alnsn BPF_STMT(BPF_ST, 2), 430 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137), 431 1.1 alnsn BPF_STMT(BPF_ST, 1), 432 1.1 alnsn BPF_STMT(BPF_LDX+BPF_IMM, 0), // retM 433 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COPX, 0), 434 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) 435 1.1 alnsn }; 436 1.1 alnsn 437 1.1 alnsn bpfjit_func_t code; 438 1.1 alnsn uint8_t pkt[1] = { 0 }; 439 1.1 alnsn uint32_t mem[ctx.extwords]; 440 1.1 alnsn void *arg = (void*)(uintptr_t)3; 441 1.1 alnsn 442 1.1 alnsn /* Pre-inited words. */ 443 1.1 alnsn mem[0] = 0; 444 1.1 alnsn mem[3] = 3; 445 1.1 alnsn 446 1.1 alnsn bpf_args_t args = { 447 1.1 alnsn .pkt = pkt, 448 1.1 alnsn .buflen = sizeof(pkt), 449 1.1 alnsn .wirelen = sizeof(pkt), 450 1.1 alnsn .arg = arg, 451 1.1 alnsn .mem = mem, 452 1.1 alnsn }; 453 1.1 alnsn 454 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]); 455 1.1 alnsn 456 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count); 457 1.1 alnsn ATF_REQUIRE(code != NULL); 458 1.1 alnsn 459 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3); 460 1.1 alnsn 461 1.1 alnsn bpfjit_free_code(code); 462 1.1 alnsn } 463 1.1 alnsn 464 1.1 alnsn ATF_TP_ADD_TCS(tp) 465 1.1 alnsn { 466 1.1 alnsn 467 1.3 alnsn /* 468 1.3 alnsn * For every new test please also add a similar test 469 1.3 alnsn * to ../../net/bpfjit/t_extmem.c 470 1.3 alnsn */ 471 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_load_default); 472 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_load_preinited); 473 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_invalid_load); 474 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_store); 475 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_side_effect); 476 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_invalid_store); 477 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_mem); 478 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_preinited_mem); 479 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_mem); 480 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_preinited_mem); 481 1.1 alnsn 482 1.1 alnsn return atf_no_error(); 483 1.1 alnsn } 484