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