perf test: Fix bpf test sample mismatch reporting
[linux-2.6-microblaze.git] / lib / test_bpf.c
index d500320..830a18e 100644 (file)
@@ -461,6 +461,41 @@ static int bpf_fill_stxdw(struct bpf_test *self)
        return __bpf_fill_stxdw(self, BPF_DW);
 }
 
+static int bpf_fill_long_jmp(struct bpf_test *self)
+{
+       unsigned int len = BPF_MAXINSNS;
+       struct bpf_insn *insn;
+       int i;
+
+       insn = kmalloc_array(len, sizeof(*insn), GFP_KERNEL);
+       if (!insn)
+               return -ENOMEM;
+
+       insn[0] = BPF_ALU64_IMM(BPF_MOV, R0, 1);
+       insn[1] = BPF_JMP_IMM(BPF_JEQ, R0, 1, len - 2 - 1);
+
+       /*
+        * Fill with a complex 64-bit operation that expands to a lot of
+        * instructions on 32-bit JITs. The large jump offset can then
+        * overflow the conditional branch field size, triggering a branch
+        * conversion mechanism in some JITs.
+        *
+        * Note: BPF_MAXINSNS of ALU64 MUL is enough to trigger such branch
+        * conversion on the 32-bit MIPS JIT. For other JITs, the instruction
+        * count and/or operation may need to be modified to trigger the
+        * branch conversion.
+        */
+       for (i = 2; i < len - 1; i++)
+               insn[i] = BPF_ALU64_IMM(BPF_MUL, R0, (i << 16) + i);
+
+       insn[len - 1] = BPF_EXIT_INSN();
+
+       self->u.ptr.insns = insn;
+       self->u.ptr.len = len;
+
+       return 0;
+}
+
 static struct bpf_test tests[] = {
        {
                "TAX",
@@ -1916,6 +1951,163 @@ static struct bpf_test tests[] = {
                { },
                { { 0, -1 } }
        },
+       {
+               /*
+                * Register (non-)clobbering test, in the case where a 32-bit
+                * JIT implements complex ALU64 operations via function calls.
+                * If so, the function call must be invisible in the eBPF
+                * registers. The JIT must then save and restore relevant
+                * registers during the call. The following tests check that
+                * the eBPF registers retain their values after such a call.
+                */
+               "INT: Register clobbering, R1 updated",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 123456789),
+                       BPF_ALU32_IMM(BPF_MOV, R2, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R3, 3),
+                       BPF_ALU32_IMM(BPF_MOV, R4, 4),
+                       BPF_ALU32_IMM(BPF_MOV, R5, 5),
+                       BPF_ALU32_IMM(BPF_MOV, R6, 6),
+                       BPF_ALU32_IMM(BPF_MOV, R7, 7),
+                       BPF_ALU32_IMM(BPF_MOV, R8, 8),
+                       BPF_ALU32_IMM(BPF_MOV, R9, 9),
+                       BPF_ALU64_IMM(BPF_DIV, R1, 123456789),
+                       BPF_JMP_IMM(BPF_JNE, R0, 0, 10),
+                       BPF_JMP_IMM(BPF_JNE, R1, 1, 9),
+                       BPF_JMP_IMM(BPF_JNE, R2, 2, 8),
+                       BPF_JMP_IMM(BPF_JNE, R3, 3, 7),
+                       BPF_JMP_IMM(BPF_JNE, R4, 4, 6),
+                       BPF_JMP_IMM(BPF_JNE, R5, 5, 5),
+                       BPF_JMP_IMM(BPF_JNE, R6, 6, 4),
+                       BPF_JMP_IMM(BPF_JNE, R7, 7, 3),
+                       BPF_JMP_IMM(BPF_JNE, R8, 8, 2),
+                       BPF_JMP_IMM(BPF_JNE, R9, 9, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+       {
+               "INT: Register clobbering, R2 updated",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R2, 2 * 123456789),
+                       BPF_ALU32_IMM(BPF_MOV, R3, 3),
+                       BPF_ALU32_IMM(BPF_MOV, R4, 4),
+                       BPF_ALU32_IMM(BPF_MOV, R5, 5),
+                       BPF_ALU32_IMM(BPF_MOV, R6, 6),
+                       BPF_ALU32_IMM(BPF_MOV, R7, 7),
+                       BPF_ALU32_IMM(BPF_MOV, R8, 8),
+                       BPF_ALU32_IMM(BPF_MOV, R9, 9),
+                       BPF_ALU64_IMM(BPF_DIV, R2, 123456789),
+                       BPF_JMP_IMM(BPF_JNE, R0, 0, 10),
+                       BPF_JMP_IMM(BPF_JNE, R1, 1, 9),
+                       BPF_JMP_IMM(BPF_JNE, R2, 2, 8),
+                       BPF_JMP_IMM(BPF_JNE, R3, 3, 7),
+                       BPF_JMP_IMM(BPF_JNE, R4, 4, 6),
+                       BPF_JMP_IMM(BPF_JNE, R5, 5, 5),
+                       BPF_JMP_IMM(BPF_JNE, R6, 6, 4),
+                       BPF_JMP_IMM(BPF_JNE, R7, 7, 3),
+                       BPF_JMP_IMM(BPF_JNE, R8, 8, 2),
+                       BPF_JMP_IMM(BPF_JNE, R9, 9, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+       {
+               /*
+                * Test 32-bit JITs that implement complex ALU64 operations as
+                * function calls R0 = f(R1, R2), and must re-arrange operands.
+                */
+#define NUMER 0xfedcba9876543210ULL
+#define DENOM 0x0123456789abcdefULL
+               "ALU64_DIV X: Operand register permutations",
+               .u.insns_int = {
+                       /* R0 / R2 */
+                       BPF_LD_IMM64(R0, NUMER),
+                       BPF_LD_IMM64(R2, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R0, R2),
+                       BPF_JMP_IMM(BPF_JEQ, R0, NUMER / DENOM, 1),
+                       BPF_EXIT_INSN(),
+                       /* R1 / R0 */
+                       BPF_LD_IMM64(R1, NUMER),
+                       BPF_LD_IMM64(R0, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R1, R0),
+                       BPF_JMP_IMM(BPF_JEQ, R1, NUMER / DENOM, 1),
+                       BPF_EXIT_INSN(),
+                       /* R0 / R1 */
+                       BPF_LD_IMM64(R0, NUMER),
+                       BPF_LD_IMM64(R1, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R0, R1),
+                       BPF_JMP_IMM(BPF_JEQ, R0, NUMER / DENOM, 1),
+                       BPF_EXIT_INSN(),
+                       /* R2 / R0 */
+                       BPF_LD_IMM64(R2, NUMER),
+                       BPF_LD_IMM64(R0, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R2, R0),
+                       BPF_JMP_IMM(BPF_JEQ, R2, NUMER / DENOM, 1),
+                       BPF_EXIT_INSN(),
+                       /* R2 / R1 */
+                       BPF_LD_IMM64(R2, NUMER),
+                       BPF_LD_IMM64(R1, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R2, R1),
+                       BPF_JMP_IMM(BPF_JEQ, R2, NUMER / DENOM, 1),
+                       BPF_EXIT_INSN(),
+                       /* R1 / R2 */
+                       BPF_LD_IMM64(R1, NUMER),
+                       BPF_LD_IMM64(R2, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R1, R2),
+                       BPF_JMP_IMM(BPF_JEQ, R1, NUMER / DENOM, 1),
+                       BPF_EXIT_INSN(),
+                       /* R1 / R1 */
+                       BPF_LD_IMM64(R1, NUMER),
+                       BPF_ALU64_REG(BPF_DIV, R1, R1),
+                       BPF_JMP_IMM(BPF_JEQ, R1, 1, 1),
+                       BPF_EXIT_INSN(),
+                       /* R2 / R2 */
+                       BPF_LD_IMM64(R2, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R2, R2),
+                       BPF_JMP_IMM(BPF_JEQ, R2, 1, 1),
+                       BPF_EXIT_INSN(),
+                       /* R3 / R4 */
+                       BPF_LD_IMM64(R3, NUMER),
+                       BPF_LD_IMM64(R4, DENOM),
+                       BPF_ALU64_REG(BPF_DIV, R3, R4),
+                       BPF_JMP_IMM(BPF_JEQ, R3, NUMER / DENOM, 1),
+                       BPF_EXIT_INSN(),
+                       /* Successful return */
+                       BPF_LD_IMM64(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+#undef NUMER
+#undef DENOM
+       },
+#ifdef CONFIG_32BIT
+       {
+               "INT: 32-bit context pointer word order and zero-extension",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_JMP32_IMM(BPF_JEQ, R1, 0, 3),
+                       BPF_ALU64_IMM(BPF_RSH, R1, 32),
+                       BPF_JMP32_IMM(BPF_JNE, R1, 0, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+#endif
        {
                "check: missing ret",
                .u.insns = {
@@ -2360,6 +2552,48 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x1 } },
        },
+       {
+               "ALU_MOV_K: small negative",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -123 } }
+       },
+       {
+               "ALU_MOV_K: small negative zero extension",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } }
+       },
+       {
+               "ALU_MOV_K: large negative",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123456789),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -123456789 } }
+       },
+       {
+               "ALU_MOV_K: large negative zero extension",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123456789),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } }
+       },
        {
                "ALU64_MOV_K: dst = 2",
                .u.insns_int = {
@@ -2412,6 +2646,48 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x1 } },
        },
+       {
+               "ALU64_MOV_K: small negative",
+               .u.insns_int = {
+                       BPF_ALU64_IMM(BPF_MOV, R0, -123),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -123 } }
+       },
+       {
+               "ALU64_MOV_K: small negative sign extension",
+               .u.insns_int = {
+                       BPF_ALU64_IMM(BPF_MOV, R0, -123),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffffffff } }
+       },
+       {
+               "ALU64_MOV_K: large negative",
+               .u.insns_int = {
+                       BPF_ALU64_IMM(BPF_MOV, R0, -123456789),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -123456789 } }
+       },
+       {
+               "ALU64_MOV_K: large negative sign extension",
+               .u.insns_int = {
+                       BPF_ALU64_IMM(BPF_MOV, R0, -123456789),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffffffff } }
+       },
        /* BPF_ALU | BPF_ADD | BPF_X */
        {
                "ALU_ADD_X: 1 + 2 = 3",
@@ -2967,6 +3243,31 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 2147483647 } },
        },
