xref: /netbsd-src/tests/lib/libbpfjit/t_extmem.c (revision 5977f956e58a7fe1da0f9309f50b844bac3f64af)
1*5977f956Salnsn /*	$NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn Exp $ */
2966c8b06Salnsn 
3966c8b06Salnsn /*-
4966c8b06Salnsn  * Copyright (c) 2014 Alexander Nasonov.
5966c8b06Salnsn  * All rights reserved.
6966c8b06Salnsn  *
7966c8b06Salnsn  * Redistribution and use in source and binary forms, with or without
8966c8b06Salnsn  * modification, are permitted provided that the following conditions
9966c8b06Salnsn  * are met:
10966c8b06Salnsn  *
11966c8b06Salnsn  * 1. Redistributions of source code must retain the above copyright
12966c8b06Salnsn  *    notice, this list of conditions and the following disclaimer.
13966c8b06Salnsn  * 2. Redistributions in binary form must reproduce the above copyright
14966c8b06Salnsn  *    notice, this list of conditions and the following disclaimer in
15966c8b06Salnsn  *    the documentation and/or other materials provided with the
16966c8b06Salnsn  *    distribution.
17966c8b06Salnsn  *
18966c8b06Salnsn  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19966c8b06Salnsn  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20966c8b06Salnsn  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21966c8b06Salnsn  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22966c8b06Salnsn  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23966c8b06Salnsn  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24966c8b06Salnsn  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25966c8b06Salnsn  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26966c8b06Salnsn  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27966c8b06Salnsn  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28966c8b06Salnsn  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29966c8b06Salnsn  * SUCH DAMAGE.
30966c8b06Salnsn  */
31966c8b06Salnsn 
32966c8b06Salnsn #include <sys/cdefs.h>
33*5977f956Salnsn __RCSID("$NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn Exp $");
34966c8b06Salnsn 
35966c8b06Salnsn #include <atf-c.h>
36966c8b06Salnsn #include <stdint.h>
37966c8b06Salnsn #include <string.h>
38966c8b06Salnsn 
39966c8b06Salnsn #define __BPF_PRIVATE
40966c8b06Salnsn #include <net/bpf.h>
41966c8b06Salnsn #include <net/bpfjit.h>
42966c8b06Salnsn 
43966c8b06Salnsn static uint32_t retM(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
44966c8b06Salnsn 
45966c8b06Salnsn static const bpf_copfunc_t copfuncs[] = {
46966c8b06Salnsn 	&retM
47966c8b06Salnsn };
48966c8b06Salnsn 
49966c8b06Salnsn static const bpf_ctx_t ctx = {
50966c8b06Salnsn 	.copfuncs = copfuncs,
51966c8b06Salnsn 	.nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]),
52966c8b06Salnsn 	.extwords = 4,
53966c8b06Salnsn 	.preinited = BPF_MEMWORD_INIT(0) | BPF_MEMWORD_INIT(3),
54966c8b06Salnsn };
55966c8b06Salnsn 
56966c8b06Salnsn static uint32_t
retM(const bpf_ctx_t * bc,bpf_args_t * args,uint32_t A)57966c8b06Salnsn retM(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
58966c8b06Salnsn {
59966c8b06Salnsn 
60966c8b06Salnsn 	return args->mem[(uintptr_t)args->arg];
61966c8b06Salnsn }
62966c8b06Salnsn 
63966c8b06Salnsn 
64f5874843Salnsn ATF_TC(libbpfjit_extmem_load_default);
ATF_TC_HEAD(libbpfjit_extmem_load_default,tc)65f5874843Salnsn ATF_TC_HEAD(libbpfjit_extmem_load_default, tc)
66966c8b06Salnsn {
67966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test that external memory "
68966c8b06Salnsn 	    "is zero initialized by default");
69966c8b06Salnsn }
70966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_extmem_load_default,tc)71f5874843Salnsn ATF_TC_BODY(libbpfjit_extmem_load_default, tc)
72966c8b06Salnsn {
73966c8b06Salnsn 	static struct bpf_insn insns[] = {
74966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_MEM, 1),
75966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
76966c8b06Salnsn 	};
77966c8b06Salnsn 
78966c8b06Salnsn 	bpfjit_func_t code;
79966c8b06Salnsn 	uint8_t pkt[1] = { 0 };
80966c8b06Salnsn 	uint32_t mem[ctx.extwords];
81966c8b06Salnsn 
82966c8b06Salnsn 	/* Pre-inited words. */
83966c8b06Salnsn 	mem[0] = 0;
84966c8b06Salnsn 	mem[3] = 3;
85966c8b06Salnsn 
86966c8b06Salnsn 	bpf_args_t args = {
87966c8b06Salnsn 		.pkt = pkt,
88966c8b06Salnsn 		.buflen = sizeof(pkt),
89966c8b06Salnsn 		.wirelen = sizeof(pkt),
90966c8b06Salnsn 		.mem = mem,
91966c8b06Salnsn 	};
92966c8b06Salnsn 
93966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
94966c8b06Salnsn 
95966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
96966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
97966c8b06Salnsn 
98966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 0);
99966c8b06Salnsn 
100966c8b06Salnsn 	bpfjit_free_code(code);
101966c8b06Salnsn }
102966c8b06Salnsn 
103f5874843Salnsn ATF_TC(libbpfjit_extmem_load_preinited);
ATF_TC_HEAD(libbpfjit_extmem_load_preinited,tc)104f5874843Salnsn ATF_TC_HEAD(libbpfjit_extmem_load_preinited, tc)
105966c8b06Salnsn {
106966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test a load of external "
107966c8b06Salnsn 	    "pre-initialized memory");
108966c8b06Salnsn }
109966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_extmem_load_preinited,tc)110f5874843Salnsn ATF_TC_BODY(libbpfjit_extmem_load_preinited, tc)
111966c8b06Salnsn {
112966c8b06Salnsn 	static struct bpf_insn insns[] = {
113966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_MEM, 3),
114966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
115966c8b06Salnsn 	};
116966c8b06Salnsn 
117966c8b06Salnsn 	bpfjit_func_t code;
118966c8b06Salnsn 	uint8_t pkt[1] = { 0 };
119966c8b06Salnsn 	uint32_t mem[ctx.extwords];
120966c8b06Salnsn 
121966c8b06Salnsn 	/* Pre-inited words. */
122966c8b06Salnsn 	mem[0] = 0;
123966c8b06Salnsn 	mem[3] = 3;
124966c8b06Salnsn 
125966c8b06Salnsn 	bpf_args_t args = {
126966c8b06Salnsn 		.pkt = pkt,
127966c8b06Salnsn 		.buflen = sizeof(pkt),
128966c8b06Salnsn 		.wirelen = sizeof(pkt),
129966c8b06Salnsn 		.mem = mem,
130966c8b06Salnsn 	};
131966c8b06Salnsn 
132966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
133966c8b06Salnsn 
134966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
135966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
136966c8b06Salnsn 
137966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 3);
138966c8b06Salnsn 
139966c8b06Salnsn 	bpfjit_free_code(code);
140966c8b06Salnsn }
141966c8b06Salnsn 
142f5874843Salnsn ATF_TC(libbpfjit_extmem_invalid_load);
ATF_TC_HEAD(libbpfjit_extmem_invalid_load,tc)143f5874843Salnsn ATF_TC_HEAD(libbpfjit_extmem_invalid_load, tc)
144966c8b06Salnsn {
145966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test that out-of-range load "
146966c8b06Salnsn 	    "fails validation");
147966c8b06Salnsn }
148966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_extmem_invalid_load,tc)149f5874843Salnsn ATF_TC_BODY(libbpfjit_extmem_invalid_load, tc)
150966c8b06Salnsn {
151966c8b06Salnsn 	static struct bpf_insn insns[] = {
152966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_MEM, 4),
153966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
154966c8b06Salnsn 	};
155966c8b06Salnsn 
156966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
157966c8b06Salnsn 
158966c8b06Salnsn 	ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL);
159966c8b06Salnsn }
160966c8b06Salnsn 
161f5874843Salnsn ATF_TC(libbpfjit_extmem_store);
ATF_TC_HEAD(libbpfjit_extmem_store,tc)162f5874843Salnsn ATF_TC_HEAD(libbpfjit_extmem_store, tc)
163966c8b06Salnsn {
164966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test stores to external memory");
165966c8b06Salnsn }
166966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_extmem_store,tc)167f5874843Salnsn ATF_TC_BODY(libbpfjit_extmem_store, tc)
168966c8b06Salnsn {
169966c8b06Salnsn 	static struct bpf_insn insns[] = {
170966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 1),        /* A <- 1     */
171966c8b06Salnsn 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2), /* X <- 2     */
172966c8b06Salnsn 		BPF_STMT(BPF_ST, 1),                /* M[1] <- A  */
173966c8b06Salnsn 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0), /* A <- A + X */
174966c8b06Salnsn 		BPF_STMT(BPF_STX, 2),               /* M[2] <- X  */
175966c8b06Salnsn 		BPF_STMT(BPF_ST, 3),                /* M[3] <- A  */
176966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)          /* ret A      */
177966c8b06Salnsn 	};
178966c8b06Salnsn 
179966c8b06Salnsn 	bpfjit_func_t code;
180966c8b06Salnsn 	uint8_t pkt[1] = { 0 };
181966c8b06Salnsn 	uint32_t mem[ctx.extwords];
182966c8b06Salnsn 
183966c8b06Salnsn 	/* Pre-inited words. */
184966c8b06Salnsn 	mem[0] = 0;
185966c8b06Salnsn 	mem[3] = 7;
186966c8b06Salnsn 
187966c8b06Salnsn 	mem[1] = mem[2] = 0xdeadbeef;
188966c8b06Salnsn 
189966c8b06Salnsn 	bpf_args_t args = {
190966c8b06Salnsn 		.pkt = pkt,
191966c8b06Salnsn 		.buflen = sizeof(pkt),
192966c8b06Salnsn 		.wirelen = sizeof(pkt),
193966c8b06Salnsn 		.mem = mem,
194966c8b06Salnsn 	};
195966c8b06Salnsn 
196966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
197966c8b06Salnsn 
198966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
199966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
200966c8b06Salnsn 
201966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 3);
202966c8b06Salnsn 
203966c8b06Salnsn 	bpfjit_free_code(code);
204966c8b06Salnsn 
205966c8b06Salnsn 	ATF_CHECK(mem[0] == 0);
206966c8b06Salnsn 	ATF_CHECK(mem[1] == 1);
207966c8b06Salnsn 	ATF_CHECK(mem[2] == 2);
208966c8b06Salnsn 	ATF_CHECK(mem[3] == 3);
209966c8b06Salnsn }
210966c8b06Salnsn 
211f5874843Salnsn ATF_TC(libbpfjit_extmem_side_effect);
ATF_TC_HEAD(libbpfjit_extmem_side_effect,tc)212f5874843Salnsn ATF_TC_HEAD(libbpfjit_extmem_side_effect, tc)
213966c8b06Salnsn {
214966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test that ABC optimization doesn\'t "
215966c8b06Salnsn 	    "skip stores to external memory");
216966c8b06Salnsn }
217966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_extmem_side_effect,tc)218f5874843Salnsn ATF_TC_BODY(libbpfjit_extmem_side_effect, tc)
219966c8b06Salnsn {
220966c8b06Salnsn 	static struct bpf_insn insns[] = {
221966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0),  /* A <- P[0]  */
222966c8b06Salnsn 		BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2), /* X <- 2     */
223966c8b06Salnsn 		BPF_STMT(BPF_ST, 1),                /* M[1] <- A  */
224966c8b06Salnsn 		BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0), /* A <- A + X */
225966c8b06Salnsn 		BPF_STMT(BPF_STX, 2),               /* M[2] <- X  */
226966c8b06Salnsn 		BPF_STMT(BPF_ST, 3),                /* M[3] <- A  */
227966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99), /* A <- P[99] */
228966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)          /* ret A      */
229966c8b06Salnsn 	};
230966c8b06Salnsn 
231966c8b06Salnsn 	bpfjit_func_t code;
232966c8b06Salnsn 	uint8_t pkt[1] = { 1 };
233966c8b06Salnsn 	uint32_t mem[ctx.extwords];
234966c8b06Salnsn 
235966c8b06Salnsn 	/* Pre-inited words. */
236966c8b06Salnsn 	mem[0] = 0;
237966c8b06Salnsn 	mem[3] = 7;
238966c8b06Salnsn 
239966c8b06Salnsn 	mem[1] = mem[2] = 0xdeadbeef;
240966c8b06Salnsn 
241966c8b06Salnsn 	bpf_args_t args = {
242966c8b06Salnsn 		.pkt = pkt,
243966c8b06Salnsn 		.buflen = sizeof(pkt),
244966c8b06Salnsn 		.wirelen = sizeof(pkt),
245966c8b06Salnsn 		.mem = mem,
246966c8b06Salnsn 	};
247966c8b06Salnsn 
248966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
249966c8b06Salnsn 
250966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
251966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
252966c8b06Salnsn 
253966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 0);
254966c8b06Salnsn 
255966c8b06Salnsn 	bpfjit_free_code(code);
256966c8b06Salnsn 
257966c8b06Salnsn 	ATF_CHECK(mem[0] == 0);
258966c8b06Salnsn 	ATF_CHECK(mem[1] == 1);
259966c8b06Salnsn 	ATF_CHECK(mem[2] == 2);
260966c8b06Salnsn 	ATF_CHECK(mem[3] == 3);
261966c8b06Salnsn }
262966c8b06Salnsn 
263f5874843Salnsn ATF_TC(libbpfjit_extmem_invalid_store);
ATF_TC_HEAD(libbpfjit_extmem_invalid_store,tc)264f5874843Salnsn ATF_TC_HEAD(libbpfjit_extmem_invalid_store, tc)
265966c8b06Salnsn {
266966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test that out-of-range store "
267966c8b06Salnsn 	    "fails validation");
268966c8b06Salnsn }
269966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_extmem_invalid_store,tc)270f5874843Salnsn ATF_TC_BODY(libbpfjit_extmem_invalid_store, tc)
271966c8b06Salnsn {
272966c8b06Salnsn 	static struct bpf_insn insns[] = {
273966c8b06Salnsn 		BPF_STMT(BPF_ST, 4),
274966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
275966c8b06Salnsn 	};
276966c8b06Salnsn 
277966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
278966c8b06Salnsn 
279966c8b06Salnsn 	ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL);
280966c8b06Salnsn }
281966c8b06Salnsn 
282f5874843Salnsn ATF_TC(libbpfjit_cop_ret_mem);
ATF_TC_HEAD(libbpfjit_cop_ret_mem,tc)283f5874843Salnsn ATF_TC_HEAD(libbpfjit_cop_ret_mem, tc)
284966c8b06Salnsn {
285966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
286966c8b06Salnsn 	    "that returns a content of external memory word");
287966c8b06Salnsn }
288966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_cop_ret_mem,tc)289f5874843Salnsn ATF_TC_BODY(libbpfjit_cop_ret_mem, tc)
290966c8b06Salnsn {
291966c8b06Salnsn 	static struct bpf_insn insns[] = {
292966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 13),
293966c8b06Salnsn 		BPF_STMT(BPF_ST, 2),
294966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 137),
295966c8b06Salnsn 		BPF_STMT(BPF_ST, 1),
296966c8b06Salnsn 		BPF_STMT(BPF_MISC+BPF_COP, 0), // retM
297966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
298966c8b06Salnsn 	};
299966c8b06Salnsn 
300966c8b06Salnsn 	bpfjit_func_t code;
301966c8b06Salnsn 	uint8_t pkt[1] = { 0 };
302966c8b06Salnsn 	uint32_t mem[ctx.extwords];
303966c8b06Salnsn 	void *arg = (void*)(uintptr_t)2;
304966c8b06Salnsn 
305966c8b06Salnsn 	/* Pre-inited words. */
306966c8b06Salnsn 	mem[0] = 0;
307966c8b06Salnsn 	mem[3] = 3;
308966c8b06Salnsn 
309966c8b06Salnsn 	bpf_args_t args = {
310966c8b06Salnsn 		.pkt = pkt,
311966c8b06Salnsn 		.buflen = sizeof(pkt),
312966c8b06Salnsn 		.wirelen = sizeof(pkt),
313966c8b06Salnsn 		.arg = arg,
314966c8b06Salnsn 		.mem = mem,
315966c8b06Salnsn 	};
316966c8b06Salnsn 
317966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
318966c8b06Salnsn 
319966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
320966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
321966c8b06Salnsn 
322966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 13);
323966c8b06Salnsn 
324966c8b06Salnsn 	bpfjit_free_code(code);
325966c8b06Salnsn }
326966c8b06Salnsn 
327f5874843Salnsn ATF_TC(libbpfjit_cop_ret_preinited_mem);
ATF_TC_HEAD(libbpfjit_cop_ret_preinited_mem,tc)328f5874843Salnsn ATF_TC_HEAD(libbpfjit_cop_ret_preinited_mem, tc)
329966c8b06Salnsn {
330966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function that "
331966c8b06Salnsn 	    "returns a content of external pre-initialized memory word");
332966c8b06Salnsn }
333966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_cop_ret_preinited_mem,tc)334f5874843Salnsn ATF_TC_BODY(libbpfjit_cop_ret_preinited_mem, tc)
335966c8b06Salnsn {
336966c8b06Salnsn 	static struct bpf_insn insns[] = {
337966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 13),
338966c8b06Salnsn 		BPF_STMT(BPF_ST, 2),
339966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 137),
340966c8b06Salnsn 		BPF_STMT(BPF_ST, 1),
341966c8b06Salnsn 		BPF_STMT(BPF_MISC+BPF_COP, 0), // retM
342966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
343966c8b06Salnsn 	};
344966c8b06Salnsn 
345966c8b06Salnsn 	bpfjit_func_t code;
346966c8b06Salnsn 	uint8_t pkt[1] = { 0 };
347966c8b06Salnsn 	uint32_t mem[ctx.extwords];
348966c8b06Salnsn 	void *arg = (void*)(uintptr_t)3;
349966c8b06Salnsn 
350966c8b06Salnsn 	/* Pre-inited words. */
351966c8b06Salnsn 	mem[0] = 0;
352966c8b06Salnsn 	mem[3] = 3;
353966c8b06Salnsn 
354966c8b06Salnsn 	bpf_args_t args = {
355966c8b06Salnsn 		.pkt = pkt,
356966c8b06Salnsn 		.buflen = sizeof(pkt),
357966c8b06Salnsn 		.wirelen = sizeof(pkt),
358966c8b06Salnsn 		.arg = arg,
359966c8b06Salnsn 		.mem = mem,
360966c8b06Salnsn 	};
361966c8b06Salnsn 
362966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
363966c8b06Salnsn 
364966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
365966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
366966c8b06Salnsn 
367966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 3);
368966c8b06Salnsn 
369966c8b06Salnsn 	bpfjit_free_code(code);
370966c8b06Salnsn }
371966c8b06Salnsn 
372f5874843Salnsn ATF_TC(libbpfjit_copx_ret_mem);
ATF_TC_HEAD(libbpfjit_copx_ret_mem,tc)373f5874843Salnsn ATF_TC_HEAD(libbpfjit_copx_ret_mem, tc)
374966c8b06Salnsn {
375966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
376966c8b06Salnsn 	    "that returns a content of external memory word");
377966c8b06Salnsn }
378966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_copx_ret_mem,tc)379f5874843Salnsn ATF_TC_BODY(libbpfjit_copx_ret_mem, tc)
380966c8b06Salnsn {
381966c8b06Salnsn 	static struct bpf_insn insns[] = {
382966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 13),
383966c8b06Salnsn 		BPF_STMT(BPF_ST, 2),
384966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 137),
385966c8b06Salnsn 		BPF_STMT(BPF_ST, 1),
386966c8b06Salnsn 		BPF_STMT(BPF_LDX+BPF_IMM, 0), // retM
387966c8b06Salnsn 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
388966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
389966c8b06Salnsn 	};
390966c8b06Salnsn 
391966c8b06Salnsn 	bpfjit_func_t code;
392966c8b06Salnsn 	uint8_t pkt[1] = { 0 };
393966c8b06Salnsn 	uint32_t mem[ctx.extwords];
394966c8b06Salnsn 	void *arg = (void*)(uintptr_t)2;
395966c8b06Salnsn 
396966c8b06Salnsn 	/* Pre-inited words. */
397966c8b06Salnsn 	mem[0] = 0;
398966c8b06Salnsn 	mem[3] = 3;
399966c8b06Salnsn 
400966c8b06Salnsn 	bpf_args_t args = {
401966c8b06Salnsn 		.pkt = pkt,
402966c8b06Salnsn 		.buflen = sizeof(pkt),
403966c8b06Salnsn 		.wirelen = sizeof(pkt),
404966c8b06Salnsn 		.arg = arg,
405966c8b06Salnsn 		.mem = mem,
406966c8b06Salnsn 	};
407966c8b06Salnsn 
408966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
409966c8b06Salnsn 
410966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
411966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
412966c8b06Salnsn 
413966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 13);
414966c8b06Salnsn 
415966c8b06Salnsn 	bpfjit_free_code(code);
416966c8b06Salnsn }
417966c8b06Salnsn 
418f5874843Salnsn ATF_TC(libbpfjit_copx_ret_preinited_mem);
ATF_TC_HEAD(libbpfjit_copx_ret_preinited_mem,tc)419f5874843Salnsn ATF_TC_HEAD(libbpfjit_copx_ret_preinited_mem, tc)
420966c8b06Salnsn {
421966c8b06Salnsn 	atf_tc_set_md_var(tc, "descr", "Test coprocessor function that "
422966c8b06Salnsn 	    "returns a content of external pre-initialized memory word");
423966c8b06Salnsn }
424966c8b06Salnsn 
ATF_TC_BODY(libbpfjit_copx_ret_preinited_mem,tc)425f5874843Salnsn ATF_TC_BODY(libbpfjit_copx_ret_preinited_mem, tc)
426966c8b06Salnsn {
427966c8b06Salnsn 	static struct bpf_insn insns[] = {
428966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 13),
429966c8b06Salnsn 		BPF_STMT(BPF_ST, 2),
430966c8b06Salnsn 		BPF_STMT(BPF_LD+BPF_IMM, 137),
431966c8b06Salnsn 		BPF_STMT(BPF_ST, 1),
432966c8b06Salnsn 		BPF_STMT(BPF_LDX+BPF_IMM, 0), // retM
433966c8b06Salnsn 		BPF_STMT(BPF_MISC+BPF_COPX, 0),
434966c8b06Salnsn 		BPF_STMT(BPF_RET+BPF_A, 0)
435966c8b06Salnsn 	};
436966c8b06Salnsn 
437966c8b06Salnsn 	bpfjit_func_t code;
438966c8b06Salnsn 	uint8_t pkt[1] = { 0 };
439966c8b06Salnsn 	uint32_t mem[ctx.extwords];
440966c8b06Salnsn 	void *arg = (void*)(uintptr_t)3;
441966c8b06Salnsn 
442966c8b06Salnsn 	/* Pre-inited words. */
443966c8b06Salnsn 	mem[0] = 0;
444966c8b06Salnsn 	mem[3] = 3;
445966c8b06Salnsn 
446966c8b06Salnsn 	bpf_args_t args = {
447966c8b06Salnsn 		.pkt = pkt,
448966c8b06Salnsn 		.buflen = sizeof(pkt),
449966c8b06Salnsn 		.wirelen = sizeof(pkt),
450966c8b06Salnsn 		.arg = arg,
451966c8b06Salnsn 		.mem = mem,
452966c8b06Salnsn 	};
453966c8b06Salnsn 
454966c8b06Salnsn 	size_t insn_count = sizeof(insns) / sizeof(insns[0]);
455966c8b06Salnsn 
456966c8b06Salnsn 	code = bpfjit_generate_code(&ctx, insns, insn_count);
457966c8b06Salnsn 	ATF_REQUIRE(code != NULL);
458966c8b06Salnsn 
459966c8b06Salnsn 	ATF_CHECK(code(&ctx, &args) == 3);
460966c8b06Salnsn 
461966c8b06Salnsn 	bpfjit_free_code(code);
462966c8b06Salnsn }
463966c8b06Salnsn 
ATF_TP_ADD_TCS(tp)464966c8b06Salnsn ATF_TP_ADD_TCS(tp)
465966c8b06Salnsn {
466966c8b06Salnsn 
467*5977f956Salnsn 	/*
468*5977f956Salnsn 	 * For every new test please also add a similar test
469*5977f956Salnsn 	 * to ../../net/bpfjit/t_extmem.c
470*5977f956Salnsn 	 */
471f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_extmem_load_default);
472f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_extmem_load_preinited);
473f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_extmem_invalid_load);
474f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_extmem_store);
475f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_extmem_side_effect);
476f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_extmem_invalid_store);
477f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_mem);
478f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_preinited_mem);
479f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_mem);
480f5874843Salnsn 	ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_preinited_mem);
481966c8b06Salnsn 
482966c8b06Salnsn 	return atf_no_error();
483966c8b06Salnsn }
484