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