OSDN Git Service

selftests/bpf: Fix trace_virtqueue_add_sgs test issue with LLVM 17.
authorAlexei Starovoitov <ast@kernel.org>
Tue, 14 Mar 2023 22:28:11 +0000 (15:28 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 14 Mar 2023 22:28:11 +0000 (15:28 -0700)
LLVM commit https://reviews.llvm.org/D143726 introduced hoistMinMax optimization
that transformed
  (i < VIRTIO_MAX_SGS) && (i < out_sgs)
into
  i < MIN(VIRTIO_MAX_SGS, out_sgs)

and caused the verifier to stop recognizing such loop as bounded.

Which resulted in the following test failure:

libbpf: prog 'trace_virtqueue_add_sgs': BPF program load failed: Bad address
libbpf: prog 'trace_virtqueue_add_sgs': -- BEGIN PROG LOAD LOG --
The sequence of 8193 jumps is too complex.
verification time 789206 usec
stack depth 56
processed 156446 insns (limit 1000000) max_states_per_insn 7 total_states 1746 peak_states 1701 mark_read 12
-- END PROG LOAD LOG --
libbpf: prog 'trace_virtqueue_add_sgs': failed to load: -14
libbpf: failed to load object 'loop6.bpf.o'

Workaround the verifier limitation for now with inline asm that
prevents this particular optimization.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/loop6.c

index 38de033..e4ff97f 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_tracing.h>
+#include "bpf_misc.h"
 
 char _license[] SEC("license") = "GPL";
 
@@ -76,6 +77,7 @@ int BPF_KPROBE(trace_virtqueue_add_sgs, void *unused, struct scatterlist **sgs,
                return 0;
 
        for (i = 0; (i < VIRTIO_MAX_SGS) && (i < out_sgs); i++) {
+               __sink(out_sgs);
                for (n = 0, sgp = get_sgp(sgs, i); sgp && (n < SG_MAX);
                     sgp = __sg_next(sgp)) {
                        bpf_probe_read_kernel(&len, sizeof(len), &sgp->length);
@@ -85,6 +87,7 @@ int BPF_KPROBE(trace_virtqueue_add_sgs, void *unused, struct scatterlist **sgs,
        }
 
        for (i = 0; (i < VIRTIO_MAX_SGS) && (i < in_sgs); i++) {
+               __sink(in_sgs);
                for (n = 0, sgp = get_sgp(sgs, i); sgp && (n < SG_MAX);
                     sgp = __sg_next(sgp)) {
                        bpf_probe_read_kernel(&len, sizeof(len), &sgp->length);