+       {
+               "ALU64_MUL_X: 64x64 multiply, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0fedcba987654321LL),
+                       BPF_LD_IMM64(R1, 0x123456789abcdef0LL),
+                       BPF_ALU64_REG(BPF_MUL, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xe5618cf0 } }
+       },
+       {
+               "ALU64_MUL_X: 64x64 multiply, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0fedcba987654321LL),
+                       BPF_LD_IMM64(R1, 0x123456789abcdef0LL),
+                       BPF_ALU64_REG(BPF_MUL, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x2236d88f } }
+       },
        /* BPF_ALU | BPF_MUL | BPF_K */
        {
                "ALU_MUL_K: 2 * 3 = 6",
@@ -3077,6 +3378,29 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x1 } },
        },
+       {
+               "ALU64_MUL_K: 64x32 multiply, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_MUL, R0, 0x12345678),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xe242d208 } }
+       },
+       {
+               "ALU64_MUL_K: 64x32 multiply, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_MUL, R0, 0x12345678),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xc28f5c28 } }
+       },
        /* BPF_ALU | BPF_DIV | BPF_X */
        {
                "ALU_DIV_X: 6 / 2 = 3",
@@ -3430,6 +3754,44 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0xffffffff } },
        },
+       {
+               "ALU_AND_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x01020304),
+                       BPF_ALU32_IMM(BPF_AND, R0, 15),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 4 } }
+       },
+       {
+               "ALU_AND_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xf1f2f3f4),
+                       BPF_ALU32_IMM(BPF_AND, R0, 0xafbfcfdf),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xa1b2c3d4 } }
+       },
+       {
+               "ALU_AND_K: Zero extension",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0x0000000080a0c0e0LL),
+                       BPF_ALU32_IMM(BPF_AND, R0, 0xf0f0f0f0),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
        {
                "ALU64_AND_K: 3 & 2 = 2",
                .u.insns_int = {
@@ -3453,7 +3815,7 @@ static struct bpf_test tests[] = {
                { { 0, 0xffffffff } },
        },
        {
-               "ALU64_AND_K: 0x0000ffffffff0000 & 0x0 = 0x0000ffff00000000",
+               "ALU64_AND_K: 0x0000ffffffff0000 & 0x0 = 0x0000000000000000",
                .u.insns_int = {
                        BPF_LD_IMM64(R2, 0x0000ffffffff0000LL),
                        BPF_LD_IMM64(R3, 0x0000000000000000LL),
@@ -3469,7 +3831,7 @@ static struct bpf_test tests[] = {
                { { 0, 0x1 } },
        },
        {
-               "ALU64_AND_K: 0x0000ffffffff0000 & -1 = 0x0000ffffffffffff",
+               "ALU64_AND_K: 0x0000ffffffff0000 & -1 = 0x0000ffffffff0000",
                .u.insns_int = {
                        BPF_LD_IMM64(R2, 0x0000ffffffff0000LL),
                        BPF_LD_IMM64(R3, 0x0000ffffffff0000LL),
@@ -3500,6 +3862,38 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x1 } },
        },
+       {
+               "ALU64_AND_K: Sign extension 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0x00000000090b0d0fLL),
+                       BPF_ALU64_IMM(BPF_AND, R0, 0x0f0f0f0f),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+       {
+               "ALU64_AND_K: Sign extension 2",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0x0123456780a0c0e0LL),
+                       BPF_ALU64_IMM(BPF_AND, R0, 0xf0f0f0f0),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
        /* BPF_ALU | BPF_OR | BPF_X */
        {
                "ALU_OR_X: 1 | 2 = 3",
@@ -3572,6 +3966,44 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0xffffffff } },
        },
+       {
+               "ALU_OR_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x01020304),
+                       BPF_ALU32_IMM(BPF_OR, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x01020305 } }
+       },
+       {
+               "ALU_OR_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x01020304),
+                       BPF_ALU32_IMM(BPF_OR, R0, 0xa0b0c0d0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xa1b2c3d4 } }
+       },
+       {
+               "ALU_OR_K: Zero extension",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0x00000000f9fbfdffLL),
+                       BPF_ALU32_IMM(BPF_OR, R0, 0xf0f0f0f0),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
        {
                "ALU64_OR_K: 1 | 2 = 3",
                .u.insns_int = {
@@ -3595,7 +4027,7 @@ static struct bpf_test tests[] = {
                { { 0, 0xffffffff } },
        },
        {
-               "ALU64_OR_K: 0x0000ffffffff0000 | 0x0 = 0x0000ffff00000000",
+               "ALU64_OR_K: 0x0000ffffffff0000 | 0x0 = 0x0000ffffffff0000",
                .u.insns_int = {
                        BPF_LD_IMM64(R2, 0x0000ffffffff0000LL),
                        BPF_LD_IMM64(R3, 0x0000ffffffff0000LL),
@@ -3642,9 +4074,41 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x1 } },
        },
-       /* BPF_ALU | BPF_XOR | BPF_X */
        {
-               "ALU_XOR_X: 5 ^ 6 = 3",
+               "ALU64_OR_K: Sign extension 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0x012345678fafcfefLL),
+                       BPF_ALU64_IMM(BPF_OR, R0, 0x0f0f0f0f),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+       {
+               "ALU64_OR_K: Sign extension 2",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0xfffffffff9fbfdffLL),
+                       BPF_ALU64_IMM(BPF_OR, R0, 0xf0f0f0f0),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+       /* BPF_ALU | BPF_XOR | BPF_X */
+       {
+               "ALU_XOR_X: 5 ^ 6 = 3",
                .u.insns_int = {
                        BPF_LD_IMM64(R0, 5),
                        BPF_ALU32_IMM(BPF_MOV, R1, 6),
@@ -3714,6 +4178,44 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0xfffffffe } },
        },
+       {
+               "ALU_XOR_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x01020304),
+                       BPF_ALU32_IMM(BPF_XOR, R0, 15),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x0102030b } }
+       },
+       {
+               "ALU_XOR_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xf1f2f3f4),
+                       BPF_ALU32_IMM(BPF_XOR, R0, 0xafbfcfdf),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x5e4d3c2b } }
+       },
+       {
+               "ALU_XOR_K: Zero extension",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0x00000000795b3d1fLL),
+                       BPF_ALU32_IMM(BPF_XOR, R0, 0xf0f0f0f0),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
        {
                "ALU64_XOR_K: 5 ^ 6 = 3",
                .u.insns_int = {
@@ -3726,7 +4228,7 @@ static struct bpf_test tests[] = {
                { { 0, 3 } },
        },
        {
-               "ALU64_XOR_K: 1 & 0xffffffff = 0xfffffffe",
+               "ALU64_XOR_K: 1 ^ 0xffffffff = 0xfffffffe",
                .u.insns_int = {
                        BPF_LD_IMM64(R0, 1),
                        BPF_ALU64_IMM(BPF_XOR, R0, 0xffffffff),
@@ -3784,6 +4286,38 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x1 } },
        },
+       {
+               "ALU64_XOR_K: Sign extension 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0x0123456786a4c2e0LL),
+                       BPF_ALU64_IMM(BPF_XOR, R0, 0x0f0f0f0f),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+       {
+               "ALU64_XOR_K: Sign extension 2",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_LD_IMM64(R1, 0xfedcba98795b3d1fLL),
+                       BPF_ALU64_IMM(BPF_XOR, R0, 0xf0f0f0f0),
+                       BPF_JMP_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
        /* BPF_ALU | BPF_LSH | BPF_X */
        {
                "ALU_LSH_X: 1 << 1 = 2",
@@ -3809,6 +4343,18 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x80000000 } },
        },
+       {
+               "ALU_LSH_X: 0x12345678 << 12 = 0x45678000",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12345678),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 12),
+                       BPF_ALU32_REG(BPF_LSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x45678000 } }
+       },
        {
                "ALU64_LSH_X: 1 << 1 = 2",
                .u.insns_int = {
@@ -3833,570 +4379,1993 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 0x80000000 } },
        },
-       /* BPF_ALU | BPF_LSH | BPF_K */
        {
-               "ALU_LSH_K: 1 << 1 = 2",
+               "ALU64_LSH_X: Shift < 32, low word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 1),
-                       BPF_ALU32_IMM(BPF_LSH, R0, 1),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 12),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 2 } },
+               { { 0, 0xbcdef000 } }
        },
        {
-               "ALU_LSH_K: 1 << 31 = 0x80000000",
+               "ALU64_LSH_X: Shift < 32, high word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 1),
-                       BPF_ALU32_IMM(BPF_LSH, R0, 31),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 12),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x80000000 } },
+               { { 0, 0x3456789a } }
        },
        {
-               "ALU64_LSH_K: 1 << 1 = 2",
+               "ALU64_LSH_X: Shift > 32, low word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 1),
-                       BPF_ALU64_IMM(BPF_LSH, R0, 1),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 36),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 2 } },
+               { { 0, 0 } }
        },
        {
-               "ALU64_LSH_K: 1 << 31 = 0x80000000",
+               "ALU64_LSH_X: Shift > 32, high word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 1),
-                       BPF_ALU64_IMM(BPF_LSH, R0, 31),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 36),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x80000000 } },
+               { { 0, 0x9abcdef0 } }
        },
