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