]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/bpf: Add a selftest for x86 jit convergence issues
authorYonghong Song <yonghong.song@linux.dev>
Wed, 4 Sep 2024 22:12:56 +0000 (15:12 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 4 Sep 2024 23:46:22 +0000 (16:46 -0700)
The core part of the selftest, i.e., the je <-> jmp cycle, mimics the
original sched-ext bpf program. The test will fail without the
previous patch.

I tried to create some cases for other potential cycles
(je <-> je, jmp <-> je and jmp <-> jmp) with similar pattern
to the test in this patch, but failed. So this patch
only contains one test for je <-> jmp cycle.

Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20240904221256.37389-1-yonghong.song@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/verifier.c
tools/testing/selftests/bpf/progs/verifier_jit_convergence.c [new file with mode: 0644]

index 80a90c6271824cc49ff9dae36e7531e25d3812a7..df398e714dff708d5aec6ed0d7c768fa44614a12 100644 (file)
@@ -39,6 +39,7 @@
 #include "verifier_int_ptr.skel.h"
 #include "verifier_iterating_callbacks.skel.h"
 #include "verifier_jeq_infer_not_null.skel.h"
+#include "verifier_jit_convergence.skel.h"
 #include "verifier_ld_ind.skel.h"
 #include "verifier_ldsx.skel.h"
 #include "verifier_leak_ptr.skel.h"
@@ -163,6 +164,7 @@ void test_verifier_helper_value_access(void)  { RUN(verifier_helper_value_access
 void test_verifier_int_ptr(void)              { RUN(verifier_int_ptr); }
 void test_verifier_iterating_callbacks(void)  { RUN(verifier_iterating_callbacks); }
 void test_verifier_jeq_infer_not_null(void)   { RUN(verifier_jeq_infer_not_null); }
+void test_verifier_jit_convergence(void)      { RUN(verifier_jit_convergence); }
 void test_verifier_ld_ind(void)               { RUN(verifier_ld_ind); }
 void test_verifier_ldsx(void)                  { RUN(verifier_ldsx); }
 void test_verifier_leak_ptr(void)             { RUN(verifier_leak_ptr); }
diff --git a/tools/testing/selftests/bpf/progs/verifier_jit_convergence.c b/tools/testing/selftests/bpf/progs/verifier_jit_convergence.c
new file mode 100644 (file)
index 0000000..9f3f2b7
--- /dev/null
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+struct value_t {
+       long long a[32];
+};
+
+struct {
+        __uint(type, BPF_MAP_TYPE_HASH);
+        __uint(max_entries, 1);
+        __type(key, long long);
+        __type(value, struct value_t);
+} map_hash SEC(".maps");
+
+SEC("socket")
+__description("bpf_jit_convergence je <-> jmp")
+__success __retval(0)
+__arch_x86_64
+__jited("      pushq   %rbp")
+__naked void btf_jit_convergence_je_jmp(void)
+{
+       asm volatile (
+       "call %[bpf_get_prandom_u32];"
+       "if r0 == 0 goto l20_%=;"
+       "if r0 == 1 goto l21_%=;"
+       "if r0 == 2 goto l22_%=;"
+       "if r0 == 3 goto l23_%=;"
+       "if r0 == 4 goto l24_%=;"
+       "call %[bpf_get_prandom_u32];"
+       "call %[bpf_get_prandom_u32];"
+"l20_%=:"
+"l21_%=:"
+"l22_%=:"
+"l23_%=:"
+"l24_%=:"
+       "r1 = 0;"
+       "*(u64 *)(r10 - 8) = r1;"
+       "r2 = r10;"
+       "r2 += -8;"
+       "r1 = %[map_hash] ll;"
+       "call %[bpf_map_lookup_elem];"
+       "if r0 == 0 goto l1_%=;"
+       "r6 = r0;"
+       "call %[bpf_get_prandom_u32];"
+       "r7 = r0;"
+       "r5 = r6;"
+       "if r0 != 0x0 goto l12_%=;"
+       "call %[bpf_get_prandom_u32];"
+       "r1 = r0;"
+       "r2 = r6;"
+       "if r1 == 0x0 goto l0_%=;"
+"l9_%=:"
+       "r2 = *(u64 *)(r6 + 0x0);"
+       "r2 += 0x1;"
+       "*(u64 *)(r6 + 0x0) = r2;"
+       "goto l1_%=;"
+"l12_%=:"
+       "r1 = r7;"
+       "r1 += 0x98;"
+       "r2 = r5;"
+       "r2 += 0x90;"
+       "r2 = *(u32 *)(r2 + 0x0);"
+       "r3 = r7;"
+       "r3 &= 0x1;"
+       "r2 *= 0xa8;"
+       "if r3 == 0x0 goto l2_%=;"
+       "r1 += r2;"
+       "r1 -= r7;"
+       "r1 += 0x8;"
+       "if r1 <= 0xb20 goto l3_%=;"
+       "r1 = 0x0;"
+       "goto l4_%=;"
+"l3_%=:"
+       "r1 += r7;"
+"l4_%=:"
+       "if r1 == 0x0 goto l8_%=;"
+       "goto l9_%=;"
+"l2_%=:"
+       "r1 += r2;"
+       "r1 -= r7;"
+       "r1 += 0x10;"
+       "if r1 <= 0xb20 goto l6_%=;"
+       "r1 = 0x0;"
+       "goto l7_%=;"
+"l6_%=:"
+       "r1 += r7;"
+"l7_%=:"
+       "if r1 == 0x0 goto l8_%=;"
+       "goto l9_%=;"
+"l0_%=:"
+       "r1 = 0x3;"
+       "*(u64 *)(r10 - 0x10) = r1;"
+       "r2 = r1;"
+       "goto l1_%=;"
+"l8_%=:"
+       "r1 = r5;"
+       "r1 += 0x4;"
+       "r1 = *(u32 *)(r1 + 0x0);"
+       "*(u64 *)(r10 - 0x8) = r1;"
+"l1_%=:"
+       "r0 = 0;"
+       "exit;"
+       :
+       : __imm(bpf_get_prandom_u32),
+         __imm(bpf_map_lookup_elem),
+         __imm_addr(map_hash)
+       : __clobber_all);
+}
+
+char _license[] SEC("license") = "GPL";