1 /* $NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn Exp $ */
4 * Copyright (c) 2014 Alexander Nasonov.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: t_extmem.c,v 1.3 2014/07/14 19:11:15 alnsn Exp $");
41 #include <net/bpfjit.h>
43 static uint32_t retM(const bpf_ctx_t
*bc
, bpf_args_t
*args
, uint32_t A
);
45 static const bpf_copfunc_t copfuncs
[] = {
49 static const bpf_ctx_t ctx
= {
51 .nfuncs
= sizeof(copfuncs
) / sizeof(copfuncs
[0]),
53 .preinited
= BPF_MEMWORD_INIT(0) | BPF_MEMWORD_INIT(3),
57 retM(const bpf_ctx_t
*bc
, bpf_args_t
*args
, uint32_t A
)
60 return args
->mem
[(uintptr_t)args
->arg
];
64 ATF_TC(libbpfjit_extmem_load_default
);
65 ATF_TC_HEAD(libbpfjit_extmem_load_default
, tc
)
67 atf_tc_set_md_var(tc
, "descr", "Test that external memory "
68 "is zero initialized by default");
71 ATF_TC_BODY(libbpfjit_extmem_load_default
, tc
)
73 static struct bpf_insn insns
[] = {
74 BPF_STMT(BPF_LD
+BPF_MEM
, 1),
75 BPF_STMT(BPF_RET
+BPF_A
, 0)
79 uint8_t pkt
[1] = { 0 };
80 uint32_t mem
[ctx
.extwords
];
82 /* Pre-inited words. */
88 .buflen
= sizeof(pkt
),
89 .wirelen
= sizeof(pkt
),
93 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
95 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
96 ATF_REQUIRE(code
!= NULL
);
98 ATF_CHECK(code(&ctx
, &args
) == 0);
100 bpfjit_free_code(code
);
103 ATF_TC(libbpfjit_extmem_load_preinited
);
104 ATF_TC_HEAD(libbpfjit_extmem_load_preinited
, tc
)
106 atf_tc_set_md_var(tc
, "descr", "Test a load of external "
107 "pre-initialized memory");
110 ATF_TC_BODY(libbpfjit_extmem_load_preinited
, tc
)
112 static struct bpf_insn insns
[] = {
113 BPF_STMT(BPF_LD
+BPF_MEM
, 3),
114 BPF_STMT(BPF_RET
+BPF_A
, 0)
118 uint8_t pkt
[1] = { 0 };
119 uint32_t mem
[ctx
.extwords
];
121 /* Pre-inited words. */
127 .buflen
= sizeof(pkt
),
128 .wirelen
= sizeof(pkt
),
132 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
134 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
135 ATF_REQUIRE(code
!= NULL
);
137 ATF_CHECK(code(&ctx
, &args
) == 3);
139 bpfjit_free_code(code
);
142 ATF_TC(libbpfjit_extmem_invalid_load
);
143 ATF_TC_HEAD(libbpfjit_extmem_invalid_load
, tc
)
145 atf_tc_set_md_var(tc
, "descr", "Test that out-of-range load "
149 ATF_TC_BODY(libbpfjit_extmem_invalid_load
, tc
)
151 static struct bpf_insn insns
[] = {
152 BPF_STMT(BPF_LD
+BPF_MEM
, 4),
153 BPF_STMT(BPF_RET
+BPF_A
, 0)
156 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
158 ATF_CHECK(bpfjit_generate_code(&ctx
, insns
, insn_count
) == NULL
);
161 ATF_TC(libbpfjit_extmem_store
);
162 ATF_TC_HEAD(libbpfjit_extmem_store
, tc
)
164 atf_tc_set_md_var(tc
, "descr", "Test stores to external memory");
167 ATF_TC_BODY(libbpfjit_extmem_store
, tc
)
169 static struct bpf_insn insns
[] = {
170 BPF_STMT(BPF_LD
+BPF_IMM
, 1), /* A <- 1 */
171 BPF_STMT(BPF_LDX
+BPF_W
+BPF_IMM
, 2), /* X <- 2 */
172 BPF_STMT(BPF_ST
, 1), /* M[1] <- A */
173 BPF_STMT(BPF_ALU
+BPF_ADD
+BPF_X
, 0), /* A <- A + X */
174 BPF_STMT(BPF_STX
, 2), /* M[2] <- X */
175 BPF_STMT(BPF_ST
, 3), /* M[3] <- A */
176 BPF_STMT(BPF_RET
+BPF_A
, 0) /* ret A */
180 uint8_t pkt
[1] = { 0 };
181 uint32_t mem
[ctx
.extwords
];
183 /* Pre-inited words. */
187 mem
[1] = mem
[2] = 0xdeadbeef;
191 .buflen
= sizeof(pkt
),
192 .wirelen
= sizeof(pkt
),
196 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
198 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
199 ATF_REQUIRE(code
!= NULL
);
201 ATF_CHECK(code(&ctx
, &args
) == 3);
203 bpfjit_free_code(code
);
205 ATF_CHECK(mem
[0] == 0);
206 ATF_CHECK(mem
[1] == 1);
207 ATF_CHECK(mem
[2] == 2);
208 ATF_CHECK(mem
[3] == 3);
211 ATF_TC(libbpfjit_extmem_side_effect
);
212 ATF_TC_HEAD(libbpfjit_extmem_side_effect
, tc
)
214 atf_tc_set_md_var(tc
, "descr", "Test that ABC optimization doesn\'t "
215 "skip stores to external memory");
218 ATF_TC_BODY(libbpfjit_extmem_side_effect
, tc
)
220 static struct bpf_insn insns
[] = {
221 BPF_STMT(BPF_LD
+BPF_B
+BPF_ABS
, 0), /* A <- P[0] */
222 BPF_STMT(BPF_LDX
+BPF_W
+BPF_IMM
, 2), /* X <- 2 */
223 BPF_STMT(BPF_ST
, 1), /* M[1] <- A */
224 BPF_STMT(BPF_ALU
+BPF_ADD
+BPF_X
, 0), /* A <- A + X */
225 BPF_STMT(BPF_STX
, 2), /* M[2] <- X */
226 BPF_STMT(BPF_ST
, 3), /* M[3] <- A */
227 BPF_STMT(BPF_LD
+BPF_B
+BPF_ABS
, 99), /* A <- P[99] */
228 BPF_STMT(BPF_RET
+BPF_A
, 0) /* ret A */
232 uint8_t pkt
[1] = { 1 };
233 uint32_t mem
[ctx
.extwords
];
235 /* Pre-inited words. */
239 mem
[1] = mem
[2] = 0xdeadbeef;
243 .buflen
= sizeof(pkt
),
244 .wirelen
= sizeof(pkt
),
248 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
250 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
251 ATF_REQUIRE(code
!= NULL
);
253 ATF_CHECK(code(&ctx
, &args
) == 0);
255 bpfjit_free_code(code
);
257 ATF_CHECK(mem
[0] == 0);
258 ATF_CHECK(mem
[1] == 1);
259 ATF_CHECK(mem
[2] == 2);
260 ATF_CHECK(mem
[3] == 3);
263 ATF_TC(libbpfjit_extmem_invalid_store
);
264 ATF_TC_HEAD(libbpfjit_extmem_invalid_store
, tc
)
266 atf_tc_set_md_var(tc
, "descr", "Test that out-of-range store "
270 ATF_TC_BODY(libbpfjit_extmem_invalid_store
, tc
)
272 static struct bpf_insn insns
[] = {
274 BPF_STMT(BPF_RET
+BPF_A
, 0)
277 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
279 ATF_CHECK(bpfjit_generate_code(&ctx
, insns
, insn_count
) == NULL
);
282 ATF_TC(libbpfjit_cop_ret_mem
);
283 ATF_TC_HEAD(libbpfjit_cop_ret_mem
, tc
)
285 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function "
286 "that returns a content of external memory word");
289 ATF_TC_BODY(libbpfjit_cop_ret_mem
, tc
)
291 static struct bpf_insn insns
[] = {
292 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
294 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
296 BPF_STMT(BPF_MISC
+BPF_COP
, 0), // retM
297 BPF_STMT(BPF_RET
+BPF_A
, 0)
301 uint8_t pkt
[1] = { 0 };
302 uint32_t mem
[ctx
.extwords
];
303 void *arg
= (void*)(uintptr_t)2;
305 /* Pre-inited words. */
311 .buflen
= sizeof(pkt
),
312 .wirelen
= sizeof(pkt
),
317 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
319 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
320 ATF_REQUIRE(code
!= NULL
);
322 ATF_CHECK(code(&ctx
, &args
) == 13);
324 bpfjit_free_code(code
);
327 ATF_TC(libbpfjit_cop_ret_preinited_mem
);
328 ATF_TC_HEAD(libbpfjit_cop_ret_preinited_mem
, tc
)
330 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function that "
331 "returns a content of external pre-initialized memory word");
334 ATF_TC_BODY(libbpfjit_cop_ret_preinited_mem
, tc
)
336 static struct bpf_insn insns
[] = {
337 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
339 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
341 BPF_STMT(BPF_MISC
+BPF_COP
, 0), // retM
342 BPF_STMT(BPF_RET
+BPF_A
, 0)
346 uint8_t pkt
[1] = { 0 };
347 uint32_t mem
[ctx
.extwords
];
348 void *arg
= (void*)(uintptr_t)3;
350 /* Pre-inited words. */
356 .buflen
= sizeof(pkt
),
357 .wirelen
= sizeof(pkt
),
362 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
364 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
365 ATF_REQUIRE(code
!= NULL
);
367 ATF_CHECK(code(&ctx
, &args
) == 3);
369 bpfjit_free_code(code
);
372 ATF_TC(libbpfjit_copx_ret_mem
);
373 ATF_TC_HEAD(libbpfjit_copx_ret_mem
, tc
)
375 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function "
376 "that returns a content of external memory word");
379 ATF_TC_BODY(libbpfjit_copx_ret_mem
, tc
)
381 static struct bpf_insn insns
[] = {
382 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
384 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
386 BPF_STMT(BPF_LDX
+BPF_IMM
, 0), // retM
387 BPF_STMT(BPF_MISC
+BPF_COPX
, 0),
388 BPF_STMT(BPF_RET
+BPF_A
, 0)
392 uint8_t pkt
[1] = { 0 };
393 uint32_t mem
[ctx
.extwords
];
394 void *arg
= (void*)(uintptr_t)2;
396 /* Pre-inited words. */
402 .buflen
= sizeof(pkt
),
403 .wirelen
= sizeof(pkt
),
408 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
410 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
411 ATF_REQUIRE(code
!= NULL
);
413 ATF_CHECK(code(&ctx
, &args
) == 13);
415 bpfjit_free_code(code
);
418 ATF_TC(libbpfjit_copx_ret_preinited_mem
);
419 ATF_TC_HEAD(libbpfjit_copx_ret_preinited_mem
, tc
)
421 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function that "
422 "returns a content of external pre-initialized memory word");
425 ATF_TC_BODY(libbpfjit_copx_ret_preinited_mem
, tc
)
427 static struct bpf_insn insns
[] = {
428 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
430 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
432 BPF_STMT(BPF_LDX
+BPF_IMM
, 0), // retM
433 BPF_STMT(BPF_MISC
+BPF_COPX
, 0),
434 BPF_STMT(BPF_RET
+BPF_A
, 0)
438 uint8_t pkt
[1] = { 0 };
439 uint32_t mem
[ctx
.extwords
];
440 void *arg
= (void*)(uintptr_t)3;
442 /* Pre-inited words. */
448 .buflen
= sizeof(pkt
),
449 .wirelen
= sizeof(pkt
),
454 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
456 code
= bpfjit_generate_code(&ctx
, insns
, insn_count
);
457 ATF_REQUIRE(code
!= NULL
);
459 ATF_CHECK(code(&ctx
, &args
) == 3);
461 bpfjit_free_code(code
);
468 * For every new test please also add a similar test
469 * to ../../net/bpfjit/t_extmem.c
471 ATF_TP_ADD_TC(tp
, libbpfjit_extmem_load_default
);
472 ATF_TP_ADD_TC(tp
, libbpfjit_extmem_load_preinited
);
473 ATF_TP_ADD_TC(tp
, libbpfjit_extmem_invalid_load
);
474 ATF_TP_ADD_TC(tp
, libbpfjit_extmem_store
);
475 ATF_TP_ADD_TC(tp
, libbpfjit_extmem_side_effect
);
476 ATF_TP_ADD_TC(tp
, libbpfjit_extmem_invalid_store
);
477 ATF_TP_ADD_TC(tp
, libbpfjit_cop_ret_mem
);
478 ATF_TP_ADD_TC(tp
, libbpfjit_cop_ret_preinited_mem
);
479 ATF_TP_ADD_TC(tp
, libbpfjit_copx_ret_mem
);
480 ATF_TP_ADD_TC(tp
, libbpfjit_copx_ret_preinited_mem
);
482 return atf_no_error();