Commit 8c89b5db authored by Yonghong Song's avatar Yonghong Song Committed by Alexei Starovoitov

selftests/bpf: Limit unroll_count for pyperf600 test

LLVM commit [1] changed loop pragma behavior such that
full loop unroll is always honored with user pragma.
Previously, unroll count also depends on the unrolled
code size. For pyperf600, without [1], the loop unroll
count is 150. With [1], the loop unroll count is 600.

The unroll count of 600 caused the program size close to
298k and this caused the following code is generated:
         0:       7b 1a 00 ff 00 00 00 00 *(u64 *)(r10 - 256) = r1
  ;       uint64_t pid_tgid = bpf_get_current_pid_tgid();
         1:       85 00 00 00 0e 00 00 00 call 14
         2:       bf 06 00 00 00 00 00 00 r6 = r0
  ;       pid_t pid = (pid_t)(pid_tgid >> 32);
         3:       bf 61 00 00 00 00 00 00 r1 = r6
         4:       77 01 00 00 20 00 00 00 r1 >>= 32
         5:       63 1a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r1
         6:       bf a2 00 00 00 00 00 00 r2 = r10
         7:       07 02 00 00 fc ff ff ff r2 += -4
  ;       PidData* pidData = bpf_map_lookup_elem(&pidmap, &pid);
         8:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
        10:       85 00 00 00 01 00 00 00 call 1
        11:       bf 08 00 00 00 00 00 00 r8 = r0
  ;       if (!pidData)
        12:       15 08 15 e8 00 00 00 00 if r8 == 0 goto -6123 <LBB0_27588+0xffffffffffdae100>

Note that insn 12 has a branch offset -6123 which is clearly illegal
and will be rejected by the verifier. The negative offset is due to
the branch range is greater than INT16_MAX.

This patch changed the unroll count to be 150 to avoid above
branch target insn out-of-range issue. Also the llvm is enhanced ([2])
to assert if the branch target insn is out of INT16 range.

  [1] https://reviews.llvm.org/D119148
  [2] https://reviews.llvm.org/D123877Signed-off-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20220419043230.2928530-1-yhs@fb.com
parent 055eb955
...@@ -299,7 +299,11 @@ int __on_event(struct bpf_raw_tracepoint_args *ctx) ...@@ -299,7 +299,11 @@ int __on_event(struct bpf_raw_tracepoint_args *ctx)
#ifdef NO_UNROLL #ifdef NO_UNROLL
#pragma clang loop unroll(disable) #pragma clang loop unroll(disable)
#else #else
#ifdef UNROLL_COUNT
#pragma clang loop unroll_count(UNROLL_COUNT)
#else
#pragma clang loop unroll(full) #pragma clang loop unroll(full)
#endif
#endif /* NO_UNROLL */ #endif /* NO_UNROLL */
/* Unwind python stack */ /* Unwind python stack */
for (int i = 0; i < STACK_MAX_LEN; ++i) { for (int i = 0; i < STACK_MAX_LEN; ++i) {
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019 Facebook // Copyright (c) 2019 Facebook
#define STACK_MAX_LEN 600 #define STACK_MAX_LEN 600
/* clang will not unroll the loop 600 times. /* Full unroll of 600 iterations will have total
* Instead it will unroll it to the amount it deemed * program size close to 298k insns and this may
* appropriate, but the loop will still execute 600 times. * cause BPF_JMP insn out of 16-bit integer range.
* Total program size is around 90k insns * So limit the unroll size to 150 so the
* total program size is around 80k insns but
* the loop will still execute 600 times.
*/ */
#define UNROLL_COUNT 150
#include "pyperf.h" #include "pyperf.h"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment