1 /* $NetBSD: t_extmem.c,v 1.1 2014/07/09 13:49:49 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.1 2014/07/09 13:49:49 alnsn Exp $");
40 #include <net/bpfjit.h>
42 #include "../../net/bpf/h_bpf.h"
44 /* XXX: atf-c.h has collisions with mbuf */
49 #include "../../h_macros.h"
51 static uint32_t retM(const bpf_ctx_t
*bc
, bpf_args_t
*args
, uint32_t A
);
53 static const bpf_copfunc_t copfuncs
[] = {
57 static const bpf_ctx_t ctx
= {
59 .nfuncs
= sizeof(copfuncs
) / sizeof(copfuncs
[0]),
61 .preinited
= BPF_MEMWORD_INIT(0) | BPF_MEMWORD_INIT(3),
65 retM(const bpf_ctx_t
*bc
, bpf_args_t
*args
, uint32_t A
)
68 return args
->mem
[(uintptr_t)args
->arg
];
72 ATF_TC(bpfjit_extmem_load_preinited
);
73 ATF_TC_HEAD(bpfjit_extmem_load_preinited
, tc
)
75 atf_tc_set_md_var(tc
, "descr", "Test a load of external "
76 "pre-initialized memory");
79 ATF_TC_BODY(bpfjit_extmem_load_preinited
, tc
)
81 static struct bpf_insn insns
[] = {
82 BPF_STMT(BPF_LD
+BPF_MEM
, 3),
83 BPF_STMT(BPF_RET
+BPF_A
, 0)
87 uint8_t pkt
[1] = { 0 };
88 uint32_t mem
[ctx
.extwords
];
90 /* Pre-inited words. */
96 .buflen
= sizeof(pkt
),
97 .wirelen
= sizeof(pkt
),
101 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
106 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
108 ATF_REQUIRE(code
!= NULL
);
110 ATF_CHECK(code(&ctx
, &args
) == 3);
113 rumpns_bpfjit_free_code(code
);
117 ATF_TC(bpfjit_extmem_invalid_load
);
118 ATF_TC_HEAD(bpfjit_extmem_invalid_load
, tc
)
120 atf_tc_set_md_var(tc
, "descr", "Test that out-of-range load "
124 ATF_TC_BODY(bpfjit_extmem_invalid_load
, tc
)
126 static struct bpf_insn insns
[] = {
127 BPF_STMT(BPF_LD
+BPF_MEM
, 4),
128 BPF_STMT(BPF_RET
+BPF_A
, 0)
132 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
137 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
139 ATF_CHECK(code
== NULL
);
142 ATF_TC(bpfjit_extmem_store
);
143 ATF_TC_HEAD(bpfjit_extmem_store
, tc
)
145 atf_tc_set_md_var(tc
, "descr", "Test stores to external memory");
148 ATF_TC_BODY(bpfjit_extmem_store
, tc
)
150 static struct bpf_insn insns
[] = {
151 BPF_STMT(BPF_LD
+BPF_IMM
, 1), /* A <- 1 */
152 BPF_STMT(BPF_LDX
+BPF_W
+BPF_IMM
, 2), /* X <- 2 */
153 BPF_STMT(BPF_ST
, 1), /* M[1] <- A */
154 BPF_STMT(BPF_ALU
+BPF_ADD
+BPF_X
, 0), /* A <- A + X */
155 BPF_STMT(BPF_STX
, 2), /* M[2] <- X */
156 BPF_STMT(BPF_ST
, 3), /* M[3] <- A */
157 BPF_STMT(BPF_RET
+BPF_A
, 0) /* ret A */
161 uint8_t pkt
[1] = { 0 };
162 uint32_t mem
[ctx
.extwords
];
164 /* Pre-inited words. */
168 mem
[1] = mem
[2] = 0xdeadbeef;
172 .buflen
= sizeof(pkt
),
173 .wirelen
= sizeof(pkt
),
177 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
182 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
184 ATF_REQUIRE(code
!= NULL
);
186 ATF_CHECK(code(&ctx
, &args
) == 3);
189 rumpns_bpfjit_free_code(code
);
192 ATF_CHECK(mem
[0] == 0);
193 ATF_CHECK(mem
[1] == 1);
194 ATF_CHECK(mem
[2] == 2);
195 ATF_CHECK(mem
[3] == 3);
198 ATF_TC(bpfjit_extmem_side_effect
);
199 ATF_TC_HEAD(bpfjit_extmem_side_effect
, tc
)
201 atf_tc_set_md_var(tc
, "descr", "Test that ABC optimization doesn\'t "
202 "skip stores to external memory");
205 ATF_TC_BODY(bpfjit_extmem_side_effect
, tc
)
207 static struct bpf_insn insns
[] = {
208 BPF_STMT(BPF_LD
+BPF_B
+BPF_ABS
, 0), /* A <- P[0] */
209 BPF_STMT(BPF_LDX
+BPF_W
+BPF_IMM
, 2), /* X <- 2 */
210 BPF_STMT(BPF_ST
, 1), /* M[1] <- A */
211 BPF_STMT(BPF_ALU
+BPF_ADD
+BPF_X
, 0), /* A <- A + X */
212 BPF_STMT(BPF_STX
, 2), /* M[2] <- X */
213 BPF_STMT(BPF_ST
, 3), /* M[3] <- A */
214 BPF_STMT(BPF_LD
+BPF_B
+BPF_ABS
, 99), /* A <- P[99] */
215 BPF_STMT(BPF_RET
+BPF_A
, 0) /* ret A */
219 uint8_t pkt
[1] = { 1 };
220 uint32_t mem
[ctx
.extwords
];
222 /* Pre-inited words. */
226 mem
[1] = mem
[2] = 0xdeadbeef;
230 .buflen
= sizeof(pkt
),
231 .wirelen
= sizeof(pkt
),
235 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
240 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
242 ATF_REQUIRE(code
!= NULL
);
244 ATF_CHECK(code(&ctx
, &args
) == 0);
247 rumpns_bpfjit_free_code(code
);
250 ATF_CHECK(mem
[0] == 0);
251 ATF_CHECK(mem
[1] == 1);
252 ATF_CHECK(mem
[2] == 2);
253 ATF_CHECK(mem
[3] == 3);
256 ATF_TC(bpfjit_extmem_invalid_store
);
257 ATF_TC_HEAD(bpfjit_extmem_invalid_store
, tc
)
259 atf_tc_set_md_var(tc
, "descr", "Test that out-of-range store "
263 ATF_TC_BODY(bpfjit_extmem_invalid_store
, tc
)
265 static struct bpf_insn insns
[] = {
267 BPF_STMT(BPF_RET
+BPF_A
, 0)
271 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
276 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
278 ATF_CHECK(code
== NULL
);
281 ATF_TC(bpfjit_cop_ret_mem
);
282 ATF_TC_HEAD(bpfjit_cop_ret_mem
, tc
)
284 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function "
285 "that returns a content of external memory word");
288 ATF_TC_BODY(bpfjit_cop_ret_mem
, tc
)
290 static struct bpf_insn insns
[] = {
291 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
293 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
295 BPF_STMT(BPF_MISC
+BPF_COP
, 0), // retM
296 BPF_STMT(BPF_RET
+BPF_A
, 0)
300 uint8_t pkt
[1] = { 0 };
301 uint32_t mem
[ctx
.extwords
];
302 void *arg
= (void*)(uintptr_t)2;
304 /* Pre-inited words. */
310 .buflen
= sizeof(pkt
),
311 .wirelen
= sizeof(pkt
),
316 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
321 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
323 ATF_REQUIRE(code
!= NULL
);
325 ATF_CHECK(code(&ctx
, &args
) == 13);
328 rumpns_bpfjit_free_code(code
);
332 ATF_TC(bpfjit_cop_ret_preinited_mem
);
333 ATF_TC_HEAD(bpfjit_cop_ret_preinited_mem
, tc
)
335 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function that "
336 "returns a content of external pre-initialized memory word");
339 ATF_TC_BODY(bpfjit_cop_ret_preinited_mem
, tc
)
341 static struct bpf_insn insns
[] = {
342 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
344 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
346 BPF_STMT(BPF_MISC
+BPF_COP
, 0), // retM
347 BPF_STMT(BPF_RET
+BPF_A
, 0)
351 uint8_t pkt
[1] = { 0 };
352 uint32_t mem
[ctx
.extwords
];
353 void *arg
= (void*)(uintptr_t)3;
355 /* Pre-inited words. */
361 .buflen
= sizeof(pkt
),
362 .wirelen
= sizeof(pkt
),
367 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
372 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
374 ATF_REQUIRE(code
!= NULL
);
376 ATF_CHECK(code(&ctx
, &args
) == 3);
379 rumpns_bpfjit_free_code(code
);
383 ATF_TC(bpfjit_copx_ret_mem
);
384 ATF_TC_HEAD(bpfjit_copx_ret_mem
, tc
)
386 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function "
387 "that returns a content of external memory word");
390 ATF_TC_BODY(bpfjit_copx_ret_mem
, tc
)
392 static struct bpf_insn insns
[] = {
393 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
395 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
397 BPF_STMT(BPF_LDX
+BPF_IMM
, 0), // retM
398 BPF_STMT(BPF_MISC
+BPF_COPX
, 0),
399 BPF_STMT(BPF_RET
+BPF_A
, 0)
403 uint8_t pkt
[1] = { 0 };
404 uint32_t mem
[ctx
.extwords
];
405 void *arg
= (void*)(uintptr_t)2;
407 /* Pre-inited words. */
413 .buflen
= sizeof(pkt
),
414 .wirelen
= sizeof(pkt
),
419 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
424 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
426 ATF_REQUIRE(code
!= NULL
);
428 ATF_CHECK(code(&ctx
, &args
) == 13);
431 rumpns_bpfjit_free_code(code
);
435 ATF_TC(bpfjit_copx_ret_preinited_mem
);
436 ATF_TC_HEAD(bpfjit_copx_ret_preinited_mem
, tc
)
438 atf_tc_set_md_var(tc
, "descr", "Test coprocessor function that "
439 "returns a content of external pre-initialized memory word");
442 ATF_TC_BODY(bpfjit_copx_ret_preinited_mem
, tc
)
444 static struct bpf_insn insns
[] = {
445 BPF_STMT(BPF_LD
+BPF_IMM
, 13),
447 BPF_STMT(BPF_LD
+BPF_IMM
, 137),
449 BPF_STMT(BPF_LDX
+BPF_IMM
, 0), // retM
450 BPF_STMT(BPF_MISC
+BPF_COPX
, 0),
451 BPF_STMT(BPF_RET
+BPF_A
, 0)
455 uint8_t pkt
[1] = { 0 };
456 uint32_t mem
[ctx
.extwords
];
457 void *arg
= (void*)(uintptr_t)3;
459 /* Pre-inited words. */
465 .buflen
= sizeof(pkt
),
466 .wirelen
= sizeof(pkt
),
471 size_t insn_count
= sizeof(insns
) / sizeof(insns
[0]);
476 code
= rumpns_bpfjit_generate_code(&ctx
, insns
, insn_count
);
478 ATF_REQUIRE(code
!= NULL
);
480 ATF_CHECK(code(&ctx
, &args
) == 3);
483 rumpns_bpfjit_free_code(code
);
491 * For every new test please also add a similar test
492 * to ../../lib/libbpfjit/t_extmem.c
494 //ATF_TP_ADD_TC(tp, bpfjit_extmem_load_default);
495 ATF_TP_ADD_TC(tp
, bpfjit_extmem_load_preinited
);
496 ATF_TP_ADD_TC(tp
, bpfjit_extmem_invalid_load
);
497 ATF_TP_ADD_TC(tp
, bpfjit_extmem_store
);
498 ATF_TP_ADD_TC(tp
, bpfjit_extmem_side_effect
);
499 ATF_TP_ADD_TC(tp
, bpfjit_extmem_invalid_store
);
500 ATF_TP_ADD_TC(tp
, bpfjit_cop_ret_mem
);
501 ATF_TP_ADD_TC(tp
, bpfjit_cop_ret_preinited_mem
);
502 ATF_TP_ADD_TC(tp
, bpfjit_copx_ret_mem
);
503 ATF_TP_ADD_TC(tp
, bpfjit_copx_ret_preinited_mem
);
505 return atf_no_error();