-       /* BPF_ALU | BPF_RSH | BPF_X */
        {
-               "ALU_RSH_X: 2 >> 1 = 1",
+               "ALU64_LSH_X: Shift == 32, low word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 2),
-                       BPF_ALU32_IMM(BPF_MOV, R1, 1),
-                       BPF_ALU32_REG(BPF_RSH, R0, R1),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 32),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 0 } }
        },
        {
-               "ALU_RSH_X: 0x80000000 >> 31 = 1",
+               "ALU64_LSH_X: Shift == 32, high word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0x80000000),
-                       BPF_ALU32_IMM(BPF_MOV, R1, 31),
-                       BPF_ALU32_REG(BPF_RSH, R0, R1),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 32),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 0x89abcdef } }
        },
        {
-               "ALU64_RSH_X: 2 >> 1 = 1",
+               "ALU64_LSH_X: Zero shift, low word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 2),
-                       BPF_ALU32_IMM(BPF_MOV, R1, 1),
-                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 0x89abcdef } }
        },
        {
-               "ALU64_RSH_X: 0x80000000 >> 31 = 1",
+               "ALU64_LSH_X: Zero shift, high word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0x80000000),
-                       BPF_ALU32_IMM(BPF_MOV, R1, 31),
-                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0),
+                       BPF_ALU64_REG(BPF_LSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 0x01234567 } }
        },
-       /* BPF_ALU | BPF_RSH | BPF_K */
+       /* BPF_ALU | BPF_LSH | BPF_K */
        {
-               "ALU_RSH_K: 2 >> 1 = 1",
+               "ALU_LSH_K: 1 << 1 = 2",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 2),
-                       BPF_ALU32_IMM(BPF_RSH, R0, 1),
+                       BPF_LD_IMM64(R0, 1),
+                       BPF_ALU32_IMM(BPF_LSH, R0, 1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 2 } },
        },
        {
-               "ALU_RSH_K: 0x80000000 >> 31 = 1",
+               "ALU_LSH_K: 1 << 31 = 0x80000000",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0x80000000),
-                       BPF_ALU32_IMM(BPF_RSH, R0, 31),
+                       BPF_LD_IMM64(R0, 1),
+                       BPF_ALU32_IMM(BPF_LSH, R0, 31),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 0x80000000 } },
        },
        {
-               "ALU64_RSH_K: 2 >> 1 = 1",
+               "ALU_LSH_K: 0x12345678 << 12 = 0x45678000",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 2),
-                       BPF_ALU64_IMM(BPF_RSH, R0, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12345678),
+                       BPF_ALU32_IMM(BPF_LSH, R0, 12),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 0x45678000 } }
        },
        {
-               "ALU64_RSH_K: 0x80000000 >> 31 = 1",
+               "ALU_LSH_K: 0x12345678 << 0 = 0x12345678",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0x80000000),
-                       BPF_ALU64_IMM(BPF_RSH, R0, 31),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12345678),
+                       BPF_ALU32_IMM(BPF_LSH, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 1 } },
+               { { 0, 0x12345678 } }
        },
-       /* BPF_ALU | BPF_ARSH | BPF_X */
        {
-               "ALU_ARSH_X: 0xff00ff0000000000 >> 40 = 0xffffffffffff00ff",
+               "ALU64_LSH_K: 1 << 1 = 2",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0xff00ff0000000000LL),
-                       BPF_ALU32_IMM(BPF_MOV, R1, 40),
-                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_LD_IMM64(R0, 1),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffff00ff } },
+               { { 0, 2 } },
        },
-       /* BPF_ALU | BPF_ARSH | BPF_K */
        {
-               "ALU_ARSH_K: 0xff00ff0000000000 >> 40 = 0xffffffffffff00ff",
+               "ALU64_LSH_K: 1 << 31 = 0x80000000",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0xff00ff0000000000LL),
-                       BPF_ALU64_IMM(BPF_ARSH, R0, 40),
+                       BPF_LD_IMM64(R0, 1),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 31),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffff00ff } },
+               { { 0, 0x80000000 } },
        },
-       /* BPF_ALU | BPF_NEG */
        {
-               "ALU_NEG: -(3) = -3",
+               "ALU64_LSH_K: Shift < 32, low word",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 3),
-                       BPF_ALU32_IMM(BPF_NEG, R0, 0),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 12),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, -3 } },
+               { { 0, 0xbcdef000 } }
        },
        {
-               "ALU_NEG: -(-3) = 3",
+               "ALU64_LSH_K: Shift < 32, high word",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, -3),
-                       BPF_ALU32_IMM(BPF_NEG, R0, 0),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 12),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 3 } },
+               { { 0, 0x3456789a } }
        },
        {
-               "ALU64_NEG: -(3) = -3",
+               "ALU64_LSH_K: Shift > 32, low word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 3),
-                       BPF_ALU64_IMM(BPF_NEG, R0, 0),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 36),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, -3 } },
+               { { 0, 0 } }
        },
        {
-               "ALU64_NEG: -(-3) = 3",
+               "ALU64_LSH_K: Shift > 32, high word",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, -3),
-                       BPF_ALU64_IMM(BPF_NEG, R0, 0),
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 36),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 3 } },
+               { { 0, 0x9abcdef0 } }
        },
-       /* BPF_ALU | BPF_END | BPF_FROM_BE */
        {
-               "ALU_END_FROM_BE 16: 0x0123456789abcdef -> 0xcdef",
+               "ALU64_LSH_K: Shift == 32, low word",
                .u.insns_int = {
                        BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
-                       BPF_ENDIAN(BPF_FROM_BE, R0, 16),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0,  cpu_to_be16(0xcdef) } },
+               { { 0, 0 } }
        },
        {
-               "ALU_END_FROM_BE 32: 0x0123456789abcdef -> 0x89abcdef",
+               "ALU64_LSH_K: Shift == 32, high word",
                .u.insns_int = {
                        BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
-                       BPF_ENDIAN(BPF_FROM_BE, R0, 32),
-                       BPF_ALU64_REG(BPF_MOV, R1, R0),
-                       BPF_ALU64_IMM(BPF_RSH, R1, 32),
-                       BPF_ALU32_REG(BPF_ADD, R0, R1), /* R1 = 0 */
+                       BPF_ALU64_IMM(BPF_LSH, R0, 32),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, cpu_to_be32(0x89abcdef) } },
+               { { 0, 0x89abcdef } }
        },
        {
-               "ALU_END_FROM_BE 64: 0x0123456789abcdef -> 0x89abcdef",
+               "ALU64_LSH_K: Zero shift",
                .u.insns_int = {
                        BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
-                       BPF_ENDIAN(BPF_FROM_BE, R0, 64),
+                       BPF_ALU64_IMM(BPF_LSH, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, (u32) cpu_to_be64(0x0123456789abcdefLL) } },
+               { { 0, 0x89abcdef } }
        },
-       /* BPF_ALU | BPF_END | BPF_FROM_LE */
+       /* BPF_ALU | BPF_RSH | BPF_X */
        {
-               "ALU_END_FROM_LE 16: 0x0123456789abcdef -> 0xefcd",
+               "ALU_RSH_X: 2 >> 1 = 1",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
-                       BPF_ENDIAN(BPF_FROM_LE, R0, 16),
+                       BPF_LD_IMM64(R0, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 1),
+                       BPF_ALU32_REG(BPF_RSH, R0, R1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, cpu_to_le16(0xcdef) } },
+               { { 0, 1 } },
        },
        {
-               "ALU_END_FROM_LE 32: 0x0123456789abcdef -> 0xefcdab89",
+               "ALU_RSH_X: 0x80000000 >> 31 = 1",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
-                       BPF_ENDIAN(BPF_FROM_LE, R0, 32),
-                       BPF_ALU64_REG(BPF_MOV, R1, R0),
-                       BPF_ALU64_IMM(BPF_RSH, R1, 32),
-                       BPF_ALU32_REG(BPF_ADD, R0, R1), /* R1 = 0 */
+                       BPF_LD_IMM64(R0, 0x80000000),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 31),
+                       BPF_ALU32_REG(BPF_RSH, R0, R1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, cpu_to_le32(0x89abcdef) } },
+               { { 0, 1 } },
        },
        {
-               "ALU_END_FROM_LE 64: 0x0123456789abcdef -> 0x67452301",
+               "ALU_RSH_X: 0x12345678 >> 20 = 0x123",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
-                       BPF_ENDIAN(BPF_FROM_LE, R0, 64),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12345678),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 20),
+                       BPF_ALU32_REG(BPF_RSH, R0, R1),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, (u32) cpu_to_le64(0x0123456789abcdefLL) } },
+               { { 0, 0x123 } }
        },
