diff options
| author | Yonghong Song <yonghong.song@linux.dev> | 2026-08-18 22:53:09 -0700 |
|---|---|---|
| committer | Eduard Zingerman <eddyz87@gmail.com> | 2026-08-21 10:49:28 -0700 |
| commit | 0630ad00d96d9cf600c5c340cdecb363caa9d1cc (patch) | |
| tree | 8f1346b2de66693be0beb156247c151ba8ba5a31 /scripts | |
| parent | 991fb7823106bb2faa8a4871bc1d7c745201bac9 (diff) | |
| download | linux-next-0630ad00d96d9cf600c5c340cdecb363caa9d1cc.tar.gz linux-next-0630ad00d96d9cf600c5c340cdecb363caa9d1cc.zip | |
bpf: Add verifier support for 16-byte returns in R0: R2
LLVM 23 added support for returning a value in two registers for an
__int128, or a struct/union whose size is greater than 8 but not more than
16 bytes. See LLVM patches [1] and [2].
Before LLVM 23 the BPF backend could not return these values at all. A
by-value struct or union return (of any size) was rejected at compile time
with:
error: aggregate returns are not supported
and an __int128 return failed later in the backend with:
fatal error: error in backend: unable to allocate function return #1
Both are resolved in LLVM 23, which lowers such returns into the R0:R2
register pair.
Model that pair at calls to global and static BPF subprograms and at kfunc
calls: R2 is marked alongside R0 at the call, propagated out of a callee
at its exit, and held to the same scalar-only and no-stack-pointer rules
that already apply to R0. A struct returned by a kfunc must be composed of
scalars, since its bytes reach the program as raw register contents and a
pointer field would otherwise be laundered into a scalar.
An extension program is the one caller of the convention that cannot take
part in it: only R0 is checked at its exit, since that is the program exit
code, so it has no way to hand back an upper half. Replacing a function
whose return value is larger than 8 bytes is therefore rejected in
btf_check_func_type_match(). That function compares btf_type->info, which
carries no size for an int, so an 8 byte long and a 16 byte __int128
compared equal; sizes up to 8 bytes stay interchangeable, as they always
have been, so this only rejects what the R0:R2 convention newly makes
incompatible.
[1] https://github.com/llvm/llvm-project/pull/190894
[2] https://github.com/llvm/llvm-project/pull/206876
Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20260819055309.3297684-1-yonghong.song@linux.dev
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Diffstat (limited to 'scripts')
0 files changed, 0 insertions, 0 deletions
