Re: [PATCH bpf-next v1 0/8] bpf: magic kernel functions

Andrii Nakryiko
2025-10-30T20:39:18Z

On Thu, Oct 30, 2025 at 1:02 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> On 10/30/25 12:47 PM, Andrii Nakryiko wrote:
> > On Thu, Oct 30, 2025 at 11:46 AM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
> >>
> >> On 10/30/25 11:26 AM, Alan Maguire wrote:
> >>> On 30/10/2025 18:14, Eduard Zingerman wrote:
> >>>> On Wed, 2025-10-29 at 23:11 -0700, Eduard Zingerman wrote:
> >>>>> On Wed, 2025-10-29 at 17:44 -0700, Eduard Zingerman wrote:
> >>>>>> On Wed, 2025-10-29 at 12:01 -0700, Ihor Solodrai wrote:
> >>>>>>
> >>>>>> [...]
> >>>>
> >>>> Scheme discussed off-list for new functions with __implicit args:
> >>>> - kernel source code:
> >>>>
> >>>> __bpf_kfunc void foo(struct bpf_prog_aux p__implicit)
> >>>> BTF_ID_FLAGS(foo, KF_IMPLICIT_ARGS)
> >>>>
> >>>> - pahole:
> >>>> - renames foo to foo_impl
> >>>> - adds bpf-side definition for 'foo' w/o implicit args
> >>>> vmlinux btf:
> >>>>
> >>>> __bpf_kfunc void foo_impl(struct bpf_prog_aux p__implicit);
> >>>> void foo(void);
> >>>>
> >>>> - resolve_btfids puts the 'foo' (the one w/o implicit args) id to all
> >>>> id lists (no changes needed for this, follows from pahole changes);
> >>>> - verifier.c:add_kfunc_call()
> >>>> - Sees the id of 'foo' and kfunc flags with KF_IMPLICIT_ARGS
> >>>> - Replaces the id with id of 'foo_impl'.
> >>>>
> >>>> This will break the following scenario:
> >>>> - new kfunc is added with __implicit arg
> >>>> - kernel is built with old pahole
> >>>> - vmlinux.h is generated for such kernel
> >>>> - bpf program is compiled against such vmlinux.h
> >>>> - attempt to run such program on a new kernel compiled with new pahole
> >>>> will fail.
> >>>>
> >>>> Andrei and Alexei deemed this acceptable.
> >>>
> >>> Okay so bear with me as this is probably a massive over-simplification.
> >>> It seems like what we want here is a way to establish a relationship
> >>> between the BTF associated with the _impl function and the kfunc-visible
> >>> form (without the implicit arguments), right? Once we have that
> >>> relationship, it's sort of implicit which are the implicit arguments;
> >>> they're the ones the _impl variant has and the non-impl variant doesn't
> >>> have. So to me - and again I'm probably missing a lot - the key thing is
> >>> to establish that relationship between kfunc and kfunc_impl. Couldn't we
> >>> leverage the kernel build machinery around resolve_btf_ids to construct
> >>> these pairwise mappings of BTF ids? That way we keep pahole out of the
> >>> loop (aside from generating BTF for both variants as usual) and
> >>> compatibility issues aren't there as much because resolve_btfids travels
> >>> with the kernel, no changes needed for pahole.
> >>
> >> We've had a couple of rounds of back and forth on this.
> >>
> >> The reasoning here is that going forward we want to make a kfunc with
> >> implicit arguments easy to define. That is:
> >>
> >> __bpf_kfunc int bpf_kfunc(int arg, struct bpf_prog_aux *aux__impl) {}
> >
> > I don't think we even need __impl suffix for argument name with
> > KF_IMPLICIT_ARGS, right?
>
> I mentioned options that we discussed before in the cover letter.
>
> Basically, pahole needs to figure out how many arguments to omit *somehow*.
> Using a name suffix (aka annotation) seems to be the most flexible way, as
> it allows to avoid changes in pahole if/when we add new implicit arg types.

Ah, right, I forgot we discussed this. Ok, arg suffix isn't too bad.

>
> >
> >> BTF_ID_FLAGS(func, bpf_kfunc, KF_IMPLICIT_ARGS)
> >>
> >> That's it.
> >>
> >> In order to keep pahole out of the loop, it's necessary to have both
> >> interface and implementation declarations in the kernel. Something
> >> like this:
> >>
> >> __bpf_kfunc_interface int bpf_kfunc(int arg) {}
> >> __bpf_kfunc int bpf_kfunc_impl(int arg, struct bpf_prog_aux *aux__impl) {}
> >> BTF_ID_FLAGS(func, bpf_kfunc, KF_IMPLICIT_ARGS)
> >>
> >> Which shifts most of the burden of resolving KF_IMPLICIT_ARGS to the
> >> verifier. But then of course both variants will be callable from BPF,
> >> which is another thing we'd like to avoid.
> >>
> >> pahole provides an ability to modify BTF only, and make that
> >> bpf_kfunc_impl (almost) invisible to the user, which is great.
> >>
> >> The downside is that maintaining backwards compatibility between
> >> kernel, pahole and BPF binaries is difficult.
> >>
> >
> > I think we should differentiate backwards compat for all existing
> > _impl kfuncs and BPF programs that used to work with them, and then,
> > separately, what happens going forward with newly added non-_impl
> > kfuncs with KF_IMPLICIT_ARGS and BPF programs that want to make use of
> > these _impl-less kfuncs.
> >
> > For existing _impl kfuncs ("legacy" case), backwards compat is 100%
> > preserved, even if the kernel was built with an old pahole that
> > doesn't yet know about KF_IMPLICTI_ARGS. There will be BTF for both
> > _impl and _impl-less func_protos, all that will work. And BPF programs
> > are explicitly calling _impl kfuncs. So even if pahole didn't do
> > anything special for KF_IMPLICIT_ARGS, verifier should work fine, it
> > will find _impl BTF, etc.
> >
> > For all new _impl-less kfunc definitions and/or BPF programs that
> > switch to _impl-less calls, yes, we will document and require that
> > kernel BTF has to be generated with a newer pahole. We can enforce
> > that in Kconfig, but it's a bit too strict/too soon as it's irrelevant
> > and unnecessary for the majority of BPF users that don't care about
> > _impl-less stuff.
>
> I think some kind of build-time enforcement will be necessary.
> It's *very* easy to unintentionally use old(-er) pahole version
> for kernel build, especially when the new version is recent.
>

I'd try to avoid failing kernel build if pahole is not recent enough
for this feature.

How about we teach resolve_btfids() to check whether kernel BTF is
"conformant" (i.e., it has xxx and xxx_impl func_protos, and xxx
doesn't have implicit args, while _impl has implicit args), and if
it's not conformant, we just effectively make such _impl-less kfunc
not a kfunc. Would resolving such BTF_ID to zero do the trick?

> >
> > Keep in mind, right now we have 4-5 such _impl special functions, but
> > going forward we will probably have lots. sched-ext is poised to use
> > that very extensively throughout a lot of its kfuncs, so requiring
> > these explicit _impl wrappers just to support older pahole with newer
> > kernels I think doesn't make sense in the grand scheme of things.
> > Getting the latest pahole released/packaged/used for kernel build for
> > distros shouldn't be a big deal at all. It's not really like upgrading
> > the compiler toolchain at all.
> >
> >>
> >>>
> >>> I'm guessing the above is missing something though?
> >>>
> >>> Thanks!
> >>>
> >>> Alan
> >>
>