bpf: add ld64 imm test cases
authorDaniel Borkmann <daniel@iogearbox.net>
Mon, 14 May 2018 21:22:34 +0000 (23:22 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 15 May 2018 02:11:45 +0000 (19:11 -0700)
Add test cases where we combine semi-random imm values, mainly for testing
JITs when they have different encoding options for 64 bit immediates in
order to reduce resulting image size.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/bpf_rand.h [new file with mode: 0644]
tools/testing/selftests/bpf/test_verifier.c

diff --git a/tools/testing/selftests/bpf/bpf_rand.h b/tools/testing/selftests/bpf/bpf_rand.h
new file mode 100644 (file)
index 0000000..59bf3e1
--- /dev/null
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __BPF_RAND__
+#define __BPF_RAND__
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+
+static inline uint64_t bpf_rand_mask(uint64_t mask)
+{
+       return (((uint64_t)(uint32_t)rand()) |
+               ((uint64_t)(uint32_t)rand() << 32)) & mask;
+}
+
+#define bpf_rand_ux(x, m)                      \
+static inline uint64_t bpf_rand_u##x(int shift)        \
+{                                              \
+       return bpf_rand_mask((m)) << shift;     \
+}
+
+bpf_rand_ux( 8,               0xffULL)
+bpf_rand_ux(16,             0xffffULL)
+bpf_rand_ux(24,           0xffffffULL)
+bpf_rand_ux(32,         0xffffffffULL)
+bpf_rand_ux(40,       0xffffffffffULL)
+bpf_rand_ux(48,     0xffffffffffffULL)
+bpf_rand_ux(56,   0xffffffffffffffULL)
+bpf_rand_ux(64, 0xffffffffffffffffULL)
+
+static inline void bpf_semi_rand_init(void)
+{
+       srand(time(NULL));
+}
+
+static inline uint64_t bpf_semi_rand_get(void)
+{
+       switch (rand() % 39) {
+       case  0: return 0x000000ff00000000ULL | bpf_rand_u8(0);
+       case  1: return 0xffffffff00000000ULL | bpf_rand_u16(0);
+       case  2: return 0x00000000ffff0000ULL | bpf_rand_u16(0);
+       case  3: return 0x8000000000000000ULL | bpf_rand_u32(0);
+       case  4: return 0x00000000f0000000ULL | bpf_rand_u32(0);
+       case  5: return 0x0000000100000000ULL | bpf_rand_u24(0);
+       case  6: return 0x800ff00000000000ULL | bpf_rand_u32(0);
+       case  7: return 0x7fffffff00000000ULL | bpf_rand_u32(0);
+       case  8: return 0xffffffffffffff00ULL ^ bpf_rand_u32(24);
+       case  9: return 0xffffffffffffff00ULL | bpf_rand_u8(0);
+       case 10: return 0x0000000010000000ULL | bpf_rand_u32(0);
+       case 11: return 0xf000000000000000ULL | bpf_rand_u8(0);
+       case 12: return 0x0000f00000000000ULL | bpf_rand_u8(8);
+       case 13: return 0x000000000f000000ULL | bpf_rand_u8(16);
+       case 14: return 0x0000000000000f00ULL | bpf_rand_u8(32);
+       case 15: return 0x00fff00000000f00ULL | bpf_rand_u8(48);
+       case 16: return 0x00007fffffffffffULL ^ bpf_rand_u32(1);
+       case 17: return 0xffff800000000000ULL | bpf_rand_u8(4);
+       case 18: return 0xffff800000000000ULL | bpf_rand_u8(20);
+       case 19: return (0xffffffc000000000ULL + 0x80000ULL) | bpf_rand_u32(0);
+       case 20: return (0xffffffc000000000ULL - 0x04000000ULL) | bpf_rand_u32(0);
+       case 21: return 0x0000000000000000ULL | bpf_rand_u8(55) | bpf_rand_u32(20);
+       case 22: return 0xffffffffffffffffULL ^ bpf_rand_u8(3) ^ bpf_rand_u32(40);
+       case 23: return 0x0000000000000000ULL | bpf_rand_u8(bpf_rand_u8(0) % 64);
+       case 24: return 0x0000000000000000ULL | bpf_rand_u16(bpf_rand_u8(0) % 64);
+       case 25: return 0xffffffffffffffffULL ^ bpf_rand_u8(bpf_rand_u8(0) % 64);
+       case 26: return 0xffffffffffffffffULL ^ bpf_rand_u40(bpf_rand_u8(0) % 64);
+       case 27: return 0x0000800000000000ULL;
+       case 28: return 0x8000000000000000ULL;
+       case 29: return 0x0000000000000000ULL;
+       case 30: return 0xffffffffffffffffULL;
+       case 31: return bpf_rand_u16(bpf_rand_u8(0) % 64);
+       case 32: return bpf_rand_u24(bpf_rand_u8(0) % 64);
+       case 33: return bpf_rand_u32(bpf_rand_u8(0) % 64);
+       case 34: return bpf_rand_u40(bpf_rand_u8(0) % 64);
+       case 35: return bpf_rand_u48(bpf_rand_u8(0) % 64);
+       case 36: return bpf_rand_u56(bpf_rand_u8(0) % 64);
+       case 37: return bpf_rand_u64(bpf_rand_u8(0) % 64);
+       default: return bpf_rand_u64(0);
+       }
+}
+
+#endif /* __BPF_RAND__ */
index 275b4570b5b81386940c5ef53b03a950d7d0c083..a877af00605d199a44c9e48226a840e4359001de 100644 (file)
@@ -41,6 +41,7 @@
 # endif
 #endif
 #include "bpf_rlimit.h"
+#include "bpf_rand.h"
 #include "../../../include/linux/filter.h"
 
 #ifndef ARRAY_SIZE
@@ -152,6 +153,30 @@ static void bpf_fill_jump_around_ld_abs(struct bpf_test *self)
        insn[i] = BPF_EXIT_INSN();
 }
 
