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