-       /* BPF_ST(X) | BPF_MEM | BPF_B/H/W/DW */
        {
-               "ST_MEM_B: Store/Load byte: max negative",
+               "ALU64_RSH_X: 2 >> 1 = 1",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_B, R10, -40, 0xff),
-                       BPF_LDX_MEM(BPF_B, R0, R10, -40),
+                       BPF_LD_IMM64(R0, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 1),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
+       {
+               "ALU64_RSH_X: 0x80000000 >> 31 = 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x80000000),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 31),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
+       {
+               "ALU64_RSH_X: Shift < 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 12),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x56789abc } }
+       },
+       {
+               "ALU64_RSH_X: Shift < 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 12),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x00081234 } }
+       },
+       {
+               "ALU64_RSH_X: Shift > 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 36),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x08123456 } }
+       },
+       {
+               "ALU64_RSH_X: Shift > 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 36),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } }
+       },
+       {
+               "ALU64_RSH_X: Shift == 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 32),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x81234567 } }
+       },
+       {
+               "ALU64_RSH_X: Shift == 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 32),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } }
+       },
+       {
+               "ALU64_RSH_X: Zero shift, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x89abcdef } }
+       },
+       {
+               "ALU64_RSH_X: Zero shift, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0),
+                       BPF_ALU64_REG(BPF_RSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x81234567 } }
+       },
+       /* BPF_ALU | BPF_RSH | BPF_K */
+       {
+               "ALU_RSH_K: 2 >> 1 = 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 2),
+                       BPF_ALU32_IMM(BPF_RSH, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
+       {
+               "ALU_RSH_K: 0x80000000 >> 31 = 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x80000000),
+                       BPF_ALU32_IMM(BPF_RSH, R0, 31),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
+       {
+               "ALU_RSH_K: 0x12345678 >> 20 = 0x123",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12345678),
+                       BPF_ALU32_IMM(BPF_RSH, R0, 20),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x123 } }
+       },
+       {
+               "ALU_RSH_K: 0x12345678 >> 0 = 0x12345678",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12345678),
+                       BPF_ALU32_IMM(BPF_RSH, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x12345678 } }
+       },
+       {
+               "ALU64_RSH_K: 2 >> 1 = 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 2),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
+       {
+               "ALU64_RSH_K: 0x80000000 >> 31 = 1",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x80000000),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 31),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
+       {
+               "ALU64_RSH_K: Shift < 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 12),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x56789abc } }
+       },
+       {
+               "ALU64_RSH_K: Shift < 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 12),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x00081234 } }
+       },
+       {
+               "ALU64_RSH_K: Shift > 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 36),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x08123456 } }
+       },
+       {
+               "ALU64_RSH_K: Shift > 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 36),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } }
+       },
+       {
+               "ALU64_RSH_K: Shift == 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x81234567 } }
+       },
+       {
+               "ALU64_RSH_K: Shift == 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } }
+       },
+       {
+               "ALU64_RSH_K: Zero shift",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x89abcdef } }
+       },
+       /* BPF_ALU | BPF_ARSH | BPF_X */
+       {
+               "ALU32_ARSH_X: -1234 >> 7 = -10",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -1234),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 7),
+                       BPF_ALU32_REG(BPF_ARSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -10 } }
+       },
+       {
+               "ALU64_ARSH_X: 0xff00ff0000000000 >> 40 = 0xffffffffffff00ff",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0xff00ff0000000000LL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 40),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffff00ff } },
+       },
+       {
+               "ALU64_ARSH_X: Shift < 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 12),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x56789abc } }
+       },
+       {
+               "ALU64_ARSH_X: Shift < 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 12),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xfff81234 } }
+       },
+       {
+               "ALU64_ARSH_X: Shift > 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 36),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xf8123456 } }
+       },
+       {
+               "ALU64_ARSH_X: Shift > 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 36),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -1 } }
+       },
+       {
+               "ALU64_ARSH_X: Shift == 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 32),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x81234567 } }
+       },
+       {
+               "ALU64_ARSH_X: Shift == 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 32),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -1 } }
+       },
+       {
+               "ALU64_ARSH_X: Zero shift, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x89abcdef } }
+       },
+       {
+               "ALU64_ARSH_X: Zero shift, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0),
+                       BPF_ALU64_REG(BPF_ARSH, R0, R1),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x81234567 } }
+       },
+       /* BPF_ALU | BPF_ARSH | BPF_K */
+       {
+               "ALU32_ARSH_K: -1234 >> 7 = -10",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -1234),
+                       BPF_ALU32_IMM(BPF_ARSH, R0, 7),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -10 } }
+       },
+       {
+               "ALU32_ARSH_K: -1234 >> 0 = -1234",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -1234),
+                       BPF_ALU32_IMM(BPF_ARSH, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -1234 } }
+       },
+       {
+               "ALU64_ARSH_K: 0xff00ff0000000000 >> 40 = 0xffffffffffff00ff",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0xff00ff0000000000LL),
+                       BPF_ALU64_IMM(BPF_ARSH, R0, 40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffff00ff } },
+       },
+       {
+               "ALU64_ARSH_K: Shift < 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 12),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x56789abc } }
+       },
+       {
+               "ALU64_ARSH_K: Shift < 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_ARSH, R0, 12),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xfff81234 } }
+       },
+       {
+               "ALU64_ARSH_K: Shift > 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_ARSH, R0, 36),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xf8123456 } }
+       },
+       {
+               "ALU64_ARSH_K: Shift > 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0xf123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_ARSH, R0, 36),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -1 } }
+       },
+       {
+               "ALU64_ARSH_K: Shift == 32, low word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_ARSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x81234567 } }
+       },
+       {
+               "ALU64_ARSH_K: Shift == 32, high word",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_ARSH, R0, 32),
+                       BPF_ALU64_IMM(BPF_RSH, R0, 32),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -1 } }
+       },
+       {
+               "ALU64_ARSH_K: Zero shift",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x8123456789abcdefLL),
+                       BPF_ALU64_IMM(BPF_ARSH, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x89abcdef } }
+       },
+       /* BPF_ALU | BPF_NEG */
+       {
+               "ALU_NEG: -(3) = -3",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 3),
+                       BPF_ALU32_IMM(BPF_NEG, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -3 } },
+       },
+       {
+               "ALU_NEG: -(-3) = 3",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -3),
+                       BPF_ALU32_IMM(BPF_NEG, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 3 } },
+       },
+       {
+               "ALU64_NEG: -(3) = -3",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 3),
+                       BPF_ALU64_IMM(BPF_NEG, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -3 } },
+       },
+       {
+               "ALU64_NEG: -(-3) = 3",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, -3),
+                       BPF_ALU64_IMM(BPF_NEG, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 3 } },
+       },
+       /* BPF_ALU | BPF_END | BPF_FROM_BE */
+       {
+               "ALU_END_FROM_BE 16: 0x0123456789abcdef -> 0xcdef",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ENDIAN(BPF_FROM_BE, R0, 16),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0,  cpu_to_be16(0xcdef) } },
+       },
+       {
+               "ALU_END_FROM_BE 32: 0x0123456789abcdef -> 0x89abcdef",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ENDIAN(BPF_FROM_BE, R0, 32),
+                       BPF_ALU64_REG(BPF_MOV, R1, R0),
+                       BPF_ALU64_IMM(BPF_RSH, R1, 32),
+                       BPF_ALU32_REG(BPF_ADD, R0, R1), /* R1 = 0 */
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, cpu_to_be32(0x89abcdef) } },
+       },
+       {
+               "ALU_END_FROM_BE 64: 0x0123456789abcdef -> 0x89abcdef",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ENDIAN(BPF_FROM_BE, R0, 64),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, (u32) cpu_to_be64(0x0123456789abcdefLL) } },
+       },
+       /* BPF_ALU | BPF_END | BPF_FROM_LE */
+       {
+               "ALU_END_FROM_LE 16: 0x0123456789abcdef -> 0xefcd",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ENDIAN(BPF_FROM_LE, R0, 16),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, cpu_to_le16(0xcdef) } },
+       },
+       {
+               "ALU_END_FROM_LE 32: 0x0123456789abcdef -> 0xefcdab89",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ENDIAN(BPF_FROM_LE, R0, 32),
+                       BPF_ALU64_REG(BPF_MOV, R1, R0),
+                       BPF_ALU64_IMM(BPF_RSH, R1, 32),
+                       BPF_ALU32_REG(BPF_ADD, R0, R1), /* R1 = 0 */
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, cpu_to_le32(0x89abcdef) } },
+       },
+       {
+               "ALU_END_FROM_LE 64: 0x0123456789abcdef -> 0x67452301",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0x0123456789abcdefLL),
+                       BPF_ENDIAN(BPF_FROM_LE, R0, 64),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, (u32) cpu_to_le64(0x0123456789abcdefLL) } },
+       },
+       /* BPF_ST(X) | BPF_MEM | BPF_B/H/W/DW */
+       {
+               "ST_MEM_B: Store/Load byte: max negative",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_B, R10, -40, 0xff),
+                       BPF_LDX_MEM(BPF_B, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xff } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_B: Store/Load byte: max positive",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_H, R10, -40, 0x7f),
+                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x7f } },
+               .stack_depth = 40,
+       },
+       {
+               "STX_MEM_B: Store/Load byte: max negative",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0),
+                       BPF_LD_IMM64(R1, 0xffLL),
+                       BPF_STX_MEM(BPF_B, R10, R1, -40),
+                       BPF_LDX_MEM(BPF_B, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xff } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_H: Store/Load half word: max negative",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_H, R10, -40, 0xffff),
+                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffff } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_H: Store/Load half word: max positive",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_H, R10, -40, 0x7fff),
+                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x7fff } },
+               .stack_depth = 40,
+       },
+       {
+               "STX_MEM_H: Store/Load half word: max negative",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0),
+                       BPF_LD_IMM64(R1, 0xffffLL),
+                       BPF_STX_MEM(BPF_H, R10, R1, -40),
+                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffff } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_W: Store/Load word: max negative",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_W, R10, -40, 0xffffffff),
+                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffffffff } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_W: Store/Load word: max positive",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_W, R10, -40, 0x7fffffff),
+                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x7fffffff } },
+               .stack_depth = 40,
+       },
+       {
+               "STX_MEM_W: Store/Load word: max negative",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0),
+                       BPF_LD_IMM64(R1, 0xffffffffLL),
+                       BPF_STX_MEM(BPF_W, R10, R1, -40),
+                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffffffff } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_DW: Store/Load double word: max negative",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_DW, R10, -40, 0xffffffff),
+                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffffffff } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_DW: Store/Load double word: max negative 2",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R2, 0xffff00000000ffffLL),
+                       BPF_LD_IMM64(R3, 0xffffffffffffffffLL),
+                       BPF_ST_MEM(BPF_DW, R10, -40, 0xffffffff),
+                       BPF_LDX_MEM(BPF_DW, R2, R10, -40),
+                       BPF_JMP_REG(BPF_JEQ, R2, R3, 2),
+                       BPF_MOV32_IMM(R0, 2),
+                       BPF_EXIT_INSN(),
+                       BPF_MOV32_IMM(R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x1 } },
+               .stack_depth = 40,
+       },
+       {
+               "ST_MEM_DW: Store/Load double word: max positive",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_ST_MEM(BPF_DW, R10, -40, 0x7fffffff),
+                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x7fffffff } },
+               .stack_depth = 40,
+       },
+       {
+               "STX_MEM_DW: Store/Load double word: max negative",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0),
+                       BPF_LD_IMM64(R1, 0xffffffffffffffffLL),
+                       BPF_STX_MEM(BPF_DW, R10, R1, -40),
+                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xffffffff } },
+               .stack_depth = 40,
+       },
+       {
+               "STX_MEM_DW: Store double word: first word in memory",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0),
+                       BPF_LD_IMM64(R1, 0x0123456789abcdefLL),
+                       BPF_STX_MEM(BPF_DW, R10, R1, -40),
+                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+#ifdef __BIG_ENDIAN
+               { { 0, 0x01234567 } },
+#else
+               { { 0, 0x89abcdef } },
+#endif
+               .stack_depth = 40,
+       },
+       {
+               "STX_MEM_DW: Store double word: second word in memory",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R0, 0),
+                       BPF_LD_IMM64(R1, 0x0123456789abcdefLL),
+                       BPF_STX_MEM(BPF_DW, R10, R1, -40),
+                       BPF_LDX_MEM(BPF_W, R0, R10, -36),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+#ifdef __BIG_ENDIAN
+               { { 0, 0x89abcdef } },
+#else
+               { { 0, 0x01234567 } },
+#endif
+               .stack_depth = 40,
+       },
+       /* BPF_STX | BPF_ATOMIC | BPF_W/DW */
+       {
+               "STX_XADD_W: X + 1 + 1 + 1 + ...",
+               { },
+               INTERNAL,
+               { },
+               { { 0, 4134 } },
+               .fill_helper = bpf_fill_stxw,
+       },
+       {
+               "STX_XADD_DW: X + 1 + 1 + 1 + ...",
+               { },
+               INTERNAL,
+               { },
+               { { 0, 4134 } },
+               .fill_helper = bpf_fill_stxdw,
+       },
+       /*
+        * Exhaustive tests of atomic operation variants.
+        * Individual tests are expanded from template macros for all
+        * combinations of ALU operation, word size and fetching.
+        */
+#define BPF_ATOMIC_OP_TEST1(width, op, logic, old, update, result)     \
+{                                                                      \
+       "BPF_ATOMIC | " #width ", " #op ": Test: "                      \
+               #old " " #logic " " #update " = " #result,              \
+       .u.insns_int = {                                                \
+               BPF_ALU32_IMM(BPF_MOV, R5, update),                     \
+               BPF_ST_MEM(width, R10, -40, old),                       \
+               BPF_ATOMIC_OP(width, op, R10, R5, -40),                 \
+               BPF_LDX_MEM(width, R0, R10, -40),                       \
+               BPF_EXIT_INSN(),                                        \
+       },                                                              \
+       INTERNAL,                                                       \
+       { },                                                            \
+       { { 0, result } },                                              \
+       .stack_depth = 40,                                              \
+}
+#define BPF_ATOMIC_OP_TEST2(width, op, logic, old, update, result)     \
+{                                                                      \
+       "BPF_ATOMIC | " #width ", " #op ": Test side effects, r10: "    \
+               #old " " #logic " " #update " = " #result,              \
+       .u.insns_int = {                                                \
+               BPF_ALU64_REG(BPF_MOV, R1, R10),                        \
+               BPF_ALU32_IMM(BPF_MOV, R0, update),                     \
+               BPF_ST_MEM(BPF_W, R10, -40, old),                       \
+               BPF_ATOMIC_OP(width, op, R10, R0, -40),                 \
+               BPF_ALU64_REG(BPF_MOV, R0, R10),                        \
+               BPF_ALU64_REG(BPF_SUB, R0, R1),                         \
+               BPF_EXIT_INSN(),                                        \
+       },                                                              \
+       INTERNAL,                                                       \
+       { },                                                            \
+       { { 0, 0 } },                                                   \
+       .stack_depth = 40,                                              \
+}
+#define BPF_ATOMIC_OP_TEST3(width, op, logic, old, update, result)     \
+{                                                                      \
+       "BPF_ATOMIC | " #width ", " #op ": Test side effects, r0: "     \
+               #old " " #logic " " #update " = " #result,              \
+       .u.insns_int = {                                                \
+               BPF_ALU64_REG(BPF_MOV, R0, R10),                        \
+               BPF_ALU32_IMM(BPF_MOV, R1, update),                     \
+               BPF_ST_MEM(width, R10, -40, old),                       \
+               BPF_ATOMIC_OP(width, op, R10, R1, -40),                 \
+               BPF_ALU64_REG(BPF_SUB, R0, R10),                        \
+               BPF_EXIT_INSN(),                                        \
+       },                                                              \
+       INTERNAL,                                                       \
+       { },                                                            \
+       { { 0, 0 } },                                                   \
+       .stack_depth = 40,                                              \
+}
+#define BPF_ATOMIC_OP_TEST4(width, op, logic, old, update, result)     \
+{                                                                      \
+       "BPF_ATOMIC | " #width ", " #op ": Test fetch: "                \
+               #old " " #logic " " #update " = " #result,              \
+       .u.insns_int = {                                                \
+               BPF_ALU32_IMM(BPF_MOV, R3, update),                     \
+               BPF_ST_MEM(width, R10, -40, old),                       \
+               BPF_ATOMIC_OP(width, op, R10, R3, -40),                 \
+               BPF_ALU64_REG(BPF_MOV, R0, R3),                         \
+               BPF_EXIT_INSN(),                                        \
+       },                                                              \
+       INTERNAL,                                                       \
+       { },                                                            \
+       { { 0, (op) & BPF_FETCH ? old : update } },                     \
+       .stack_depth = 40,                                              \
+}
+       /* BPF_ATOMIC | BPF_W: BPF_ADD */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       /* BPF_ATOMIC | BPF_W: BPF_ADD | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       /* BPF_ATOMIC | BPF_DW: BPF_ADD */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_ADD, +, 0x12, 0xab, 0xbd),
+       /* BPF_ATOMIC | BPF_DW: BPF_ADD | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_ADD | BPF_FETCH, +, 0x12, 0xab, 0xbd),
+       /* BPF_ATOMIC | BPF_W: BPF_AND */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_AND, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_AND, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_AND, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_AND, &, 0x12, 0xab, 0x02),
+       /* BPF_ATOMIC | BPF_W: BPF_AND | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       /* BPF_ATOMIC | BPF_DW: BPF_AND */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_AND, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_AND, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_AND, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_AND, &, 0x12, 0xab, 0x02),
+       /* BPF_ATOMIC | BPF_DW: BPF_AND | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_AND | BPF_FETCH, &, 0x12, 0xab, 0x02),
+       /* BPF_ATOMIC | BPF_W: BPF_OR */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_OR, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_OR, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_OR, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_OR, |, 0x12, 0xab, 0xbb),
+       /* BPF_ATOMIC | BPF_W: BPF_OR | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       /* BPF_ATOMIC | BPF_DW: BPF_OR */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_OR, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_OR, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_OR, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_OR, |, 0x12, 0xab, 0xbb),
+       /* BPF_ATOMIC | BPF_DW: BPF_OR | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_OR | BPF_FETCH, |, 0x12, 0xab, 0xbb),
+       /* BPF_ATOMIC | BPF_W: BPF_XOR */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       /* BPF_ATOMIC | BPF_W: BPF_XOR | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       /* BPF_ATOMIC | BPF_DW: BPF_XOR */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_XOR, ^, 0x12, 0xab, 0xb9),
+       /* BPF_ATOMIC | BPF_DW: BPF_XOR | BPF_FETCH */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_XOR | BPF_FETCH, ^, 0x12, 0xab, 0xb9),
+       /* BPF_ATOMIC | BPF_W: BPF_XCHG */
+       BPF_ATOMIC_OP_TEST1(BPF_W, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+       BPF_ATOMIC_OP_TEST2(BPF_W, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+       BPF_ATOMIC_OP_TEST3(BPF_W, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+       BPF_ATOMIC_OP_TEST4(BPF_W, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+       /* BPF_ATOMIC | BPF_DW: BPF_XCHG */
+       BPF_ATOMIC_OP_TEST1(BPF_DW, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+       BPF_ATOMIC_OP_TEST2(BPF_DW, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+       BPF_ATOMIC_OP_TEST3(BPF_DW, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+       BPF_ATOMIC_OP_TEST4(BPF_DW, BPF_XCHG, xchg, 0x12, 0xab, 0xab),
+#undef BPF_ATOMIC_OP_TEST1
+#undef BPF_ATOMIC_OP_TEST2
+#undef BPF_ATOMIC_OP_TEST3
+#undef BPF_ATOMIC_OP_TEST4
+       /* BPF_ATOMIC | BPF_W, BPF_CMPXCHG */
+       {
+               "BPF_ATOMIC | BPF_W, BPF_CMPXCHG: Test successful return",
+               .u.insns_int = {
+                       BPF_ST_MEM(BPF_W, R10, -40, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R3, 0x89abcdef),
+                       BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, R10, R3, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x01234567 } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_W, BPF_CMPXCHG: Test successful store",
+               .u.insns_int = {
+                       BPF_ST_MEM(BPF_W, R10, -40, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R3, 0x89abcdef),
+                       BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, R10, R3, -40),
+                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x89abcdef } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_W, BPF_CMPXCHG: Test failure return",
+               .u.insns_int = {
+                       BPF_ST_MEM(BPF_W, R10, -40, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x76543210),
+                       BPF_ALU32_IMM(BPF_MOV, R3, 0x89abcdef),
+                       BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, R10, R3, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x01234567 } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_W, BPF_CMPXCHG: Test failure store",
+               .u.insns_int = {
+                       BPF_ST_MEM(BPF_W, R10, -40, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x76543210),
+                       BPF_ALU32_IMM(BPF_MOV, R3, 0x89abcdef),
+                       BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, R10, R3, -40),
+                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x01234567 } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_W, BPF_CMPXCHG: Test side effects",
+               .u.insns_int = {
+                       BPF_ST_MEM(BPF_W, R10, -40, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x01234567),
+                       BPF_ALU32_IMM(BPF_MOV, R3, 0x89abcdef),
+                       BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, R10, R3, -40),
+                       BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, R10, R3, -40),
+                       BPF_ALU32_REG(BPF_MOV, R0, R3),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x89abcdef } },
+               .stack_depth = 40,
+       },
+       /* BPF_ATOMIC | BPF_DW, BPF_CMPXCHG */
+       {
+               "BPF_ATOMIC | BPF_DW, BPF_CMPXCHG: Test successful return",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R1, 0x0123456789abcdefULL),
+                       BPF_LD_IMM64(R2, 0xfecdba9876543210ULL),
+                       BPF_ALU64_REG(BPF_MOV, R0, R1),
+                       BPF_STX_MEM(BPF_DW, R10, R1, -40),
+                       BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, R10, R2, -40),
+                       BPF_JMP_REG(BPF_JNE, R0, R1, 1),
+                       BPF_ALU64_REG(BPF_SUB, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_DW, BPF_CMPXCHG: Test successful store",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R1, 0x0123456789abcdefULL),
+                       BPF_LD_IMM64(R2, 0xfecdba9876543210ULL),
+                       BPF_ALU64_REG(BPF_MOV, R0, R1),
+                       BPF_STX_MEM(BPF_DW, R10, R0, -40),
+                       BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, R10, R2, -40),
+                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_JMP_REG(BPF_JNE, R0, R2, 1),
+                       BPF_ALU64_REG(BPF_SUB, R0, R2),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_DW, BPF_CMPXCHG: Test failure return",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R1, 0x0123456789abcdefULL),
+                       BPF_LD_IMM64(R2, 0xfecdba9876543210ULL),
+                       BPF_ALU64_REG(BPF_MOV, R0, R1),
+                       BPF_ALU64_IMM(BPF_ADD, R0, 1),
+                       BPF_STX_MEM(BPF_DW, R10, R1, -40),
+                       BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, R10, R2, -40),
+                       BPF_JMP_REG(BPF_JNE, R0, R1, 1),
+                       BPF_ALU64_REG(BPF_SUB, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_DW, BPF_CMPXCHG: Test failure store",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R1, 0x0123456789abcdefULL),
+                       BPF_LD_IMM64(R2, 0xfecdba9876543210ULL),
+                       BPF_ALU64_REG(BPF_MOV, R0, R1),
+                       BPF_ALU64_IMM(BPF_ADD, R0, 1),
+                       BPF_STX_MEM(BPF_DW, R10, R1, -40),
+                       BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, R10, R2, -40),
+                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_JMP_REG(BPF_JNE, R0, R1, 1),
+                       BPF_ALU64_REG(BPF_SUB, R0, R1),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } },
+               .stack_depth = 40,
+       },
+       {
+               "BPF_ATOMIC | BPF_DW, BPF_CMPXCHG: Test side effects",
+               .u.insns_int = {
+                       BPF_LD_IMM64(R1, 0x0123456789abcdefULL),
+                       BPF_LD_IMM64(R2, 0xfecdba9876543210ULL),
+                       BPF_ALU64_REG(BPF_MOV, R0, R1),
+                       BPF_STX_MEM(BPF_DW, R10, R1, -40),
+                       BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, R10, R2, -40),
+                       BPF_LD_IMM64(R0, 0xfecdba9876543210ULL),
+                       BPF_JMP_REG(BPF_JNE, R0, R2, 1),
+                       BPF_ALU64_REG(BPF_SUB, R0, R2),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0 } },
+               .stack_depth = 40,
+       },
+       /* BPF_JMP32 | BPF_JEQ | BPF_K */
+       {
+               "JMP32_JEQ_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 123),
+                       BPF_JMP32_IMM(BPF_JEQ, R0, 321, 1),
+                       BPF_JMP32_IMM(BPF_JEQ, R0, 123, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 123 } }
+       },
+       {
+               "JMP32_JEQ_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 12345678),
+                       BPF_JMP32_IMM(BPF_JEQ, R0, 12345678 & 0xffff, 1),
+                       BPF_JMP32_IMM(BPF_JEQ, R0, 12345678, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 12345678 } }
+       },
+       {
+               "JMP32_JEQ_K: negative immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_JMP32_IMM(BPF_JEQ, R0,  123, 1),
+                       BPF_JMP32_IMM(BPF_JEQ, R0, -123, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -123 } }
+       },
+       /* BPF_JMP32 | BPF_JEQ | BPF_X */
+       {
+               "JMP32_JEQ_X",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1234),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 4321),
+                       BPF_JMP32_REG(BPF_JEQ, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 1234),
+                       BPF_JMP32_REG(BPF_JEQ, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1234 } }
+       },
+       /* BPF_JMP32 | BPF_JNE | BPF_K */
+       {
+               "JMP32_JNE_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 123),
+                       BPF_JMP32_IMM(BPF_JNE, R0, 123, 1),
+                       BPF_JMP32_IMM(BPF_JNE, R0, 321, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 123 } }
+       },
+       {
+               "JMP32_JNE_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 12345678),
+                       BPF_JMP32_IMM(BPF_JNE, R0, 12345678, 1),
+                       BPF_JMP32_IMM(BPF_JNE, R0, 12345678 & 0xffff, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 12345678 } }
+       },
+       {
+               "JMP32_JNE_K: negative immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_JMP32_IMM(BPF_JNE, R0, -123, 1),
+                       BPF_JMP32_IMM(BPF_JNE, R0,  123, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -123 } }
+       },
+       /* BPF_JMP32 | BPF_JNE | BPF_X */
+       {
+               "JMP32_JNE_X",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1234),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 1234),
+                       BPF_JMP32_REG(BPF_JNE, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 4321),
+                       BPF_JMP32_REG(BPF_JNE, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1234 } }
+       },
+       /* BPF_JMP32 | BPF_JSET | BPF_K */
+       {
+               "JMP32_JSET_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
+                       BPF_JMP32_IMM(BPF_JSET, R0, 2, 1),
+                       BPF_JMP32_IMM(BPF_JSET, R0, 3, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } }
+       },
+       {
+               "JMP32_JSET_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0x40000000),
+                       BPF_JMP32_IMM(BPF_JSET, R0, 0x3fffffff, 1),
+                       BPF_JMP32_IMM(BPF_JSET, R0, 0x60000000, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0x40000000 } }
+       },
+       {
+               "JMP32_JSET_K: negative immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_JMP32_IMM(BPF_JSET, R0, -1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, -123 } }
+       },
+       /* BPF_JMP32 | BPF_JSET | BPF_X */
+       {
+               "JMP32_JSET_X",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 8),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 7),
+                       BPF_JMP32_REG(BPF_JSET, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 8 | 2),
+                       BPF_JMP32_REG(BPF_JNE, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 8 } }
+       },
+       /* BPF_JMP32 | BPF_JGT | BPF_K */
+       {
+               "JMP32_JGT_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 123),
+                       BPF_JMP32_IMM(BPF_JGT, R0, 123, 1),
+                       BPF_JMP32_IMM(BPF_JGT, R0, 122, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 123 } }
+       },
+       {
+               "JMP32_JGT_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_JMP32_IMM(BPF_JGT, R0, 0xffffffff, 1),
+                       BPF_JMP32_IMM(BPF_JGT, R0, 0xfffffffd, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xfffffffe } }
+       },
+       /* BPF_JMP32 | BPF_JGT | BPF_X */
+       {
+               "JMP32_JGT_X",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xffffffff),
+                       BPF_JMP32_REG(BPF_JGT, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xfffffffd),
+                       BPF_JMP32_REG(BPF_JGT, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 0xfffffffe } }
+       },
+       /* BPF_JMP32 | BPF_JGE | BPF_K */
+       {
+               "JMP32_JGE_K: Small immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 123),
+                       BPF_JMP32_IMM(BPF_JGE, R0, 124, 1),
+                       BPF_JMP32_IMM(BPF_JGE, R0, 123, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xff } },
-               .stack_depth = 40,
+               { { 0, 123 } }
        },
        {
-               "ST_MEM_B: Store/Load byte: max positive",
+               "JMP32_JGE_K: Large immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_H, R10, -40, 0x7f),
-                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_JMP32_IMM(BPF_JGE, R0, 0xffffffff, 1),
+                       BPF_JMP32_IMM(BPF_JGE, R0, 0xfffffffe, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x7f } },
-               .stack_depth = 40,
+               { { 0, 0xfffffffe } }
        },