+static void bpf_fill_rand_ld_dw(struct bpf_test *self)
+{
+       struct bpf_insn *insn = self->insns;
+       uint64_t res = 0;
+       int i = 0;
+
+       insn[i++] = BPF_MOV32_IMM(BPF_REG_0, 0);
+       while (i < self->retval) {
+               uint64_t val = bpf_semi_rand_get();
+               struct bpf_insn tmp[2] = { BPF_LD_IMM64(BPF_REG_1, val) };
+
+               res ^= val;
+               insn[i++] = tmp[0];
+               insn[i++] = tmp[1];
+               insn[i++] = BPF_ALU64_REG(BPF_XOR, BPF_REG_0, BPF_REG_1);
+       }
+       insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_0);
+       insn[i++] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_1, 32);
+       insn[i++] = BPF_ALU64_REG(BPF_XOR, BPF_REG_0, BPF_REG_1);
+       insn[i] = BPF_EXIT_INSN();
+       res ^= (res >> 32);
+       self->retval = (uint32_t)res;
+}
+
 static struct bpf_test tests[] = {
        {
                "add+sub+mul",
@@ -11974,6 +11999,42 @@ static struct bpf_test tests[] = {
                .result = ACCEPT,
                .retval = 10,
        },
+       {
+               "ld_dw: xor semi-random 64 bit imms, test 1",
+               .insns = { },
+               .data = { },
+               .fill_helper = bpf_fill_rand_ld_dw,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .result = ACCEPT,
+               .retval = 4090,
+       },
+       {
+               "ld_dw: xor semi-random 64 bit imms, test 2",
+               .insns = { },
+               .data = { },
+               .fill_helper = bpf_fill_rand_ld_dw,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .result = ACCEPT,
+               .retval = 2047,
+       },
+       {
+               "ld_dw: xor semi-random 64 bit imms, test 3",
+               .insns = { },
+               .data = { },
+               .fill_helper = bpf_fill_rand_ld_dw,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .result = ACCEPT,
+               .retval = 511,
+       },
+       {
+               "ld_dw: xor semi-random 64 bit imms, test 4",
+               .insns = { },
+               .data = { },
+               .fill_helper = bpf_fill_rand_ld_dw,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .result = ACCEPT,
+               .retval = 5,
+       },
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)
@@ -12346,5 +12407,6 @@ int main(int argc, char **argv)
                return EXIT_FAILURE;
        }
 
+       bpf_semi_rand_init();
        return do_test(unpriv, from, to);
 }