diff options
| author | Eduard Zingerman <eddyz87@gmail.com> | 2026-08-21 10:40:05 -0700 |
|---|---|---|
| committer | Eduard Zingerman <eddyz87@gmail.com> | 2026-08-21 10:49:28 -0700 |
| commit | 4954de7dbd1cfafecafcf7e4e801c50c11be49d9 (patch) | |
| tree | 4971425c2403208d1f43329875736ec5cb5eed68 /scripts/Makefile.thinlto | |
| parent | da13c047cda6ef1bbc9355adb040d5b4eecea710 (diff) | |
| parent | d50d9a06c86a76e800071d184d05c9cdbfa1ec4b (diff) | |
| download | linux-next-4954de7dbd1cfafecafcf7e4e801c50c11be49d9.tar.gz linux-next-4954de7dbd1cfafecafcf7e4e801c50c11be49d9.zip | |
Merge branch 'bpf-support-aggregate-return-values-up-to-16-bytes'
Yonghong Song says:
====================
bpf: Support aggregate return values up to 16 bytes
LLVM 23 can return an __int128, or a struct/union larger than 8 bytes and
no larger than 16 bytes, in the BPF R0:R2 register pair [1][2]. Before
that the BPF backend could not return such values at all: a by-value
aggregate return was rejected at compile time with "aggregate returns are
not supported", and an __int128 return failed in the backend with "unable
to allocate function return #1".
This series teaches the kernel the same convention, so that BPF programs
and kfuncs can return these values. The first 8 bytes of the value come
back in R0 and the second 8 bytes in R2. It applies to kfunc returns and
to BPF-to-BPF subprogram returns, both global and static. The main program
is unchanged: its return value is the program's exit code, so a return
larger than 8 bytes is still rejected at BPF_EXIT.
Patches 1-2 are preparation: patch 1 factors out the per-register check
used by the global return path, and patch 2 adds the shared helpers that
answer "does this subprogram return a register pair", so that the patches
which follow can be ordered independently. Patch 3 wires up the JIT side.
Patches 4-5 teach precision backtracking and live register analysis about
R2 as a second return register, ahead of the patch that starts modeling it.
Patch 6 adds the verifier support proper. Patch 7 relaxes
btf_distill_func_proto() and btf_validate_return_type(), which is what
makes the whole thing reachable. Patches 8-9 add selftests and patch 10
documents the convention.
Constraints worth calling out:
- A by-value struct or union returned by a kfunc or by a global subprogram
must be composed only of scalars. The verifier models the returned
register bits as an unknown scalar, so a pointer member would be
laundered into one and escape provenance and reference tracking. A
static subprogram is verified inline and is not restricted this way.
- Returning the pair from a kfunc needs the JIT to place the second half
into R2, which is architecture-specific work. Architectures opt in
through bpf_jit_supports_kfunc_ret_reg_pair(); x86_64, arm64 and riscv64
do so here, and elsewhere bpf_add_kfunc_call() rejects such a kfunc with
-EOPNOTSUPP. A register-pair return from a BPF subprogram needs no such
capability.
- The pair is modelled only when the JIT is enabled, since the interpreter
propagates R0 alone out of a subprogram. Modelling it sets jit_required,
so a JIT fallback to the interpreter becomes a load failure rather than
a silent divergence from what was verified. With the JIT off, the pair
is not modelled and a caller reading R2 fails verification.
- The compiler side requires LLVM 23 or newer. The selftests written in C
sit behind a __clang_major__ guard; an older compiler builds a dummy
test instead, whose description says why nothing was exercised. The
inline-asm tests run everywhere, apart from the few whose callee
prototype returns a struct or union by value, which are guarded the
same way.
[1] https://github.com/llvm/llvm-project/pull/190894
[2] https://github.com/llvm/llvm-project/pull/206876
Changelog:
v6 -> v7:
- v6: https://lore.kernel.org/bpf/20260817042141.2286086-1-yonghong.song@linux.dev/
- Simplify type checking in function bpf_compute_subprog_ret_regs().
- Add __load_if_JITed() for a few negative tests.
- Adjust a few comments and error message.
v5 -> v6:
- v5: https://lore.kernel.org/bpf/20260813200210.1991507-1-yonghong.song@linux.dev/
- Returning R0 only if jit is not enabled. If jit is enabled, main prog will
not force jit even if main prog may return R0:R2.
- Simplify precision backtracking.
- Check returning R0:R2 in btf_check_func_type_match().
- Remove some redundant tests.
v4 -> v5:
- v4: https://lore.kernel.org/bpf/20260811000911.2378679-1-yonghong.song@linux.dev/
- Removed R0:R2 restriction on callback functions and its related tests.
- Simplify the code for backtracking.
- Reduce comments and verify R0/R2 together.
- Use RUN_TESTS for selftests.
v3 -> v4:
- v3: https://lore.kernel.org/bpf/20260808190322.1896580-1-yonghong.song@linux.dev/
- Fix a few kernel comment format.
- Guard more kfunc's with x86_64/arm64 only to avoid s390x failure.
v2 -> v3:
- v2: https://lore.kernel.org/bpf/20260804203522.1869244-1-yonghong.song@linux.dev/
- Add additional guard with __SIZEOF_INT128__ for 32bit kernel.
- Guard little endian to avoid arm64 big endian for selftests.
- Fix test failures for gcc15.
- Rebase to avoid conflict with latest master branch.
v1 -> v2:
- v1: https://lore.kernel.org/bpf/20260708200939.2153664-1-yonghong.song@linux.dev/
- Split the R0:R2 helpers out of the verifier patch into their own
preparation patch, and reordered the series so the core verifier patch
comes after the infrastructure it depends on.
- New patch rejecting callbacks that return more than 8 bytes, both
helper/kfunc callbacks and exception callbacks, with selftests.
- New patch rejecting a register-pair return once btf_check_subprog_call()
has marked the subprogram's BTF unreliable, rather than silently
mistracking R2.
- Folded "bpf: Force JIT for programs using the R0:R2 register pair" into
the verifier patch.
- Dropped "bpf: Reject >8 byte return values on return-reading trampoline
paths" and its selftests; that went in separately as commit
c48796aa6c39.
- Described the register mapping as the first and second 8 bytes rather
than the low and high 64 bits, which is only correct on little-endian,
and reworded "16-byte" to "up to 16 bytes" where the range 9..16 was
meant.
====================
Link: https://patch.msgid.link/20260819055239.3293449-1-yonghong.song@linux.dev
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Diffstat (limited to 'scripts/Makefile.thinlto')
0 files changed, 0 insertions, 0 deletions