+       /* BPF_JMP32 | BPF_JGE | BPF_X */
        {
-               "STX_MEM_B: Store/Load byte: max negative",
+               "JMP32_JGE_X",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0),
-                       BPF_LD_IMM64(R1, 0xffLL),
-                       BPF_STX_MEM(BPF_B, R10, R1, -40),
-                       BPF_LDX_MEM(BPF_B, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xffffffff),
+                       BPF_JMP32_REG(BPF_JGE, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xfffffffe),
+                       BPF_JMP32_REG(BPF_JGE, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xff } },
-               .stack_depth = 40,
+               { { 0, 0xfffffffe } }
        },
+       /* BPF_JMP32 | BPF_JLT | BPF_K */
        {
-               "ST_MEM_H: Store/Load half word: max negative",
+               "JMP32_JLT_K: Small immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_H, R10, -40, 0xffff),
-                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 123),
+                       BPF_JMP32_IMM(BPF_JLT, R0, 123, 1),
+                       BPF_JMP32_IMM(BPF_JLT, R0, 124, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffff } },
-               .stack_depth = 40,
+               { { 0, 123 } }
        },
        {
-               "ST_MEM_H: Store/Load half word: max positive",
+               "JMP32_JLT_K: Large immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_H, R10, -40, 0x7fff),
-                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_JMP32_IMM(BPF_JLT, R0, 0xfffffffd, 1),
+                       BPF_JMP32_IMM(BPF_JLT, R0, 0xffffffff, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x7fff } },
-               .stack_depth = 40,
+               { { 0, 0xfffffffe } }
        },
