xref: /freebsd/contrib/netbsd-tests/net/bpfjit/t_cop.c (revision 1a36faad54665288ed4eb839d2a4699ae2ead45e)
1*63d1fd59SEnji Cooper /*	$NetBSD: t_cop.c,v 1.4 2017/01/13 21:30:42 christos Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 2014 Alexander Nasonov.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
857718be8SEnji Cooper  * modification, are permitted provided that the following conditions
957718be8SEnji Cooper  * are met:
1057718be8SEnji Cooper  *
1157718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1257718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1357718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1457718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in
1557718be8SEnji Cooper  *    the documentation and/or other materials provided with the
1657718be8SEnji Cooper  *    distribution.
1757718be8SEnji Cooper  *
1857718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1957718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2057718be8SEnji Cooper  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2157718be8SEnji Cooper  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
2257718be8SEnji Cooper  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2357718be8SEnji Cooper  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2457718be8SEnji Cooper  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2557718be8SEnji Cooper  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2657718be8SEnji Cooper  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2757718be8SEnji Cooper  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2857718be8SEnji Cooper  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2957718be8SEnji Cooper  * SUCH DAMAGE.
3057718be8SEnji Cooper  */
3157718be8SEnji Cooper 
3257718be8SEnji Cooper #include <sys/cdefs.h>
33*63d1fd59SEnji Cooper __RCSID("$NetBSD: t_cop.c,v 1.4 2017/01/13 21:30:42 christos Exp $");
3457718be8SEnji Cooper 
3557718be8SEnji Cooper #include <stdint.h>
3657718be8SEnji Cooper #include <string.h>
3757718be8SEnji Cooper 
3857718be8SEnji Cooper #define __BPF_PRIVATE
3957718be8SEnji Cooper #include <net/bpf.h>
4057718be8SEnji Cooper #include <net/bpfjit.h>
4157718be8SEnji Cooper 
4257718be8SEnji Cooper #include "../../net/bpf/h_bpf.h"
4357718be8SEnji Cooper 
4457718be8SEnji Cooper /* XXX: atf-c.h has collisions with mbuf */
4557718be8SEnji Cooper #undef m_type
4657718be8SEnji Cooper #undef m_data
4757718be8SEnji Cooper #include <atf-c.h>
4857718be8SEnji Cooper 
49*63d1fd59SEnji Cooper #include "h_macros.h"
5057718be8SEnji Cooper 
5157718be8SEnji Cooper static uint32_t retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
5257718be8SEnji Cooper static uint32_t retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
5357718be8SEnji Cooper static uint32_t retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
5457718be8SEnji Cooper static uint32_t retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
5557718be8SEnji Cooper static uint32_t setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
5657718be8SEnji Cooper 
5757718be8SEnji Cooper static const bpf_copfunc_t copfuncs[] = {
5857718be8SEnji Cooper 	&retA,
5957718be8SEnji Cooper 	&retBL,
6057718be8SEnji Cooper 	&retWL,
6157718be8SEnji Cooper 	&retNF,
6257718be8SEnji Cooper 	&setARG
6357718be8SEnji Cooper };
6457718be8SEnji Cooper 
6557718be8SEnji Cooper static const bpf_ctx_t ctx = {
6657718be8SEnji Cooper 	.copfuncs = copfuncs,
6757718be8SEnji Cooper 	.nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]),
6857718be8SEnji Cooper 	.extwords = 0
6957718be8SEnji Cooper };
7057718be8SEnji Cooper 
7157718be8SEnji Cooper static uint32_t
retA(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)7257718be8SEnji Cooper retA(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
7357718be8SEnji Cooper {
7457718be8SEnji Cooper 
7557718be8SEnji Cooper 	return A;
7657718be8SEnji Cooper }
7757718be8SEnji Cooper 
7857718be8SEnji Cooper static uint32_t
retBL(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)7957718be8SEnji Cooper retBL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
8057718be8SEnji Cooper {
8157718be8SEnji Cooper 
8257718be8SEnji Cooper 	return args->buflen;
8357718be8SEnji Cooper }
8457718be8SEnji Cooper 
8557718be8SEnji Cooper static uint32_t
retWL(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)8657718be8SEnji Cooper retWL(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
8757718be8SEnji Cooper {
8857718be8SEnji Cooper 
8957718be8SEnji Cooper 	return args->wirelen;
9057718be8SEnji Cooper }
9157718be8SEnji Cooper 
9257718be8SEnji Cooper static uint32_t
retNF(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)9357718be8SEnji Cooper retNF(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
9457718be8SEnji Cooper {
9557718be8SEnji Cooper 
9657718be8SEnji Cooper 	return bc->nfuncs;
9757718be8SEnji Cooper }
9857718be8SEnji Cooper 
9957718be8SEnji Cooper /*
10057718be8SEnji Cooper  * COP function with a side effect.
10157718be8SEnji Cooper  */
10257718be8SEnji Cooper static uint32_t
setARG(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)10357718be8SEnji Cooper setARG(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
10457718be8SEnji Cooper {
10557718be8SEnji Cooper 	bool *arg = (bool *)args->arg;
10657718be8SEnji Cooper 	bool old = *arg;
10757718be8SEnji Cooper 
10857718be8SEnji Cooper 	*arg = true;
10957718be8SEnji Cooper 	return old;
11057718be8SEnji Cooper }
11157718be8SEnji Cooper 
11257718be8SEnji Cooper ATF_TC(bpfjit_cop_no_ctx);
ATF_TC_HEAD(bpfjit_cop_no_ctx,tc)11357718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_no_ctx, tc)
11457718be8SEnji Cooper {
11557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COP "
11657718be8SEnji Cooper 	    "instruction isn't valid without a context");
11757718be8SEnji Cooper }
11857718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_no_ctx,tc)11957718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_no_ctx, tc)
12057718be8SEnji Cooper {
12157718be8SEnji Cooper 	static struct bpf_insn insns[] = {
12257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 0),
12357718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_K, 7)
12457718be8SEnji Cooper 	};
12557718be8SEnji Cooper 
12657718be8SEnji Cooper 	bpfjit_func_t code;
12757718be8SEnji Cooper 
12857718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
12957718be8SEnji Cooper 
13057718be8SEnji Cooper 	RZ(rump_init());
13157718be8SEnji Cooper 
13257718be8SEnji Cooper 	ATF_CHECK(!prog_validate(insns, insn_count));
13357718be8SEnji Cooper 
13457718be8SEnji Cooper 	rump_schedule();
13557718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
13657718be8SEnji Cooper 	rump_unschedule();
13757718be8SEnji Cooper 	ATF_CHECK(code == NULL);
13857718be8SEnji Cooper }
13957718be8SEnji Cooper 
14057718be8SEnji Cooper ATF_TC(bpfjit_cop_ret_A);
ATF_TC_HEAD(bpfjit_cop_ret_A,tc)14157718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_ret_A, tc)
14257718be8SEnji Cooper {
14357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
14457718be8SEnji Cooper 	    "that returns a content of the A register");
14557718be8SEnji Cooper }
14657718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_ret_A,tc)14757718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_ret_A, tc)
14857718be8SEnji Cooper {
14957718be8SEnji Cooper 	static struct bpf_insn insns[] = {
15057718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
15157718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 0), // retA
15257718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
15357718be8SEnji Cooper 	};
15457718be8SEnji Cooper 
15557718be8SEnji Cooper 	bpfjit_func_t code;
15657718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
15757718be8SEnji Cooper 	bpf_args_t args = {
15857718be8SEnji Cooper 		.pkt = pkt,
15957718be8SEnji Cooper 		.buflen = sizeof(pkt),
16057718be8SEnji Cooper 		.wirelen = sizeof(pkt),
16157718be8SEnji Cooper 	};
16257718be8SEnji Cooper 
16357718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
16457718be8SEnji Cooper 
16557718be8SEnji Cooper 	RZ(rump_init());
16657718be8SEnji Cooper 
16757718be8SEnji Cooper 	rump_schedule();
16857718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
16957718be8SEnji Cooper 	rump_unschedule();
17057718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
17157718be8SEnji Cooper 
17257718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == 13);
17357718be8SEnji Cooper 
17457718be8SEnji Cooper 	rump_schedule();
17557718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
17657718be8SEnji Cooper 	rump_unschedule();
17757718be8SEnji Cooper }
17857718be8SEnji Cooper 
17957718be8SEnji Cooper ATF_TC(bpfjit_cop_ret_buflen);
ATF_TC_HEAD(bpfjit_cop_ret_buflen,tc)18057718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_ret_buflen, tc)
18157718be8SEnji Cooper {
18257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
18357718be8SEnji Cooper 	    "that returns the buflen argument");
18457718be8SEnji Cooper }
18557718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_ret_buflen,tc)18657718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_ret_buflen, tc)
18757718be8SEnji Cooper {
18857718be8SEnji Cooper 	static struct bpf_insn insns[] = {
18957718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
19057718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 1), // retBL
19157718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
19257718be8SEnji Cooper 	};
19357718be8SEnji Cooper 
19457718be8SEnji Cooper 	bpfjit_func_t code;
19557718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
19657718be8SEnji Cooper 	bpf_args_t args = {
19757718be8SEnji Cooper 		.pkt = pkt,
19857718be8SEnji Cooper 		.buflen = sizeof(pkt),
19957718be8SEnji Cooper 		.wirelen = sizeof(pkt)
20057718be8SEnji Cooper 	};
20157718be8SEnji Cooper 
20257718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
20357718be8SEnji Cooper 
20457718be8SEnji Cooper 	RZ(rump_init());
20557718be8SEnji Cooper 
20657718be8SEnji Cooper 	rump_schedule();
20757718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
20857718be8SEnji Cooper 	rump_unschedule();
20957718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
21057718be8SEnji Cooper 
21157718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
21257718be8SEnji Cooper 
21357718be8SEnji Cooper 	rump_schedule();
21457718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
21557718be8SEnji Cooper 	rump_unschedule();
21657718be8SEnji Cooper }
21757718be8SEnji Cooper 
21857718be8SEnji Cooper ATF_TC(bpfjit_cop_ret_wirelen);
ATF_TC_HEAD(bpfjit_cop_ret_wirelen,tc)21957718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_ret_wirelen, tc)
22057718be8SEnji Cooper {
22157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
22257718be8SEnji Cooper 	    "that returns the wirelen argument");
22357718be8SEnji Cooper }
22457718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_ret_wirelen,tc)22557718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_ret_wirelen, tc)
22657718be8SEnji Cooper {
22757718be8SEnji Cooper 	static struct bpf_insn insns[] = {
22857718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
22957718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 2), // retWL
23057718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
23157718be8SEnji Cooper 	};
23257718be8SEnji Cooper 
23357718be8SEnji Cooper 	bpfjit_func_t code;
23457718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
23557718be8SEnji Cooper 	bpf_args_t args = {
23657718be8SEnji Cooper 		.pkt = pkt,
23757718be8SEnji Cooper 		.buflen = sizeof(pkt),
23857718be8SEnji Cooper 		.wirelen = sizeof(pkt)
23957718be8SEnji Cooper 	};
24057718be8SEnji Cooper 
24157718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
24257718be8SEnji Cooper 
24357718be8SEnji Cooper 	RZ(rump_init());
24457718be8SEnji Cooper 
24557718be8SEnji Cooper 	rump_schedule();
24657718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
24757718be8SEnji Cooper 	rump_unschedule();
24857718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
24957718be8SEnji Cooper 
25057718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
25157718be8SEnji Cooper 
25257718be8SEnji Cooper 	rump_schedule();
25357718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
25457718be8SEnji Cooper 	rump_unschedule();
25557718be8SEnji Cooper }
25657718be8SEnji Cooper 
25757718be8SEnji Cooper ATF_TC(bpfjit_cop_ret_nfuncs);
ATF_TC_HEAD(bpfjit_cop_ret_nfuncs,tc)25857718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_ret_nfuncs, tc)
25957718be8SEnji Cooper {
26057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
26157718be8SEnji Cooper 	    "that returns nfuncs member of the context argument");
26257718be8SEnji Cooper }
26357718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_ret_nfuncs,tc)26457718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_ret_nfuncs, tc)
26557718be8SEnji Cooper {
26657718be8SEnji Cooper 	static struct bpf_insn insns[] = {
26757718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
26857718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 3), // retNF
26957718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
27057718be8SEnji Cooper 	};
27157718be8SEnji Cooper 
27257718be8SEnji Cooper 	bpfjit_func_t code;
27357718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
27457718be8SEnji Cooper 	bpf_args_t args = {
27557718be8SEnji Cooper 		.pkt = pkt,
27657718be8SEnji Cooper 		.buflen = sizeof(pkt),
27757718be8SEnji Cooper 		.wirelen = sizeof(pkt)
27857718be8SEnji Cooper 	};
27957718be8SEnji Cooper 
28057718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
28157718be8SEnji Cooper 
28257718be8SEnji Cooper 	RZ(rump_init());
28357718be8SEnji Cooper 
28457718be8SEnji Cooper 	rump_schedule();
28557718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
28657718be8SEnji Cooper 	rump_unschedule();
28757718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
28857718be8SEnji Cooper 
28957718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
29057718be8SEnji Cooper 
29157718be8SEnji Cooper 	rump_schedule();
29257718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
29357718be8SEnji Cooper 	rump_unschedule();
29457718be8SEnji Cooper }
29557718be8SEnji Cooper 
29657718be8SEnji Cooper ATF_TC(bpfjit_cop_side_effect);
ATF_TC_HEAD(bpfjit_cop_side_effect,tc)29757718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_side_effect, tc)
29857718be8SEnji Cooper {
29957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
30057718be8SEnji Cooper 	    "Test that ABC optimization doesn't skip BPF_COP call");
30157718be8SEnji Cooper }
30257718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_side_effect,tc)30357718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_side_effect, tc)
30457718be8SEnji Cooper {
30557718be8SEnji Cooper 	static struct bpf_insn insns[] = {
30657718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
30757718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),
30857718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 4), // setARG
30957718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999),
31057718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
31157718be8SEnji Cooper 	};
31257718be8SEnji Cooper 
31357718be8SEnji Cooper 	bpfjit_func_t code;
31457718be8SEnji Cooper 	bool arg = false;
31557718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
31657718be8SEnji Cooper 	bpf_args_t args = {
31757718be8SEnji Cooper 		.pkt = pkt,
31857718be8SEnji Cooper 		.buflen = sizeof(pkt),
31957718be8SEnji Cooper 		.wirelen = sizeof(pkt),
32057718be8SEnji Cooper 		.mem = NULL,
32157718be8SEnji Cooper 		.arg = &arg
32257718be8SEnji Cooper 	};
32357718be8SEnji Cooper 
32457718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
32557718be8SEnji Cooper 
32657718be8SEnji Cooper 	RZ(rump_init());
32757718be8SEnji Cooper 
32857718be8SEnji Cooper 	rump_schedule();
32957718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
33057718be8SEnji Cooper 	rump_unschedule();
33157718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
33257718be8SEnji Cooper 
33357718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == 0);
33457718be8SEnji Cooper 	ATF_CHECK(arg == true);
33557718be8SEnji Cooper 
33657718be8SEnji Cooper 	rump_schedule();
33757718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
33857718be8SEnji Cooper 	rump_unschedule();
33957718be8SEnji Cooper }
34057718be8SEnji Cooper 
34157718be8SEnji Cooper ATF_TC(bpfjit_cop_copx);
ATF_TC_HEAD(bpfjit_cop_copx,tc)34257718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_copx, tc)
34357718be8SEnji Cooper {
34457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
34557718be8SEnji Cooper 	    "Test BPF_COP call followed by BPF_COPX call");
34657718be8SEnji Cooper }
34757718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_copx,tc)34857718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_copx, tc)
34957718be8SEnji Cooper {
35057718be8SEnji Cooper 	static struct bpf_insn insns[] = {
35157718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 1),         /* A <- 1    */
35257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 0),       /* retA      */
35357718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
35457718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),   /* A = P[0]  */
35557718be8SEnji Cooper 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
35657718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
35757718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),      /* retNF     */
35857718be8SEnji Cooper 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
35957718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
36057718be8SEnji Cooper 	};
36157718be8SEnji Cooper 
36257718be8SEnji Cooper 	bpfjit_func_t code;
36357718be8SEnji Cooper 	uint8_t pkt[1] = { 2 };
36457718be8SEnji Cooper 	bpf_args_t args = {
36557718be8SEnji Cooper 		.pkt = pkt,
36657718be8SEnji Cooper 		.buflen = sizeof(pkt),
36757718be8SEnji Cooper 		.wirelen = sizeof(pkt),
36857718be8SEnji Cooper 	};
36957718be8SEnji Cooper 
37057718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
37157718be8SEnji Cooper 
37257718be8SEnji Cooper 	RZ(rump_init());
37357718be8SEnji Cooper 
37457718be8SEnji Cooper 	rump_schedule();
37557718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
37657718be8SEnji Cooper 	rump_unschedule();
37757718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
37857718be8SEnji Cooper 
37957718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == 3 + ctx.nfuncs);
38057718be8SEnji Cooper 
38157718be8SEnji Cooper 	rump_schedule();
38257718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
38357718be8SEnji Cooper 	rump_unschedule();
38457718be8SEnji Cooper }
38557718be8SEnji Cooper 
38657718be8SEnji Cooper ATF_TC(bpfjit_cop_invalid_index);
ATF_TC_HEAD(bpfjit_cop_invalid_index,tc)38757718be8SEnji Cooper ATF_TC_HEAD(bpfjit_cop_invalid_index, tc)
38857718be8SEnji Cooper {
38957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
39057718be8SEnji Cooper 	    "Test that out-of-range coprocessor function fails validation");
39157718be8SEnji Cooper }
39257718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_cop_invalid_index,tc)39357718be8SEnji Cooper ATF_TC_BODY(bpfjit_cop_invalid_index, tc)
39457718be8SEnji Cooper {
39557718be8SEnji Cooper 	static struct bpf_insn insns[] = {
39657718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
39757718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 6), // invalid index
39857718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_K, 27)
39957718be8SEnji Cooper 	};
40057718be8SEnji Cooper 
40157718be8SEnji Cooper 	bpfjit_func_t code;
40257718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
40357718be8SEnji Cooper 
40457718be8SEnji Cooper 	RZ(rump_init());
40557718be8SEnji Cooper 
40657718be8SEnji Cooper 	rump_schedule();
40757718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
40857718be8SEnji Cooper 	rump_unschedule();
40957718be8SEnji Cooper 	ATF_CHECK(code == NULL);
41057718be8SEnji Cooper }
41157718be8SEnji Cooper 
41257718be8SEnji Cooper ATF_TC(bpfjit_copx_no_ctx);
ATF_TC_HEAD(bpfjit_copx_no_ctx,tc)41357718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_no_ctx, tc)
41457718be8SEnji Cooper {
41557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test that bpf program with BPF_COPX "
41657718be8SEnji Cooper 	    "instruction isn't valid without a context");
41757718be8SEnji Cooper }
41857718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_no_ctx,tc)41957718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_no_ctx, tc)
42057718be8SEnji Cooper {
42157718be8SEnji Cooper 	static struct bpf_insn insns[] = {
42257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 0),
42357718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_K, 7)
42457718be8SEnji Cooper 	};
42557718be8SEnji Cooper 
42657718be8SEnji Cooper 	bpfjit_func_t code;
42757718be8SEnji Cooper 
42857718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
42957718be8SEnji Cooper 
43057718be8SEnji Cooper 	RZ(rump_init());
43157718be8SEnji Cooper 
43257718be8SEnji Cooper 	ATF_CHECK(!prog_validate(insns, insn_count));
43357718be8SEnji Cooper 
43457718be8SEnji Cooper 	rump_schedule();
43557718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(NULL, insns, insn_count);
43657718be8SEnji Cooper 	rump_unschedule();
43757718be8SEnji Cooper 	ATF_CHECK(code == NULL);
43857718be8SEnji Cooper }
43957718be8SEnji Cooper 
44057718be8SEnji Cooper ATF_TC(bpfjit_copx_ret_A);
ATF_TC_HEAD(bpfjit_copx_ret_A,tc)44157718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_ret_A, tc)
44257718be8SEnji Cooper {
44357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
44457718be8SEnji Cooper 	    "that returns a content of the A register");
44557718be8SEnji Cooper }
44657718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_ret_A,tc)44757718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_ret_A, tc)
44857718be8SEnji Cooper {
44957718be8SEnji Cooper 	static struct bpf_insn insns[] = {
45057718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
45157718be8SEnji Cooper 		BPF_STMT(BPF_LDX+BPF_IMM, 0), // retA
45257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
45357718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
45457718be8SEnji Cooper 	};
45557718be8SEnji Cooper 
45657718be8SEnji Cooper 	bpfjit_func_t code;
45757718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
45857718be8SEnji Cooper 	bpf_args_t args = {
45957718be8SEnji Cooper 		.pkt = pkt,
46057718be8SEnji Cooper 		.buflen = sizeof(pkt),
46157718be8SEnji Cooper 		.wirelen = sizeof(pkt),
46257718be8SEnji Cooper 	};
46357718be8SEnji Cooper 
46457718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
46557718be8SEnji Cooper 
46657718be8SEnji Cooper 	RZ(rump_init());
46757718be8SEnji Cooper 
46857718be8SEnji Cooper 	rump_schedule();
46957718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
47057718be8SEnji Cooper 	rump_unschedule();
47157718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
47257718be8SEnji Cooper 
47357718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == 13);
47457718be8SEnji Cooper 
47557718be8SEnji Cooper 	rump_schedule();
47657718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
47757718be8SEnji Cooper 	rump_unschedule();
47857718be8SEnji Cooper }
47957718be8SEnji Cooper 
48057718be8SEnji Cooper ATF_TC(bpfjit_copx_ret_buflen);
ATF_TC_HEAD(bpfjit_copx_ret_buflen,tc)48157718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_ret_buflen, tc)
48257718be8SEnji Cooper {
48357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
48457718be8SEnji Cooper 	    "that returns the buflen argument");
48557718be8SEnji Cooper }
48657718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_ret_buflen,tc)48757718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_ret_buflen, tc)
48857718be8SEnji Cooper {
48957718be8SEnji Cooper 	static struct bpf_insn insns[] = {
49057718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
49157718be8SEnji Cooper 		BPF_STMT(BPF_LDX+BPF_IMM, 1), // retBL
49257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
49357718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
49457718be8SEnji Cooper 	};
49557718be8SEnji Cooper 
49657718be8SEnji Cooper 	bpfjit_func_t code;
49757718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
49857718be8SEnji Cooper 	bpf_args_t args = {
49957718be8SEnji Cooper 		.pkt = pkt,
50057718be8SEnji Cooper 		.buflen = sizeof(pkt),
50157718be8SEnji Cooper 		.wirelen = sizeof(pkt)
50257718be8SEnji Cooper 	};
50357718be8SEnji Cooper 
50457718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
50557718be8SEnji Cooper 
50657718be8SEnji Cooper 	RZ(rump_init());
50757718be8SEnji Cooper 
50857718be8SEnji Cooper 	rump_schedule();
50957718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
51057718be8SEnji Cooper 	rump_unschedule();
51157718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
51257718be8SEnji Cooper 
51357718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
51457718be8SEnji Cooper 
51557718be8SEnji Cooper 	rump_schedule();
51657718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
51757718be8SEnji Cooper 	rump_unschedule();
51857718be8SEnji Cooper }
51957718be8SEnji Cooper 
52057718be8SEnji Cooper ATF_TC(bpfjit_copx_ret_wirelen);
ATF_TC_HEAD(bpfjit_copx_ret_wirelen,tc)52157718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_ret_wirelen, tc)
52257718be8SEnji Cooper {
52357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
52457718be8SEnji Cooper 	    "that returns the wirelen argument");
52557718be8SEnji Cooper }
52657718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_ret_wirelen,tc)52757718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_ret_wirelen, tc)
52857718be8SEnji Cooper {
52957718be8SEnji Cooper 	static struct bpf_insn insns[] = {
53057718be8SEnji Cooper 		BPF_STMT(BPF_LDX+BPF_IMM, 2), // retWL
53157718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
53257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
53357718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
53457718be8SEnji Cooper 	};
53557718be8SEnji Cooper 
53657718be8SEnji Cooper 	bpfjit_func_t code;
53757718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
53857718be8SEnji Cooper 	bpf_args_t args = {
53957718be8SEnji Cooper 		.pkt = pkt,
54057718be8SEnji Cooper 		.buflen = sizeof(pkt),
54157718be8SEnji Cooper 		.wirelen = sizeof(pkt)
54257718be8SEnji Cooper 	};
54357718be8SEnji Cooper 
54457718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
54557718be8SEnji Cooper 
54657718be8SEnji Cooper 	RZ(rump_init());
54757718be8SEnji Cooper 
54857718be8SEnji Cooper 	rump_schedule();
54957718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
55057718be8SEnji Cooper 	rump_unschedule();
55157718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
55257718be8SEnji Cooper 
55357718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == sizeof(pkt));
55457718be8SEnji Cooper 
55557718be8SEnji Cooper 	rump_schedule();
55657718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
55757718be8SEnji Cooper 	rump_unschedule();
55857718be8SEnji Cooper }
55957718be8SEnji Cooper 
56057718be8SEnji Cooper ATF_TC(bpfjit_copx_ret_nfuncs);
ATF_TC_HEAD(bpfjit_copx_ret_nfuncs,tc)56157718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_ret_nfuncs, tc)
56257718be8SEnji Cooper {
56357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
56457718be8SEnji Cooper 	    "that returns nfuncs member of the context argument");
56557718be8SEnji Cooper }
56657718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_ret_nfuncs,tc)56757718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_ret_nfuncs, tc)
56857718be8SEnji Cooper {
56957718be8SEnji Cooper 	static struct bpf_insn insns[] = {
57057718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
57157718be8SEnji Cooper 		BPF_STMT(BPF_LDX+BPF_IMM, 3), // retNF
57257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
57357718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
57457718be8SEnji Cooper 	};
57557718be8SEnji Cooper 
57657718be8SEnji Cooper 	bpfjit_func_t code;
57757718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
57857718be8SEnji Cooper 	bpf_args_t args = {
57957718be8SEnji Cooper 		.pkt = pkt,
58057718be8SEnji Cooper 		.buflen = sizeof(pkt),
58157718be8SEnji Cooper 		.wirelen = sizeof(pkt)
58257718be8SEnji Cooper 	};
58357718be8SEnji Cooper 
58457718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
58557718be8SEnji Cooper 
58657718be8SEnji Cooper 	RZ(rump_init());
58757718be8SEnji Cooper 
58857718be8SEnji Cooper 	rump_schedule();
58957718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
59057718be8SEnji Cooper 	rump_unschedule();
59157718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
59257718be8SEnji Cooper 
59357718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == ctx.nfuncs);
59457718be8SEnji Cooper 
59557718be8SEnji Cooper 	rump_schedule();
59657718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
59757718be8SEnji Cooper 	rump_unschedule();
59857718be8SEnji Cooper }
59957718be8SEnji Cooper 
60057718be8SEnji Cooper ATF_TC(bpfjit_copx_side_effect);
ATF_TC_HEAD(bpfjit_copx_side_effect,tc)60157718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_side_effect, tc)
60257718be8SEnji Cooper {
60357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
60457718be8SEnji Cooper 	    "Test that ABC optimization doesn't skip BPF_COPX call");
60557718be8SEnji Cooper }
60657718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_side_effect,tc)60757718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_side_effect, tc)
60857718be8SEnji Cooper {
60957718be8SEnji Cooper 	static struct bpf_insn insns[] = {
61057718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_IMM, 13),
61157718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),
61257718be8SEnji Cooper 		BPF_STMT(BPF_LDX+BPF_IMM, 4), // setARG
61357718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
61457718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99999),
61557718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
61657718be8SEnji Cooper 	};
61757718be8SEnji Cooper 
61857718be8SEnji Cooper 	bpfjit_func_t code;
61957718be8SEnji Cooper 	bool arg = false;
62057718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
62157718be8SEnji Cooper 	bpf_args_t args = {
62257718be8SEnji Cooper 		.pkt = pkt,
62357718be8SEnji Cooper 		.buflen = sizeof(pkt),
62457718be8SEnji Cooper 		.wirelen = sizeof(pkt),
62557718be8SEnji Cooper 		.mem = NULL,
62657718be8SEnji Cooper 		.arg = &arg
62757718be8SEnji Cooper 	};
62857718be8SEnji Cooper 
62957718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
63057718be8SEnji Cooper 
63157718be8SEnji Cooper 	RZ(rump_init());
63257718be8SEnji Cooper 
63357718be8SEnji Cooper 	rump_schedule();
63457718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
63557718be8SEnji Cooper 	rump_unschedule();
63657718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
63757718be8SEnji Cooper 
63857718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == 0);
63957718be8SEnji Cooper 	ATF_CHECK(arg == true);
64057718be8SEnji Cooper 
64157718be8SEnji Cooper 	rump_schedule();
64257718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
64357718be8SEnji Cooper 	rump_unschedule();
64457718be8SEnji Cooper }
64557718be8SEnji Cooper 
64657718be8SEnji Cooper ATF_TC(bpfjit_copx_cop);
ATF_TC_HEAD(bpfjit_copx_cop,tc)64757718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_cop, tc)
64857718be8SEnji Cooper {
64957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
65057718be8SEnji Cooper 	    "Test BPF_COPX call followed by BPF_COP call");
65157718be8SEnji Cooper }
65257718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_cop,tc)65357718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_cop, tc)
65457718be8SEnji Cooper {
65557718be8SEnji Cooper 	static struct bpf_insn insns[] = {
65657718be8SEnji Cooper 		BPF_STMT(BPF_LDX+BPF_IMM, 2),        /* X <- 2    */
65757718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),      /* retWL     */
65857718be8SEnji Cooper 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
65957718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
66057718be8SEnji Cooper 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),   /* A = P[0]  */
66157718be8SEnji Cooper 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
66257718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_TAX, 0),       /* X <- A    */
66357718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COP, 3),      /* retNF     */
66457718be8SEnji Cooper 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 1),  /* A = A + X */
66557718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_A, 0)
66657718be8SEnji Cooper 	};
66757718be8SEnji Cooper 
66857718be8SEnji Cooper 	bpfjit_func_t code;
66957718be8SEnji Cooper 	uint8_t pkt[1] = { 2 };
67057718be8SEnji Cooper 	bpf_args_t args = {
67157718be8SEnji Cooper 		.pkt = pkt,
67257718be8SEnji Cooper 		.buflen = sizeof(pkt),
67357718be8SEnji Cooper 		.wirelen = sizeof(pkt),
67457718be8SEnji Cooper 	};
67557718be8SEnji Cooper 
67657718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
67757718be8SEnji Cooper 
67857718be8SEnji Cooper 	RZ(rump_init());
67957718be8SEnji Cooper 
68057718be8SEnji Cooper 	rump_schedule();
68157718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
68257718be8SEnji Cooper 	rump_unschedule();
68357718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
68457718be8SEnji Cooper 
68557718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == 5 + ctx.nfuncs);
68657718be8SEnji Cooper 
68757718be8SEnji Cooper 	rump_schedule();
68857718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
68957718be8SEnji Cooper 	rump_unschedule();
69057718be8SEnji Cooper }
69157718be8SEnji Cooper 
69257718be8SEnji Cooper ATF_TC(bpfjit_copx_invalid_index);
ATF_TC_HEAD(bpfjit_copx_invalid_index,tc)69357718be8SEnji Cooper ATF_TC_HEAD(bpfjit_copx_invalid_index, tc)
69457718be8SEnji Cooper {
69557718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr",
69657718be8SEnji Cooper 	    "Test that out-of-range BPF_COPX call fails at runtime");
69757718be8SEnji Cooper }
69857718be8SEnji Cooper 
ATF_TC_BODY(bpfjit_copx_invalid_index,tc)69957718be8SEnji Cooper ATF_TC_BODY(bpfjit_copx_invalid_index, tc)
70057718be8SEnji Cooper {
70157718be8SEnji Cooper 	static struct bpf_insn insns[] = {
70257718be8SEnji Cooper 		BPF_STMT(BPF_LDX+BPF_IMM, 5), // invalid index
70357718be8SEnji Cooper 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
70457718be8SEnji Cooper 		BPF_STMT(BPF_RET+BPF_K, 27)
70557718be8SEnji Cooper 	};
70657718be8SEnji Cooper 
70757718be8SEnji Cooper 	bpfjit_func_t code;
70857718be8SEnji Cooper 	uint8_t pkt[1] = { 0 };
70957718be8SEnji Cooper 	bpf_args_t args = {
71057718be8SEnji Cooper 		.pkt = pkt,
71157718be8SEnji Cooper 		.buflen = sizeof(pkt),
71257718be8SEnji Cooper 		.wirelen = sizeof(pkt)
71357718be8SEnji Cooper 	};
71457718be8SEnji Cooper 
71557718be8SEnji Cooper 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
71657718be8SEnji Cooper 
71757718be8SEnji Cooper 	RZ(rump_init());
71857718be8SEnji Cooper 
71957718be8SEnji Cooper 	rump_schedule();
72057718be8SEnji Cooper 	code = rumpns_bpfjit_generate_code(&ctx, insns, insn_count);
72157718be8SEnji Cooper 	rump_unschedule();
72257718be8SEnji Cooper 	ATF_REQUIRE(code != NULL);
72357718be8SEnji Cooper 
72457718be8SEnji Cooper 	ATF_CHECK(code(&ctx, &args) == 0);
72557718be8SEnji Cooper 
72657718be8SEnji Cooper 	rump_schedule();
72757718be8SEnji Cooper 	rumpns_bpfjit_free_code(code);
72857718be8SEnji Cooper 	rump_unschedule();
72957718be8SEnji Cooper }
73057718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)73157718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
73257718be8SEnji Cooper {
73357718be8SEnji Cooper 
73457718be8SEnji Cooper 	/*
73557718be8SEnji Cooper 	 * For every new test please also add a similar test
73657718be8SEnji Cooper 	 * to ../../lib/libbpfjit/t_cop.c
73757718be8SEnji Cooper 	 */
73857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_no_ctx);
73957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_ret_A);
74057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_ret_buflen);
74157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_ret_wirelen);
74257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_ret_nfuncs);
74357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_side_effect);
74457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_copx);
74557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_cop_invalid_index);
74657718be8SEnji Cooper 
74757718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_no_ctx);
74857718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_ret_A);
74957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_ret_buflen);
75057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_ret_wirelen);
75157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_ret_nfuncs);
75257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_side_effect);
75357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_cop);
75457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, bpfjit_copx_invalid_index);
75557718be8SEnji Cooper 
75657718be8SEnji Cooper 	return atf_no_error();
75757718be8SEnji Cooper }
758