1*57718be8SEnji Cooper /* $NetBSD: t_cop.c,v 1.4 2014/07/13 21:35:33 alnsn Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2013-2014 Alexander Nasonov. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 8*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 9*57718be8SEnji Cooper * are met: 10*57718be8SEnji Cooper * 11*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 12*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 13*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 14*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in 15*57718be8SEnji Cooper * the documentation and/or other materials provided with the 16*57718be8SEnji Cooper * distribution. 17*57718be8SEnji Cooper * 18*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20*57718be8SEnji Cooper * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21*57718be8SEnji Cooper * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22*57718be8SEnji Cooper * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23*57718be8SEnji Cooper * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24*57718be8SEnji Cooper * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25*57718be8SEnji Cooper * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26*57718be8SEnji Cooper * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27*57718be8SEnji Cooper * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28*57718be8SEnji Cooper * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29*57718be8SEnji Cooper * SUCH DAMAGE. 30*57718be8SEnji Cooper */ 31*57718be8SEnji Cooper 32*57718be8SEnji Cooper #include <sys/cdefs.h> 33*57718be8SEnji Cooper __RCSID("$NetBSD: t_cop.c,v 1.4 2014/07/13 21:35:33 alnsn Exp $"); 34*57718be8SEnji Cooper 35*57718be8SEnji Cooper #include <atf-c.h> 36*57718be8SEnji Cooper #include <stdint.h> 37*57718be8SEnji Cooper #include <string.h> 38*57718be8SEnji Cooper 39*57718be8SEnji Cooper #define __BPF_PRIVATE 40*57718be8SEnji Cooper #include <net/bpf.h> 41*57718be8SEnji Cooper #include <net/bpfjit.h> 42*57718be8SEnji Cooper 43*57718be8SEnji Cooper static uint32_t retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 44*57718be8SEnji Cooper static uint32_t retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 45*57718be8SEnji Cooper static uint32_t retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 46*57718be8SEnji Cooper static uint32_t retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 47*57718be8SEnji Cooper static uint32_t setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A); 48*57718be8SEnji Cooper 49*57718be8SEnji Cooper static const bpf_copfunc_t copfuncs[] = { 50*57718be8SEnji Cooper &retA, 51*57718be8SEnji Cooper &retBL, 52*57718be8SEnji Cooper &retWL, 53*57718be8SEnji Cooper &retNF, 54*57718be8SEnji Cooper &setARG 55*57718be8SEnji Cooper }; 56*57718be8SEnji Cooper 57*57718be8SEnji Cooper static const bpf_ctx_t ctx = { 58*57718be8SEnji Cooper .copfuncs = copfuncs, 59*57718be8SEnji Cooper .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]), 60*57718be8SEnji Cooper .extwords = 0 61*57718be8SEnji Cooper }; 62*57718be8SEnji Cooper 63*57718be8SEnji Cooper static uint32_t 64*57718be8SEnji Cooper retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 65*57718be8SEnji Cooper { 66*57718be8SEnji Cooper 67*57718be8SEnji Cooper return A; 68*57718be8SEnji Cooper } 69*57718be8SEnji Cooper 70*57718be8SEnji Cooper static uint32_t 71*57718be8SEnji Cooper retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 72*57718be8SEnji Cooper { 73*57718be8SEnji Cooper 74*57718be8SEnji Cooper return args->buflen; 75*57718be8SEnji Cooper } 76*57718be8SEnji Cooper 77*57718be8SEnji Cooper static uint32_t 78*57718be8SEnji Cooper retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 79*57718be8SEnji Cooper { 80*57718be8SEnji Cooper 81*57718be8SEnji Cooper return args->wirelen; 82*57718be8SEnji Cooper } 83*57718be8SEnji Cooper 84*57718be8SEnji Cooper static uint32_t 85*57718be8SEnji Cooper retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 86*57718be8SEnji Cooper { 87*57718be8SEnji Cooper 88*57718be8SEnji Cooper return bc->nfuncs; 89*57718be8SEnji Cooper } 90*57718be8SEnji Cooper 91*57718be8SEnji Cooper /* 92*57718be8SEnji Cooper * COP function with a side effect. 93*57718be8SEnji Cooper */ 94*57718be8SEnji Cooper static uint32_t 95*57718be8SEnji Cooper setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A) 96*57718be8SEnji Cooper { 97*57718be8SEnji Cooper bool *arg = (bool *)args->arg; 98*57718be8SEnji Cooper bool old = *arg; 99*57718be8SEnji Cooper 100*57718be8SEnji Cooper *arg = true; 101*57718be8SEnji Cooper return old; 102*57718be8SEnji Cooper } 103*57718be8SEnji Cooper 104*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_no_ctx); 105*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_no_ctx, tc) 106*57718be8SEnji Cooper { 107*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COP " 108*57718be8SEnji Cooper "instruction isn't valid without a context"); 109*57718be8SEnji Cooper } 110*57718be8SEnji Cooper 111*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_no_ctx, tc) 112*57718be8SEnji Cooper { 113*57718be8SEnji Cooper static struct bpf_insn insns[] = { 114*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 0), 115*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_K, 7) 116*57718be8SEnji Cooper }; 117*57718be8SEnji Cooper 118*57718be8SEnji Cooper bpfjit_func_t code; 119*57718be8SEnji Cooper 120*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 121*57718be8SEnji Cooper 122*57718be8SEnji Cooper ATF_CHECK(!bpf_validate(insns, insn_count)); 123*57718be8SEnji Cooper 124*57718be8SEnji Cooper code = bpfjit_generate_code(NULL, insns, insn_count); 125*57718be8SEnji Cooper ATF_CHECK(code == NULL); 126*57718be8SEnji Cooper } 127*57718be8SEnji Cooper 128*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_ret_A); 129*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_ret_A, tc) 130*57718be8SEnji Cooper { 131*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 132*57718be8SEnji Cooper "that returns a content of the A register"); 133*57718be8SEnji Cooper } 134*57718be8SEnji Cooper 135*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_ret_A, tc) 136*57718be8SEnji Cooper { 137*57718be8SEnji Cooper static struct bpf_insn insns[] = { 138*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 139*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 0), // retA 140*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 141*57718be8SEnji Cooper }; 142*57718be8SEnji Cooper 143*57718be8SEnji Cooper bpfjit_func_t code; 144*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 145*57718be8SEnji Cooper bpf_args_t args = { 146*57718be8SEnji Cooper .pkt = pkt, 147*57718be8SEnji Cooper .buflen = sizeof(pkt), 148*57718be8SEnji Cooper .wirelen = sizeof(pkt), 149*57718be8SEnji Cooper }; 150*57718be8SEnji Cooper 151*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 152*57718be8SEnji Cooper 153*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 154*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 155*57718be8SEnji Cooper 156*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == 13); 157*57718be8SEnji Cooper 158*57718be8SEnji Cooper bpfjit_free_code(code); 159*57718be8SEnji Cooper } 160*57718be8SEnji Cooper 161*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_ret_buflen); 162*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_ret_buflen, tc) 163*57718be8SEnji Cooper { 164*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 165*57718be8SEnji Cooper "that returns the buflen argument"); 166*57718be8SEnji Cooper } 167*57718be8SEnji Cooper 168*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_ret_buflen, tc) 169*57718be8SEnji Cooper { 170*57718be8SEnji Cooper static struct bpf_insn insns[] = { 171*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 172*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 1), // retBL 173*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 174*57718be8SEnji Cooper }; 175*57718be8SEnji Cooper 176*57718be8SEnji Cooper bpfjit_func_t code; 177*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 178*57718be8SEnji Cooper bpf_args_t args = { 179*57718be8SEnji Cooper .pkt = pkt, 180*57718be8SEnji Cooper .buflen = sizeof(pkt), 181*57718be8SEnji Cooper .wirelen = sizeof(pkt) 182*57718be8SEnji Cooper }; 183*57718be8SEnji Cooper 184*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 185*57718be8SEnji Cooper 186*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 187*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 188*57718be8SEnji Cooper 189*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 190*57718be8SEnji Cooper 191*57718be8SEnji Cooper bpfjit_free_code(code); 192*57718be8SEnji Cooper } 193*57718be8SEnji Cooper 194*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_ret_wirelen); 195*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_ret_wirelen, tc) 196*57718be8SEnji Cooper { 197*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 198*57718be8SEnji Cooper "that returns the wirelen argument"); 199*57718be8SEnji Cooper } 200*57718be8SEnji Cooper 201*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_ret_wirelen, tc) 202*57718be8SEnji Cooper { 203*57718be8SEnji Cooper static struct bpf_insn insns[] = { 204*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 205*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 2), // retWL 206*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 207*57718be8SEnji Cooper }; 208*57718be8SEnji Cooper 209*57718be8SEnji Cooper bpfjit_func_t code; 210*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 211*57718be8SEnji Cooper bpf_args_t args = { 212*57718be8SEnji Cooper .pkt = pkt, 213*57718be8SEnji Cooper .buflen = sizeof(pkt), 214*57718be8SEnji Cooper .wirelen = sizeof(pkt) 215*57718be8SEnji Cooper }; 216*57718be8SEnji Cooper 217*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 218*57718be8SEnji Cooper 219*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 220*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 221*57718be8SEnji Cooper 222*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 223*57718be8SEnji Cooper 224*57718be8SEnji Cooper bpfjit_free_code(code); 225*57718be8SEnji Cooper } 226*57718be8SEnji Cooper 227*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_ret_nfuncs); 228*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_ret_nfuncs, tc) 229*57718be8SEnji Cooper { 230*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 231*57718be8SEnji Cooper "that returns nfuncs member of the context argument"); 232*57718be8SEnji Cooper } 233*57718be8SEnji Cooper 234*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_ret_nfuncs, tc) 235*57718be8SEnji Cooper { 236*57718be8SEnji Cooper static struct bpf_insn insns[] = { 237*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 238*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 3), // retNF 239*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 240*57718be8SEnji Cooper }; 241*57718be8SEnji Cooper 242*57718be8SEnji Cooper bpfjit_func_t code; 243*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 244*57718be8SEnji Cooper bpf_args_t args = { 245*57718be8SEnji Cooper .pkt = pkt, 246*57718be8SEnji Cooper .buflen = sizeof(pkt), 247*57718be8SEnji Cooper .wirelen = sizeof(pkt) 248*57718be8SEnji Cooper }; 249*57718be8SEnji Cooper 250*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 251*57718be8SEnji Cooper 252*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 253*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 254*57718be8SEnji Cooper 255*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == ctx.nfuncs); 256*57718be8SEnji Cooper 257*57718be8SEnji Cooper bpfjit_free_code(code); 258*57718be8SEnji Cooper } 259*57718be8SEnji Cooper 260*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_side_effect); 261*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_side_effect, tc) 262*57718be8SEnji Cooper { 263*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 264*57718be8SEnji Cooper "Test that ABC optimization doesn't skip BPF_COP call"); 265*57718be8SEnji Cooper } 266*57718be8SEnji Cooper 267*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_side_effect, tc) 268*57718be8SEnji Cooper { 269*57718be8SEnji Cooper static struct bpf_insn insns[] = { 270*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 271*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), 272*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 4), // setARG 273*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999), 274*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 275*57718be8SEnji Cooper }; 276*57718be8SEnji Cooper 277*57718be8SEnji Cooper bpfjit_func_t code; 278*57718be8SEnji Cooper bool arg = false; 279*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 280*57718be8SEnji Cooper bpf_args_t args = { 281*57718be8SEnji Cooper .pkt = pkt, 282*57718be8SEnji Cooper .buflen = sizeof(pkt), 283*57718be8SEnji Cooper .wirelen = sizeof(pkt), 284*57718be8SEnji Cooper .mem = NULL, 285*57718be8SEnji Cooper .arg = &arg 286*57718be8SEnji Cooper }; 287*57718be8SEnji Cooper 288*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 289*57718be8SEnji Cooper 290*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 291*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 292*57718be8SEnji Cooper 293*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == 0); 294*57718be8SEnji Cooper ATF_CHECK(arg == true); 295*57718be8SEnji Cooper 296*57718be8SEnji Cooper bpfjit_free_code(code); 297*57718be8SEnji Cooper } 298*57718be8SEnji Cooper 299*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_copx); 300*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_copx, tc) 301*57718be8SEnji Cooper { 302*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 303*57718be8SEnji Cooper "Test BPF_COP call followed by BPF_COPX call"); 304*57718be8SEnji Cooper } 305*57718be8SEnji Cooper 306*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_copx, tc) 307*57718be8SEnji Cooper { 308*57718be8SEnji Cooper static struct bpf_insn insns[] = { 309*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 1), /* A <- 1 */ 310*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 0), /* retA */ 311*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 312*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */ 313*57718be8SEnji Cooper BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 314*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 315*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retNF */ 316*57718be8SEnji Cooper BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 317*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 318*57718be8SEnji Cooper }; 319*57718be8SEnji Cooper 320*57718be8SEnji Cooper bpfjit_func_t code; 321*57718be8SEnji Cooper uint8_t pkt[1] = { 2 }; 322*57718be8SEnji Cooper bpf_args_t args = { 323*57718be8SEnji Cooper .pkt = pkt, 324*57718be8SEnji Cooper .buflen = sizeof(pkt), 325*57718be8SEnji Cooper .wirelen = sizeof(pkt), 326*57718be8SEnji Cooper }; 327*57718be8SEnji Cooper 328*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 329*57718be8SEnji Cooper 330*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 331*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 332*57718be8SEnji Cooper 333*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == 3 + ctx.nfuncs); 334*57718be8SEnji Cooper 335*57718be8SEnji Cooper bpfjit_free_code(code); 336*57718be8SEnji Cooper } 337*57718be8SEnji Cooper 338*57718be8SEnji Cooper ATF_TC(libbpfjit_cop_invalid_index); 339*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_cop_invalid_index, tc) 340*57718be8SEnji Cooper { 341*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 342*57718be8SEnji Cooper "Test that out-of-range coprocessor function fails validation"); 343*57718be8SEnji Cooper } 344*57718be8SEnji Cooper 345*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_cop_invalid_index, tc) 346*57718be8SEnji Cooper { 347*57718be8SEnji Cooper static struct bpf_insn insns[] = { 348*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 349*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 6), // invalid index 350*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_K, 27) 351*57718be8SEnji Cooper }; 352*57718be8SEnji Cooper 353*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 354*57718be8SEnji Cooper 355*57718be8SEnji Cooper ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL); 356*57718be8SEnji Cooper } 357*57718be8SEnji Cooper 358*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_no_ctx); 359*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_no_ctx, tc) 360*57718be8SEnji Cooper { 361*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COPX " 362*57718be8SEnji Cooper "instruction isn't valid without a context"); 363*57718be8SEnji Cooper } 364*57718be8SEnji Cooper 365*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_no_ctx, tc) 366*57718be8SEnji Cooper { 367*57718be8SEnji Cooper static struct bpf_insn insns[] = { 368*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 0), 369*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_K, 7) 370*57718be8SEnji Cooper }; 371*57718be8SEnji Cooper 372*57718be8SEnji Cooper bpfjit_func_t code; 373*57718be8SEnji Cooper 374*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 375*57718be8SEnji Cooper 376*57718be8SEnji Cooper ATF_CHECK(!bpf_validate(insns, insn_count)); 377*57718be8SEnji Cooper 378*57718be8SEnji Cooper code = bpfjit_generate_code(NULL, insns, insn_count); 379*57718be8SEnji Cooper ATF_CHECK(code == NULL); 380*57718be8SEnji Cooper } 381*57718be8SEnji Cooper 382*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_ret_A); 383*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_ret_A, tc) 384*57718be8SEnji Cooper { 385*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 386*57718be8SEnji Cooper "that returns a content of the A register"); 387*57718be8SEnji Cooper } 388*57718be8SEnji Cooper 389*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_ret_A, tc) 390*57718be8SEnji Cooper { 391*57718be8SEnji Cooper static struct bpf_insn insns[] = { 392*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 393*57718be8SEnji Cooper BPF_STMT(BPF_LDX+BPF_IMM, 0), // retA 394*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), 395*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 396*57718be8SEnji Cooper }; 397*57718be8SEnji Cooper 398*57718be8SEnji Cooper bpfjit_func_t code; 399*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 400*57718be8SEnji Cooper bpf_args_t args = { 401*57718be8SEnji Cooper .pkt = pkt, 402*57718be8SEnji Cooper .buflen = sizeof(pkt), 403*57718be8SEnji Cooper .wirelen = sizeof(pkt), 404*57718be8SEnji Cooper }; 405*57718be8SEnji Cooper 406*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 407*57718be8SEnji Cooper 408*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 409*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 410*57718be8SEnji Cooper 411*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == 13); 412*57718be8SEnji Cooper 413*57718be8SEnji Cooper bpfjit_free_code(code); 414*57718be8SEnji Cooper } 415*57718be8SEnji Cooper 416*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_ret_buflen); 417*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_ret_buflen, tc) 418*57718be8SEnji Cooper { 419*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 420*57718be8SEnji Cooper "that returns the buflen argument"); 421*57718be8SEnji Cooper } 422*57718be8SEnji Cooper 423*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_ret_buflen, tc) 424*57718be8SEnji Cooper { 425*57718be8SEnji Cooper static struct bpf_insn insns[] = { 426*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 427*57718be8SEnji Cooper BPF_STMT(BPF_LDX+BPF_IMM, 1), // retBL 428*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), 429*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 430*57718be8SEnji Cooper }; 431*57718be8SEnji Cooper 432*57718be8SEnji Cooper bpfjit_func_t code; 433*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 434*57718be8SEnji Cooper bpf_args_t args = { 435*57718be8SEnji Cooper .pkt = pkt, 436*57718be8SEnji Cooper .buflen = sizeof(pkt), 437*57718be8SEnji Cooper .wirelen = sizeof(pkt) 438*57718be8SEnji Cooper }; 439*57718be8SEnji Cooper 440*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 441*57718be8SEnji Cooper 442*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 443*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 444*57718be8SEnji Cooper 445*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 446*57718be8SEnji Cooper 447*57718be8SEnji Cooper bpfjit_free_code(code); 448*57718be8SEnji Cooper } 449*57718be8SEnji Cooper 450*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_ret_wirelen); 451*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_ret_wirelen, tc) 452*57718be8SEnji Cooper { 453*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 454*57718be8SEnji Cooper "that returns the wirelen argument"); 455*57718be8SEnji Cooper } 456*57718be8SEnji Cooper 457*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_ret_wirelen, tc) 458*57718be8SEnji Cooper { 459*57718be8SEnji Cooper static struct bpf_insn insns[] = { 460*57718be8SEnji Cooper BPF_STMT(BPF_LDX+BPF_IMM, 2), // retWL 461*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 462*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), 463*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 464*57718be8SEnji Cooper }; 465*57718be8SEnji Cooper 466*57718be8SEnji Cooper bpfjit_func_t code; 467*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 468*57718be8SEnji Cooper bpf_args_t args = { 469*57718be8SEnji Cooper .pkt = pkt, 470*57718be8SEnji Cooper .buflen = sizeof(pkt), 471*57718be8SEnji Cooper .wirelen = sizeof(pkt) 472*57718be8SEnji Cooper }; 473*57718be8SEnji Cooper 474*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 475*57718be8SEnji Cooper 476*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 477*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 478*57718be8SEnji Cooper 479*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == sizeof(pkt)); 480*57718be8SEnji Cooper 481*57718be8SEnji Cooper bpfjit_free_code(code); 482*57718be8SEnji Cooper } 483*57718be8SEnji Cooper 484*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_ret_nfuncs); 485*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_ret_nfuncs, tc) 486*57718be8SEnji Cooper { 487*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test coprocessor function " 488*57718be8SEnji Cooper "that returns nfuncs member of the context argument"); 489*57718be8SEnji Cooper } 490*57718be8SEnji Cooper 491*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_ret_nfuncs, tc) 492*57718be8SEnji Cooper { 493*57718be8SEnji Cooper static struct bpf_insn insns[] = { 494*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 495*57718be8SEnji Cooper BPF_STMT(BPF_LDX+BPF_IMM, 3), // retNF 496*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), 497*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 498*57718be8SEnji Cooper }; 499*57718be8SEnji Cooper 500*57718be8SEnji Cooper bpfjit_func_t code; 501*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 502*57718be8SEnji Cooper bpf_args_t args = { 503*57718be8SEnji Cooper .pkt = pkt, 504*57718be8SEnji Cooper .buflen = sizeof(pkt), 505*57718be8SEnji Cooper .wirelen = sizeof(pkt) 506*57718be8SEnji Cooper }; 507*57718be8SEnji Cooper 508*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 509*57718be8SEnji Cooper 510*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 511*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 512*57718be8SEnji Cooper 513*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == ctx.nfuncs); 514*57718be8SEnji Cooper 515*57718be8SEnji Cooper bpfjit_free_code(code); 516*57718be8SEnji Cooper } 517*57718be8SEnji Cooper 518*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_side_effect); 519*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_side_effect, tc) 520*57718be8SEnji Cooper { 521*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 522*57718be8SEnji Cooper "Test that ABC optimization doesn't skip BPF_COPX call"); 523*57718be8SEnji Cooper } 524*57718be8SEnji Cooper 525*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_side_effect, tc) 526*57718be8SEnji Cooper { 527*57718be8SEnji Cooper static struct bpf_insn insns[] = { 528*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_IMM, 13), 529*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), 530*57718be8SEnji Cooper BPF_STMT(BPF_LDX+BPF_IMM, 4), // setARG 531*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), 532*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999), 533*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 534*57718be8SEnji Cooper }; 535*57718be8SEnji Cooper 536*57718be8SEnji Cooper bpfjit_func_t code; 537*57718be8SEnji Cooper bool arg = false; 538*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 539*57718be8SEnji Cooper bpf_args_t args = { 540*57718be8SEnji Cooper .pkt = pkt, 541*57718be8SEnji Cooper .buflen = sizeof(pkt), 542*57718be8SEnji Cooper .wirelen = sizeof(pkt), 543*57718be8SEnji Cooper .mem = NULL, 544*57718be8SEnji Cooper .arg = &arg 545*57718be8SEnji Cooper }; 546*57718be8SEnji Cooper 547*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 548*57718be8SEnji Cooper 549*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 550*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 551*57718be8SEnji Cooper 552*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == 0); 553*57718be8SEnji Cooper ATF_CHECK(arg == true); 554*57718be8SEnji Cooper 555*57718be8SEnji Cooper bpfjit_free_code(code); 556*57718be8SEnji Cooper } 557*57718be8SEnji Cooper 558*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_cop); 559*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_cop, tc) 560*57718be8SEnji Cooper { 561*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 562*57718be8SEnji Cooper "Test BPF_COPX call followed by BPF_COP call"); 563*57718be8SEnji Cooper } 564*57718be8SEnji Cooper 565*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_cop, tc) 566*57718be8SEnji Cooper { 567*57718be8SEnji Cooper static struct bpf_insn insns[] = { 568*57718be8SEnji Cooper BPF_STMT(BPF_LDX+BPF_IMM, 2), /* X <- 2 */ 569*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), /* retWL */ 570*57718be8SEnji Cooper BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 571*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 572*57718be8SEnji Cooper BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A = P[0] */ 573*57718be8SEnji Cooper BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 574*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_TAX, 0), /* X <- A */ 575*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COP, 3), /* retNF */ 576*57718be8SEnji Cooper BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1), /* A = A + X */ 577*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_A, 0) 578*57718be8SEnji Cooper }; 579*57718be8SEnji Cooper 580*57718be8SEnji Cooper bpfjit_func_t code; 581*57718be8SEnji Cooper uint8_t pkt[1] = { 2 }; 582*57718be8SEnji Cooper bpf_args_t args = { 583*57718be8SEnji Cooper .pkt = pkt, 584*57718be8SEnji Cooper .buflen = sizeof(pkt), 585*57718be8SEnji Cooper .wirelen = sizeof(pkt), 586*57718be8SEnji Cooper }; 587*57718be8SEnji Cooper 588*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 589*57718be8SEnji Cooper 590*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 591*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 592*57718be8SEnji Cooper 593*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == 5 + ctx.nfuncs); 594*57718be8SEnji Cooper 595*57718be8SEnji Cooper bpfjit_free_code(code); 596*57718be8SEnji Cooper } 597*57718be8SEnji Cooper 598*57718be8SEnji Cooper ATF_TC(libbpfjit_copx_invalid_index); 599*57718be8SEnji Cooper ATF_TC_HEAD(libbpfjit_copx_invalid_index, tc) 600*57718be8SEnji Cooper { 601*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 602*57718be8SEnji Cooper "Test that out-of-range BPF_COPX call fails at runtime"); 603*57718be8SEnji Cooper } 604*57718be8SEnji Cooper 605*57718be8SEnji Cooper ATF_TC_BODY(libbpfjit_copx_invalid_index, tc) 606*57718be8SEnji Cooper { 607*57718be8SEnji Cooper static struct bpf_insn insns[] = { 608*57718be8SEnji Cooper BPF_STMT(BPF_LDX+BPF_IMM, 5), // invalid index 609*57718be8SEnji Cooper BPF_STMT(BPF_MISC+BPF_COPX, 0), 610*57718be8SEnji Cooper BPF_STMT(BPF_RET+BPF_K, 27) 611*57718be8SEnji Cooper }; 612*57718be8SEnji Cooper 613*57718be8SEnji Cooper bpfjit_func_t code; 614*57718be8SEnji Cooper uint8_t pkt[1] = { 0 }; 615*57718be8SEnji Cooper bpf_args_t args = { 616*57718be8SEnji Cooper .pkt = pkt, 617*57718be8SEnji Cooper .buflen = sizeof(pkt), 618*57718be8SEnji Cooper .wirelen = sizeof(pkt) 619*57718be8SEnji Cooper }; 620*57718be8SEnji Cooper 621*57718be8SEnji Cooper size_t insn_count = sizeof(insns) / sizeof(insns[0]); 622*57718be8SEnji Cooper 623*57718be8SEnji Cooper code = bpfjit_generate_code(&ctx, insns, insn_count); 624*57718be8SEnji Cooper ATF_REQUIRE(code != NULL); 625*57718be8SEnji Cooper 626*57718be8SEnji Cooper ATF_CHECK(code(&ctx, &args) == 0); 627*57718be8SEnji Cooper 628*57718be8SEnji Cooper bpfjit_free_code(code); 629*57718be8SEnji Cooper } 630*57718be8SEnji Cooper 631*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 632*57718be8SEnji Cooper { 633*57718be8SEnji Cooper 634*57718be8SEnji Cooper /* 635*57718be8SEnji Cooper * For every new test please also add a similar test 636*57718be8SEnji Cooper * to ../../net/bpfjit/t_cop.c 637*57718be8SEnji Cooper */ 638*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_no_ctx); 639*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_A); 640*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_buflen); 641*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_wirelen); 642*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_nfuncs); 643*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_side_effect); 644*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_copx); 645*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_cop_invalid_index); 646*57718be8SEnji Cooper 647*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_no_ctx); 648*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_A); 649*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_buflen); 650*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_wirelen); 651*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_nfuncs); 652*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_side_effect); 653*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_cop); 654*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, libbpfjit_copx_invalid_index); 655*57718be8SEnji Cooper 656*57718be8SEnji Cooper return atf_no_error(); 657*57718be8SEnji Cooper } 658