+       /* BPF_JMP32 | BPF_JLT | BPF_X */
        {
-               "STX_MEM_H: Store/Load half word: max negative",
+               "JMP32_JLT_X",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0),
-                       BPF_LD_IMM64(R1, 0xffffLL),
-                       BPF_STX_MEM(BPF_H, R10, R1, -40),
-                       BPF_LDX_MEM(BPF_H, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xfffffffd),
+                       BPF_JMP32_REG(BPF_JLT, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xffffffff),
+                       BPF_JMP32_REG(BPF_JLT, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffff } },
-               .stack_depth = 40,
+               { { 0, 0xfffffffe } }
        },
+       /* BPF_JMP32 | BPF_JLE | BPF_K */
        {
-               "ST_MEM_W: Store/Load word: max negative",
+               "JMP32_JLE_K: Small immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_W, R10, -40, 0xffffffff),
-                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 123),
+                       BPF_JMP32_IMM(BPF_JLE, R0, 122, 1),
+                       BPF_JMP32_IMM(BPF_JLE, R0, 123, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffffffff } },
-               .stack_depth = 40,
+               { { 0, 123 } }
        },
        {
-               "ST_MEM_W: Store/Load word: max positive",
+               "JMP32_JLE_K: Large immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_W, R10, -40, 0x7fffffff),
-                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_JMP32_IMM(BPF_JLE, R0, 0xfffffffd, 1),
+                       BPF_JMP32_IMM(BPF_JLE, R0, 0xfffffffe, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x7fffffff } },
-               .stack_depth = 40,
+               { { 0, 0xfffffffe } }
        },
