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