t_extmem.c revision 1.3 1 1.3 alnsn /* $NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn 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.3 alnsn __RCSID("$NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn Exp $");
34 1.1 alnsn
35 1.1 alnsn #include <atf-c.h>
36 1.1 alnsn #include <stdint.h>
37 1.1 alnsn #include <string.h>
38 1.1 alnsn
39 1.1 alnsn #define __BPF_PRIVATE
40 1.1 alnsn #include <net/bpf.h>
41 1.1 alnsn #include <net/bpfjit.h>
42 1.1 alnsn
43 1.1 alnsn static uint32_t retM(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A);
44 1.1 alnsn
45 1.1 alnsn static const bpf_copfunc_t copfuncs[] = {
46 1.1 alnsn &retM
47 1.1 alnsn };
48 1.1 alnsn
49 1.1 alnsn static const bpf_ctx_t ctx = {
50 1.1 alnsn .copfuncs = copfuncs,
51 1.1 alnsn .nfuncs = sizeof(copfuncs) / sizeof(copfuncs[0]),
52 1.1 alnsn .extwords = 4,
53 1.1 alnsn .preinited = BPF_MEMWORD_INIT(0) | BPF_MEMWORD_INIT(3),
54 1.1 alnsn };
55 1.1 alnsn
56 1.1 alnsn static uint32_t
57 1.1 alnsn retM(const bpf_ctx_t *bc, bpf_args_t *args, uint32_t A)
58 1.1 alnsn {
59 1.1 alnsn
60 1.1 alnsn return args->mem[(uintptr_t)args->arg];
61 1.1 alnsn }
62 1.1 alnsn
63 1.1 alnsn
64 1.2 alnsn ATF_TC(libbpfjit_extmem_load_default);
65 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_load_default, tc)
66 1.1 alnsn {
67 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that external memory "
68 1.1 alnsn "is zero initialized by default");
69 1.1 alnsn }
70 1.1 alnsn
71 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_load_default, tc)
72 1.1 alnsn {
73 1.1 alnsn static struct bpf_insn insns[] = {
74 1.1 alnsn BPF_STMT(BPF_LD+BPF_MEM, 1),
75 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
76 1.1 alnsn };
77 1.1 alnsn
78 1.1 alnsn bpfjit_func_t code;
79 1.1 alnsn uint8_t pkt[1] = { 0 };
80 1.1 alnsn uint32_t mem[ctx.extwords];
81 1.1 alnsn
82 1.1 alnsn /* Pre-inited words. */
83 1.1 alnsn mem[0] = 0;
84 1.1 alnsn mem[3] = 3;
85 1.1 alnsn
86 1.1 alnsn bpf_args_t args = {
87 1.1 alnsn .pkt = pkt,
88 1.1 alnsn .buflen = sizeof(pkt),
89 1.1 alnsn .wirelen = sizeof(pkt),
90 1.1 alnsn .mem = mem,
91 1.1 alnsn };
92 1.1 alnsn
93 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
94 1.1 alnsn
95 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
96 1.1 alnsn ATF_REQUIRE(code != NULL);
97 1.1 alnsn
98 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 0);
99 1.1 alnsn
100 1.1 alnsn bpfjit_free_code(code);
101 1.1 alnsn }
102 1.1 alnsn
103 1.2 alnsn ATF_TC(libbpfjit_extmem_load_preinited);
104 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_load_preinited, tc)
105 1.1 alnsn {
106 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test a load of external "
107 1.1 alnsn "pre-initialized memory");
108 1.1 alnsn }
109 1.1 alnsn
110 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_load_preinited, tc)
111 1.1 alnsn {
112 1.1 alnsn static struct bpf_insn insns[] = {
113 1.1 alnsn BPF_STMT(BPF_LD+BPF_MEM, 3),
114 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
115 1.1 alnsn };
116 1.1 alnsn
117 1.1 alnsn bpfjit_func_t code;
118 1.1 alnsn uint8_t pkt[1] = { 0 };
119 1.1 alnsn uint32_t mem[ctx.extwords];
120 1.1 alnsn
121 1.1 alnsn /* Pre-inited words. */
122 1.1 alnsn mem[0] = 0;
123 1.1 alnsn mem[3] = 3;
124 1.1 alnsn
125 1.1 alnsn bpf_args_t args = {
126 1.1 alnsn .pkt = pkt,
127 1.1 alnsn .buflen = sizeof(pkt),
128 1.1 alnsn .wirelen = sizeof(pkt),
129 1.1 alnsn .mem = mem,
130 1.1 alnsn };
131 1.1 alnsn
132 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
133 1.1 alnsn
134 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
135 1.1 alnsn ATF_REQUIRE(code != NULL);
136 1.1 alnsn
137 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3);
138 1.1 alnsn
139 1.1 alnsn bpfjit_free_code(code);
140 1.1 alnsn }
141 1.1 alnsn
142 1.2 alnsn ATF_TC(libbpfjit_extmem_invalid_load);
143 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_invalid_load, tc)
144 1.1 alnsn {
145 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that out-of-range load "
146 1.1 alnsn "fails validation");
147 1.1 alnsn }
148 1.1 alnsn
149 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_invalid_load, tc)
150 1.1 alnsn {
151 1.1 alnsn static struct bpf_insn insns[] = {
152 1.1 alnsn BPF_STMT(BPF_LD+BPF_MEM, 4),
153 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
154 1.1 alnsn };
155 1.1 alnsn
156 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
157 1.1 alnsn
158 1.1 alnsn ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL);
159 1.1 alnsn }
160 1.1 alnsn
161 1.2 alnsn ATF_TC(libbpfjit_extmem_store);
162 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_store, tc)
163 1.1 alnsn {
164 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test stores to external memory");
165 1.1 alnsn }
166 1.1 alnsn
167 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_store, tc)
168 1.1 alnsn {
169 1.1 alnsn static struct bpf_insn insns[] = {
170 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 1), /* A <- 1 */
171 1.1 alnsn BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2), /* X <- 2 */
172 1.1 alnsn BPF_STMT(BPF_ST, 1), /* M[1] <- A */
173 1.1 alnsn BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0), /* A <- A + X */
174 1.1 alnsn BPF_STMT(BPF_STX, 2), /* M[2] <- X */
175 1.1 alnsn BPF_STMT(BPF_ST, 3), /* M[3] <- A */
176 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) /* ret A */
177 1.1 alnsn };
178 1.1 alnsn
179 1.1 alnsn bpfjit_func_t code;
180 1.1 alnsn uint8_t pkt[1] = { 0 };
181 1.1 alnsn uint32_t mem[ctx.extwords];
182 1.1 alnsn
183 1.1 alnsn /* Pre-inited words. */
184 1.1 alnsn mem[0] = 0;
185 1.1 alnsn mem[3] = 7;
186 1.1 alnsn
187 1.1 alnsn mem[1] = mem[2] = 0xdeadbeef;
188 1.1 alnsn
189 1.1 alnsn bpf_args_t args = {
190 1.1 alnsn .pkt = pkt,
191 1.1 alnsn .buflen = sizeof(pkt),
192 1.1 alnsn .wirelen = sizeof(pkt),
193 1.1 alnsn .mem = mem,
194 1.1 alnsn };
195 1.1 alnsn
196 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
197 1.1 alnsn
198 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
199 1.1 alnsn ATF_REQUIRE(code != NULL);
200 1.1 alnsn
201 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3);
202 1.1 alnsn
203 1.1 alnsn bpfjit_free_code(code);
204 1.1 alnsn
205 1.1 alnsn ATF_CHECK(mem[0] == 0);
206 1.1 alnsn ATF_CHECK(mem[1] == 1);
207 1.1 alnsn ATF_CHECK(mem[2] == 2);
208 1.1 alnsn ATF_CHECK(mem[3] == 3);
209 1.1 alnsn }
210 1.1 alnsn
211 1.2 alnsn ATF_TC(libbpfjit_extmem_side_effect);
212 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_side_effect, tc)
213 1.1 alnsn {
214 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that ABC optimization doesn\'t "
215 1.1 alnsn "skip stores to external memory");
216 1.1 alnsn }
217 1.1 alnsn
218 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_side_effect, tc)
219 1.1 alnsn {
220 1.1 alnsn static struct bpf_insn insns[] = {
221 1.1 alnsn BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), /* A <- P[0] */
222 1.1 alnsn BPF_STMT(BPF_LDX+BPF_W+BPF_IMM, 2), /* X <- 2 */
223 1.1 alnsn BPF_STMT(BPF_ST, 1), /* M[1] <- A */
224 1.1 alnsn BPF_STMT(BPF_ALU+BPF_ADD+BPF_X, 0), /* A <- A + X */
225 1.1 alnsn BPF_STMT(BPF_STX, 2), /* M[2] <- X */
226 1.1 alnsn BPF_STMT(BPF_ST, 3), /* M[3] <- A */
227 1.1 alnsn BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 99), /* A <- P[99] */
228 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0) /* ret A */
229 1.1 alnsn };
230 1.1 alnsn
231 1.1 alnsn bpfjit_func_t code;
232 1.1 alnsn uint8_t pkt[1] = { 1 };
233 1.1 alnsn uint32_t mem[ctx.extwords];
234 1.1 alnsn
235 1.1 alnsn /* Pre-inited words. */
236 1.1 alnsn mem[0] = 0;
237 1.1 alnsn mem[3] = 7;
238 1.1 alnsn
239 1.1 alnsn mem[1] = mem[2] = 0xdeadbeef;
240 1.1 alnsn
241 1.1 alnsn bpf_args_t args = {
242 1.1 alnsn .pkt = pkt,
243 1.1 alnsn .buflen = sizeof(pkt),
244 1.1 alnsn .wirelen = sizeof(pkt),
245 1.1 alnsn .mem = mem,
246 1.1 alnsn };
247 1.1 alnsn
248 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
249 1.1 alnsn
250 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
251 1.1 alnsn ATF_REQUIRE(code != NULL);
252 1.1 alnsn
253 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 0);
254 1.1 alnsn
255 1.1 alnsn bpfjit_free_code(code);
256 1.1 alnsn
257 1.1 alnsn ATF_CHECK(mem[0] == 0);
258 1.1 alnsn ATF_CHECK(mem[1] == 1);
259 1.1 alnsn ATF_CHECK(mem[2] == 2);
260 1.1 alnsn ATF_CHECK(mem[3] == 3);
261 1.1 alnsn }
262 1.1 alnsn
263 1.2 alnsn ATF_TC(libbpfjit_extmem_invalid_store);
264 1.2 alnsn ATF_TC_HEAD(libbpfjit_extmem_invalid_store, tc)
265 1.1 alnsn {
266 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test that out-of-range store "
267 1.1 alnsn "fails validation");
268 1.1 alnsn }
269 1.1 alnsn
270 1.2 alnsn ATF_TC_BODY(libbpfjit_extmem_invalid_store, tc)
271 1.1 alnsn {
272 1.1 alnsn static struct bpf_insn insns[] = {
273 1.1 alnsn BPF_STMT(BPF_ST, 4),
274 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
275 1.1 alnsn };
276 1.1 alnsn
277 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
278 1.1 alnsn
279 1.1 alnsn ATF_CHECK(bpfjit_generate_code(&ctx, insns, insn_count) == NULL);
280 1.1 alnsn }
281 1.1 alnsn
282 1.2 alnsn ATF_TC(libbpfjit_cop_ret_mem);
283 1.2 alnsn ATF_TC_HEAD(libbpfjit_cop_ret_mem, tc)
284 1.1 alnsn {
285 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
286 1.1 alnsn "that returns a content of external memory word");
287 1.1 alnsn }
288 1.1 alnsn
289 1.2 alnsn ATF_TC_BODY(libbpfjit_cop_ret_mem, tc)
290 1.1 alnsn {
291 1.1 alnsn static struct bpf_insn insns[] = {
292 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13),
293 1.1 alnsn BPF_STMT(BPF_ST, 2),
294 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137),
295 1.1 alnsn BPF_STMT(BPF_ST, 1),
296 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COP, 0), // retM
297 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
298 1.1 alnsn };
299 1.1 alnsn
300 1.1 alnsn bpfjit_func_t code;
301 1.1 alnsn uint8_t pkt[1] = { 0 };
302 1.1 alnsn uint32_t mem[ctx.extwords];
303 1.1 alnsn void *arg = (void*)(uintptr_t)2;
304 1.1 alnsn
305 1.1 alnsn /* Pre-inited words. */
306 1.1 alnsn mem[0] = 0;
307 1.1 alnsn mem[3] = 3;
308 1.1 alnsn
309 1.1 alnsn bpf_args_t args = {
310 1.1 alnsn .pkt = pkt,
311 1.1 alnsn .buflen = sizeof(pkt),
312 1.1 alnsn .wirelen = sizeof(pkt),
313 1.1 alnsn .arg = arg,
314 1.1 alnsn .mem = mem,
315 1.1 alnsn };
316 1.1 alnsn
317 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
318 1.1 alnsn
319 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
320 1.1 alnsn ATF_REQUIRE(code != NULL);
321 1.1 alnsn
322 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 13);
323 1.1 alnsn
324 1.1 alnsn bpfjit_free_code(code);
325 1.1 alnsn }
326 1.1 alnsn
327 1.2 alnsn ATF_TC(libbpfjit_cop_ret_preinited_mem);
328 1.2 alnsn ATF_TC_HEAD(libbpfjit_cop_ret_preinited_mem, tc)
329 1.1 alnsn {
330 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function that "
331 1.1 alnsn "returns a content of external pre-initialized memory word");
332 1.1 alnsn }
333 1.1 alnsn
334 1.2 alnsn ATF_TC_BODY(libbpfjit_cop_ret_preinited_mem, tc)
335 1.1 alnsn {
336 1.1 alnsn static struct bpf_insn insns[] = {
337 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13),
338 1.1 alnsn BPF_STMT(BPF_ST, 2),
339 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137),
340 1.1 alnsn BPF_STMT(BPF_ST, 1),
341 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COP, 0), // retM
342 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
343 1.1 alnsn };
344 1.1 alnsn
345 1.1 alnsn bpfjit_func_t code;
346 1.1 alnsn uint8_t pkt[1] = { 0 };
347 1.1 alnsn uint32_t mem[ctx.extwords];
348 1.1 alnsn void *arg = (void*)(uintptr_t)3;
349 1.1 alnsn
350 1.1 alnsn /* Pre-inited words. */
351 1.1 alnsn mem[0] = 0;
352 1.1 alnsn mem[3] = 3;
353 1.1 alnsn
354 1.1 alnsn bpf_args_t args = {
355 1.1 alnsn .pkt = pkt,
356 1.1 alnsn .buflen = sizeof(pkt),
357 1.1 alnsn .wirelen = sizeof(pkt),
358 1.1 alnsn .arg = arg,
359 1.1 alnsn .mem = mem,
360 1.1 alnsn };
361 1.1 alnsn
362 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
363 1.1 alnsn
364 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
365 1.1 alnsn ATF_REQUIRE(code != NULL);
366 1.1 alnsn
367 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3);
368 1.1 alnsn
369 1.1 alnsn bpfjit_free_code(code);
370 1.1 alnsn }
371 1.1 alnsn
372 1.2 alnsn ATF_TC(libbpfjit_copx_ret_mem);
373 1.2 alnsn ATF_TC_HEAD(libbpfjit_copx_ret_mem, tc)
374 1.1 alnsn {
375 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function "
376 1.1 alnsn "that returns a content of external memory word");
377 1.1 alnsn }
378 1.1 alnsn
379 1.2 alnsn ATF_TC_BODY(libbpfjit_copx_ret_mem, tc)
380 1.1 alnsn {
381 1.1 alnsn static struct bpf_insn insns[] = {
382 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13),
383 1.1 alnsn BPF_STMT(BPF_ST, 2),
384 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137),
385 1.1 alnsn BPF_STMT(BPF_ST, 1),
386 1.1 alnsn BPF_STMT(BPF_LDX+BPF_IMM, 0), // retM
387 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COPX, 0),
388 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
389 1.1 alnsn };
390 1.1 alnsn
391 1.1 alnsn bpfjit_func_t code;
392 1.1 alnsn uint8_t pkt[1] = { 0 };
393 1.1 alnsn uint32_t mem[ctx.extwords];
394 1.1 alnsn void *arg = (void*)(uintptr_t)2;
395 1.1 alnsn
396 1.1 alnsn /* Pre-inited words. */
397 1.1 alnsn mem[0] = 0;
398 1.1 alnsn mem[3] = 3;
399 1.1 alnsn
400 1.1 alnsn bpf_args_t args = {
401 1.1 alnsn .pkt = pkt,
402 1.1 alnsn .buflen = sizeof(pkt),
403 1.1 alnsn .wirelen = sizeof(pkt),
404 1.1 alnsn .arg = arg,
405 1.1 alnsn .mem = mem,
406 1.1 alnsn };
407 1.1 alnsn
408 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
409 1.1 alnsn
410 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
411 1.1 alnsn ATF_REQUIRE(code != NULL);
412 1.1 alnsn
413 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 13);
414 1.1 alnsn
415 1.1 alnsn bpfjit_free_code(code);
416 1.1 alnsn }
417 1.1 alnsn
418 1.2 alnsn ATF_TC(libbpfjit_copx_ret_preinited_mem);
419 1.2 alnsn ATF_TC_HEAD(libbpfjit_copx_ret_preinited_mem, tc)
420 1.1 alnsn {
421 1.1 alnsn atf_tc_set_md_var(tc, "descr", "Test coprocessor function that "
422 1.1 alnsn "returns a content of external pre-initialized memory word");
423 1.1 alnsn }
424 1.1 alnsn
425 1.2 alnsn ATF_TC_BODY(libbpfjit_copx_ret_preinited_mem, tc)
426 1.1 alnsn {
427 1.1 alnsn static struct bpf_insn insns[] = {
428 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 13),
429 1.1 alnsn BPF_STMT(BPF_ST, 2),
430 1.1 alnsn BPF_STMT(BPF_LD+BPF_IMM, 137),
431 1.1 alnsn BPF_STMT(BPF_ST, 1),
432 1.1 alnsn BPF_STMT(BPF_LDX+BPF_IMM, 0), // retM
433 1.1 alnsn BPF_STMT(BPF_MISC+BPF_COPX, 0),
434 1.1 alnsn BPF_STMT(BPF_RET+BPF_A, 0)
435 1.1 alnsn };
436 1.1 alnsn
437 1.1 alnsn bpfjit_func_t code;
438 1.1 alnsn uint8_t pkt[1] = { 0 };
439 1.1 alnsn uint32_t mem[ctx.extwords];
440 1.1 alnsn void *arg = (void*)(uintptr_t)3;
441 1.1 alnsn
442 1.1 alnsn /* Pre-inited words. */
443 1.1 alnsn mem[0] = 0;
444 1.1 alnsn mem[3] = 3;
445 1.1 alnsn
446 1.1 alnsn bpf_args_t args = {
447 1.1 alnsn .pkt = pkt,
448 1.1 alnsn .buflen = sizeof(pkt),
449 1.1 alnsn .wirelen = sizeof(pkt),
450 1.1 alnsn .arg = arg,
451 1.1 alnsn .mem = mem,
452 1.1 alnsn };
453 1.1 alnsn
454 1.1 alnsn size_t insn_count = sizeof(insns) / sizeof(insns[0]);
455 1.1 alnsn
456 1.1 alnsn code = bpfjit_generate_code(&ctx, insns, insn_count);
457 1.1 alnsn ATF_REQUIRE(code != NULL);
458 1.1 alnsn
459 1.1 alnsn ATF_CHECK(code(&ctx, &args) == 3);
460 1.1 alnsn
461 1.1 alnsn bpfjit_free_code(code);
462 1.1 alnsn }
463 1.1 alnsn
464 1.1 alnsn ATF_TP_ADD_TCS(tp)
465 1.1 alnsn {
466 1.1 alnsn
467 1.3 alnsn /*
468 1.3 alnsn * For every new test please also add a similar test
469 1.3 alnsn * to ../../net/bpfjit/t_extmem.c
470 1.3 alnsn */
471 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_load_default);
472 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_load_preinited);
473 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_invalid_load);
474 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_store);
475 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_side_effect);
476 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_extmem_invalid_store);
477 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_mem);
478 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_cop_ret_preinited_mem);
479 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_mem);
480 1.2 alnsn ATF_TP_ADD_TC(tp, libbpfjit_copx_ret_preinited_mem);
481 1.1 alnsn
482 1.1 alnsn return atf_no_error();
483 1.1 alnsn }
484