+       /* BPF_JMP32 | BPF_JLE | BPF_X */
        {
-               "STX_MEM_W: Store/Load word: max negative",
+               "JMP32_JLE_X",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0),
-                       BPF_LD_IMM64(R1, 0xffffffffLL),
-                       BPF_STX_MEM(BPF_W, R10, R1, -40),
-                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0xfffffffe),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xfffffffd),
+                       BPF_JMP32_REG(BPF_JLE, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, 0xfffffffe),
+                       BPF_JMP32_REG(BPF_JLE, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffffffff } },
-               .stack_depth = 40,
+               { { 0, 0xfffffffe } }
        },
+       /* BPF_JMP32 | BPF_JSGT | BPF_K */
        {
-               "ST_MEM_DW: Store/Load double word: max negative",
+               "JMP32_JSGT_K: Small immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_DW, R10, -40, 0xffffffff),
-                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_JMP32_IMM(BPF_JSGT, R0, -123, 1),
+                       BPF_JMP32_IMM(BPF_JSGT, R0, -124, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffffffff } },
-               .stack_depth = 40,
+               { { 0, -123 } }
        },
        {
-               "ST_MEM_DW: Store/Load double word: max negative 2",
+               "JMP32_JSGT_K: Large immediate",
                .u.insns_int = {
-                       BPF_LD_IMM64(R2, 0xffff00000000ffffLL),
-                       BPF_LD_IMM64(R3, 0xffffffffffffffffLL),
-                       BPF_ST_MEM(BPF_DW, R10, -40, 0xffffffff),
-                       BPF_LDX_MEM(BPF_DW, R2, R10, -40),
-                       BPF_JMP_REG(BPF_JEQ, R2, R3, 2),
-                       BPF_MOV32_IMM(R0, 2),
-                       BPF_EXIT_INSN(),
-                       BPF_MOV32_IMM(R0, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_JMP32_IMM(BPF_JSGT, R0, -12345678, 1),
+                       BPF_JMP32_IMM(BPF_JSGT, R0, -12345679, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x1 } },
-               .stack_depth = 40,
+               { { 0, -12345678 } }
        },
+       /* BPF_JMP32 | BPF_JSGT | BPF_X */
        {
-               "ST_MEM_DW: Store/Load double word: max positive",
+               "JMP32_JSGT_X",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 1),
-                       BPF_ST_MEM(BPF_DW, R10, -40, 0x7fffffff),
-                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345678),
+                       BPF_JMP32_REG(BPF_JSGT, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345679),
+                       BPF_JMP32_REG(BPF_JSGT, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x7fffffff } },
-               .stack_depth = 40,
+               { { 0, -12345678 } }
        },
+       /* BPF_JMP32 | BPF_JSGE | BPF_K */
        {
-               "STX_MEM_DW: Store/Load double word: max negative",
+               "JMP32_JSGE_K: Small immediate",
                .u.insns_int = {
-                       BPF_LD_IMM64(R0, 0),
-                       BPF_LD_IMM64(R1, 0xffffffffffffffffLL),
-                       BPF_STX_MEM(BPF_W, R10, R1, -40),
-                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_JMP32_IMM(BPF_JSGE, R0, -122, 1),
+                       BPF_JMP32_IMM(BPF_JSGE, R0, -123, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0xffffffff } },
-               .stack_depth = 40,
+               { { 0, -123 } }
        },
-       /* BPF_STX | BPF_ATOMIC | BPF_W/DW */
        {
-               "STX_XADD_W: Test: 0x12 + 0x10 = 0x22",
+               "JMP32_JSGE_K: Large immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12),
-                       BPF_ST_MEM(BPF_W, R10, -40, 0x10),
-                       BPF_ATOMIC_OP(BPF_W, BPF_ADD, R10, R0, -40),
-                       BPF_LDX_MEM(BPF_W, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_JMP32_IMM(BPF_JSGE, R0, -12345677, 1),
+                       BPF_JMP32_IMM(BPF_JSGE, R0, -12345678, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x22 } },
-               .stack_depth = 40,
+               { { 0, -12345678 } }
        },
+       /* BPF_JMP32 | BPF_JSGE | BPF_X */
        {
-               "STX_XADD_W: Test side-effects, r10: 0x12 + 0x10 = 0x22",
+               "JMP32_JSGE_X",
                .u.insns_int = {
-                       BPF_ALU64_REG(BPF_MOV, R1, R10),
-                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12),
-                       BPF_ST_MEM(BPF_W, R10, -40, 0x10),
-                       BPF_ATOMIC_OP(BPF_W, BPF_ADD, R10, R0, -40),
-                       BPF_ALU64_REG(BPF_MOV, R0, R10),
-                       BPF_ALU64_REG(BPF_SUB, R0, R1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345677),
+                       BPF_JMP32_REG(BPF_JSGE, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345678),
+                       BPF_JMP32_REG(BPF_JSGE, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0 } },
-               .stack_depth = 40,
+               { { 0, -12345678 } }
        },
+       /* BPF_JMP32 | BPF_JSLT | BPF_K */
        {
-               "STX_XADD_W: Test side-effects, r0: 0x12 + 0x10 = 0x22",
+               "JMP32_JSLT_K: Small immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12),
-                       BPF_ST_MEM(BPF_W, R10, -40, 0x10),
-                       BPF_ATOMIC_OP(BPF_W, BPF_ADD, R10, R0, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_JMP32_IMM(BPF_JSLT, R0, -123, 1),
+                       BPF_JMP32_IMM(BPF_JSLT, R0, -122, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x12 } },
-               .stack_depth = 40,
+               { { 0, -123 } }
        },
        {
-               "STX_XADD_W: X + 1 + 1 + 1 + ...",
-               { },
+               "JMP32_JSLT_K: Large immediate",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_JMP32_IMM(BPF_JSLT, R0, -12345678, 1),
+                       BPF_JMP32_IMM(BPF_JSLT, R0, -12345677, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
                INTERNAL,
                { },
-               { { 0, 4134 } },
-               .fill_helper = bpf_fill_stxw,
+               { { 0, -12345678 } }
        },
+       /* BPF_JMP32 | BPF_JSLT | BPF_X */
        {
-               "STX_XADD_DW: Test: 0x12 + 0x10 = 0x22",
+               "JMP32_JSLT_X",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12),
-                       BPF_ST_MEM(BPF_DW, R10, -40, 0x10),
-                       BPF_ATOMIC_OP(BPF_DW, BPF_ADD, R10, R0, -40),
-                       BPF_LDX_MEM(BPF_DW, R0, R10, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345678),
+                       BPF_JMP32_REG(BPF_JSLT, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345677),
+                       BPF_JMP32_REG(BPF_JSLT, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x22 } },
-               .stack_depth = 40,
+               { { 0, -12345678 } }
        },
+       /* BPF_JMP32 | BPF_JSLE | BPF_K */
        {
-               "STX_XADD_DW: Test side-effects, r10: 0x12 + 0x10 = 0x22",
+               "JMP32_JSLE_K: Small immediate",
                .u.insns_int = {
-                       BPF_ALU64_REG(BPF_MOV, R1, R10),
-                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12),
-                       BPF_ST_MEM(BPF_DW, R10, -40, 0x10),
-                       BPF_ATOMIC_OP(BPF_DW, BPF_ADD, R10, R0, -40),
-                       BPF_ALU64_REG(BPF_MOV, R0, R10),
-                       BPF_ALU64_REG(BPF_SUB, R0, R1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -123),
+                       BPF_JMP32_IMM(BPF_JSLE, R0, -124, 1),
+                       BPF_JMP32_IMM(BPF_JSLE, R0, -123, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0 } },
-               .stack_depth = 40,
+               { { 0, -123 } }
        },
        {
-               "STX_XADD_DW: Test side-effects, r0: 0x12 + 0x10 = 0x22",
+               "JMP32_JSLE_K: Large immediate",
                .u.insns_int = {
-                       BPF_ALU32_IMM(BPF_MOV, R0, 0x12),
-                       BPF_ST_MEM(BPF_DW, R10, -40, 0x10),
-                       BPF_ATOMIC_OP(BPF_DW, BPF_ADD, R10, R0, -40),
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_JMP32_IMM(BPF_JSLE, R0, -12345679, 1),
+                       BPF_JMP32_IMM(BPF_JSLE, R0, -12345678, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
                        BPF_EXIT_INSN(),
                },
                INTERNAL,
                { },
-               { { 0, 0x12 } },
-               .stack_depth = 40,
+               { { 0, -12345678 } }
        },
+       /* BPF_JMP32 | BPF_JSLE | BPF_K */
        {
-               "STX_XADD_DW: X + 1 + 1 + 1 + ...",
-               { },
+               "JMP32_JSLE_X",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, -12345678),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345679),
+                       BPF_JMP32_REG(BPF_JSLE, R0, R1, 2),
+                       BPF_ALU32_IMM(BPF_MOV, R1, -12345678),
+                       BPF_JMP32_REG(BPF_JSLE, R0, R1, 1),
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_EXIT_INSN(),
+               },
                INTERNAL,
                { },
