Skip to content

Commit 6c475c0

Browse files
bmastbergenPlaidCat
authored andcommitted
selftests/bpf: Limit unroll_count for pyperf600 test
jira LE-2125 commit-author Yonghong Song <[email protected]> commit 8c89b5d 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/D123877 Signed-off-by: Yonghong Song <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected] (cherry picked from commit 8c89b5d) Signed-off-by: Brett Mastbergen <[email protected]> # Conflicts: # tools/testing/selftests/bpf/progs/pyperf.h
1 parent 6ef9865 commit 6c475c0

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

tools/testing/selftests/bpf/progs/pyperf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,12 @@ int __on_event(struct bpf_raw_tracepoint_args *ctx)
231231
#ifdef NO_UNROLL
232232
#pragma clang loop unroll(disable)
233233
#else
234+
#ifdef UNROLL_COUNT
235+
#pragma clang loop unroll_count(UNROLL_COUNT)
236+
#else
234237
#pragma clang loop unroll(full)
235238
#endif
239+
#endif /* NO_UNROLL */
236240
/* Unwind python stack */
237241
for (int i = 0; i < STACK_MAX_LEN; ++i) {
238242
if (frame_ptr && get_frame_data(frame_ptr, pidData, &frame, &sym)) {
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// SPDX-License-Identifier: GPL-2.0
22
// Copyright (c) 2019 Facebook
33
#define STACK_MAX_LEN 600
4-
/* clang will not unroll the loop 600 times.
5-
* Instead it will unroll it to the amount it deemed
6-
* appropriate, but the loop will still execute 600 times.
7-
* Total program size is around 90k insns
4+
/* Full unroll of 600 iterations will have total
5+
* program size close to 298k insns and this may
6+
* cause BPF_JMP insn out of 16-bit integer range.
7+
* So limit the unroll size to 150 so the
8+
* total program size is around 80k insns but
9+
* the loop will still execute 600 times.
810
*/
11+
#define UNROLL_COUNT 150
912
#include "pyperf.h"

0 commit comments

Comments
 (0)