-               { { 0, 4134 } },
-               .fill_helper = bpf_fill_stxdw,
+               { { 0, -12345678 } }
        },
        /* BPF_JMP | BPF_EXIT */
        {
@@ -5223,6 +7192,14 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 1 } },
        },
+       {       /* Mainly checking JIT here. */
+               "BPF_MAXINSNS: Very long conditional jump",
+               { },
+               INTERNAL | FLAG_NO_DATA,
+               { },
+               { { 0, 1 } },
+               .fill_helper = bpf_fill_long_jmp,
+       },
        {
                "JMP_JA: Jump, gap, jump, ...",
                { },
@@ -6639,7 +8616,7 @@ static int __run_one(const struct bpf_prog *fp, const void *data,
        start = ktime_get_ns();
 
        for (i = 0; i < runs; i++)
-               ret = BPF_PROG_RUN(fp, data);
+               ret = bpf_prog_run(fp, data);
 
        finish = ktime_get_ns();
        migrate_enable();
@@ -6659,7 +8636,14 @@ static int run_one(const struct bpf_prog *fp, struct bpf_test *test)
                u64 duration;
                u32 ret;
 
-               if (test->test[i].data_size == 0 &&
+               /*
+                * NOTE: Several sub-tests may be present, in which case
+                * a zero {data_size, result} tuple indicates the end of
+                * the sub-test array. The first test is always run,
+                * even if both data_size and result happen to be zero.
+                */
+               if (i > 0 &&
+                   test->test[i].data_size == 0 &&
                    test->test[i].result == 0)
                        break;
 
@@ -7005,8 +8989,248 @@ static __init int test_bpf(void)
        return err_cnt ? -EINVAL : 0;
 }
 
+struct tail_call_test {
+       const char *descr;
+       struct bpf_insn insns[MAX_INSNS];
+       int result;
+       int stack_depth;
+};
+
+/*
+ * Magic marker used in test snippets for tail calls below.
+ * BPF_LD/MOV to R2 and R2 with this immediate value is replaced
+ * with the proper values by the test runner.
+ */
+#define TAIL_CALL_MARKER 0x7a11ca11
+
+/* Special offset to indicate a NULL call target */
+#define TAIL_CALL_NULL 0x7fff
+
+/* Special offset to indicate an out-of-range index */
+#define TAIL_CALL_INVALID 0x7ffe
+
+#define TAIL_CALL(offset)                             \
+       BPF_LD_IMM64(R2, TAIL_CALL_MARKER),            \
+       BPF_RAW_INSN(BPF_ALU | BPF_MOV | BPF_K, R3, 0, \
+                    offset, TAIL_CALL_MARKER),        \
+       BPF_JMP_IMM(BPF_TAIL_CALL, 0, 0, 0)
+
+/*
+ * Tail call tests. Each test case may call any other test in the table,
+ * including itself, specified as a relative index offset from the calling
+ * test. The index TAIL_CALL_NULL can be used to specify a NULL target
+ * function to test the JIT error path. Similarly, the index TAIL_CALL_INVALID
+ * results in a target index that is out of range.
+ */
+static struct tail_call_test tail_call_tests[] = {
+       {
+               "Tail call leaf",
+               .insns = {
+                       BPF_ALU64_REG(BPF_MOV, R0, R1),
+                       BPF_ALU64_IMM(BPF_ADD, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = 1,
+       },
+       {
+               "Tail call 2",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_ADD, R1, 2),
+                       TAIL_CALL(-1),
+                       BPF_ALU64_IMM(BPF_MOV, R0, -1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = 3,
+       },
+       {
+               "Tail call 3",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_ADD, R1, 3),
+                       TAIL_CALL(-1),
+                       BPF_ALU64_IMM(BPF_MOV, R0, -1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = 6,
+       },
+       {
+               "Tail call 4",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_ADD, R1, 4),
+                       TAIL_CALL(-1),
+                       BPF_ALU64_IMM(BPF_MOV, R0, -1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = 10,
+       },
+       {
+               "Tail call error path, max count reached",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_ADD, R1, 1),
+                       BPF_ALU64_REG(BPF_MOV, R0, R1),
+                       TAIL_CALL(0),
+                       BPF_EXIT_INSN(),
+               },
+               .result = MAX_TAIL_CALL_CNT + 1,
+       },
+       {
+               "Tail call error path, NULL target",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_MOV, R0, -1),
+                       TAIL_CALL(TAIL_CALL_NULL),
+                       BPF_ALU64_IMM(BPF_MOV, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = 1,
+       },
+       {
+               "Tail call error path, index out of range",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_MOV, R0, -1),
+                       TAIL_CALL(TAIL_CALL_INVALID),
+                       BPF_ALU64_IMM(BPF_MOV, R0, 1),
+                       BPF_EXIT_INSN(),
+               },
+               .result = 1,
+       },
+};
+
+static void __init destroy_tail_call_tests(struct bpf_array *progs)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(tail_call_tests); i++)
+               if (progs->ptrs[i])
+                       bpf_prog_free(progs->ptrs[i]);
+       kfree(progs);
+}
+
+static __init int prepare_tail_call_tests(struct bpf_array **pprogs)
+{
+       int ntests = ARRAY_SIZE(tail_call_tests);
+       struct bpf_array *progs;
+       int which, err;
+
+       /* Allocate the table of programs to be used for tall calls */
+       progs = kzalloc(sizeof(*progs) + (ntests + 1) * sizeof(progs->ptrs[0]),
+                       GFP_KERNEL);
+       if (!progs)
+               goto out_nomem;
+
+       /* Create all eBPF programs and populate the table */
+       for (which = 0; which < ntests; which++) {
+               struct tail_call_test *test = &tail_call_tests[which];
+               struct bpf_prog *fp;
+               int len, i;
+
+               /* Compute the number of program instructions */
+               for (len = 0; len < MAX_INSNS; len++) {
+                       struct bpf_insn *insn = &test->insns[len];
+
+                       if (len < MAX_INSNS - 1 &&
+                           insn->code == (BPF_LD | BPF_DW | BPF_IMM))
+                               len++;
+                       if (insn->code == 0)
+                               break;
+               }
+
+               /* Allocate and initialize the program */
+               fp = bpf_prog_alloc(bpf_prog_size(len), 0);
+               if (!fp)
+                       goto out_nomem;
+
+               fp->len = len;
+               fp->type = BPF_PROG_TYPE_SOCKET_FILTER;
+               fp->aux->stack_depth = test->stack_depth;
+               memcpy(fp->insnsi, test->insns, len * sizeof(struct bpf_insn));
+
+               /* Relocate runtime tail call offsets and addresses */
+               for (i = 0; i < len; i++) {
+                       struct bpf_insn *insn = &fp->insnsi[i];
+
+                       if (insn->imm != TAIL_CALL_MARKER)
+                               continue;
+
+                       switch (insn->code) {
+                       case BPF_LD | BPF_DW | BPF_IMM:
+                               insn[0].imm = (u32)(long)progs;
+                               insn[1].imm = ((u64)(long)progs) >> 32;
+                               break;
+
+                       case BPF_ALU | BPF_MOV | BPF_K:
+                               if (insn->off == TAIL_CALL_NULL)
+                                       insn->imm = ntests;
+                               else if (insn->off == TAIL_CALL_INVALID)
+                                       insn->imm = ntests + 1;
+                               else
+                                       insn->imm = which + insn->off;
+                               insn->off = 0;
+                       }
+               }
+
+               fp = bpf_prog_select_runtime(fp, &err);
+               if (err)
+                       goto out_err;
+
+               progs->ptrs[which] = fp;
+       }
+
+       /* The last entry contains a NULL program pointer */
+       progs->map.max_entries = ntests + 1;
+       *pprogs = progs;
+       return 0;
+
+out_nomem:
+       err = -ENOMEM;
+
+out_err:
+       if (progs)
+               destroy_tail_call_tests(progs);
+       return err;
+}
+
+static __init int test_tail_calls(struct bpf_array *progs)
+{
+       int i, err_cnt = 0, pass_cnt = 0;
+       int jit_cnt = 0, run_cnt = 0;
+
+       for (i = 0; i < ARRAY_SIZE(tail_call_tests); i++) {
+               struct tail_call_test *test = &tail_call_tests[i];
+               struct bpf_prog *fp = progs->ptrs[i];
+               u64 duration;
+               int ret;
+
+               cond_resched();
+
+               pr_info("#%d %s ", i, test->descr);
+               if (!fp) {
+                       err_cnt++;
+                       continue;
+               }
+               pr_cont("jited:%u ", fp->jited);
+
+               run_cnt++;
+               if (fp->jited)
+                       jit_cnt++;
+
+               ret = __run_one(fp, NULL, MAX_TESTRUNS, &duration);
+               if (ret == test->result) {
+                       pr_cont("%lld PASS", duration);
+                       pass_cnt++;
+               } else {
+                       pr_cont("ret %d != %d FAIL", ret, test->result);
+                       err_cnt++;
+               }
+       }
+
+       pr_info("%s: Summary: %d PASSED, %d FAILED, [%d/%d JIT'ed]\n",
+               __func__, pass_cnt, err_cnt, jit_cnt, run_cnt);
+
+       return err_cnt ? -EINVAL : 0;
+}
+
 static int __init test_bpf_init(void)
 {
+       struct bpf_array *progs = NULL;
        int ret;
 
        ret = prepare_bpf_tests();
@@ -7018,6 +9242,14 @@ static int __init test_bpf_init(void)
        if (ret)
                return ret;
 
+       ret = prepare_tail_call_tests(&progs);
+       if (ret)
+               return ret;
+       ret = test_tail_calls(progs);
+       destroy_tail_call_tests(progs);
+       if (ret)
+               return ret;
+
        return test_skb_segment();
 }