On Wed, Dec 11, 2019 at 01:30:13PM +0100, Björn Töpel wrote: > + > +#define DEFINE_BPF_DISPATCHER(name) \ > + unsigned int name##func( \ > + const void *xdp_ctx, \ > + const struct bpf_insn *insnsi, \ > + unsigned int (*bpf_func)(const void *, \ > + const struct bpf_insn *)) \ > + { \ > + return bpf_func(xdp_ctx, insnsi); \ > + } \ > + EXPORT_SYMBOL(name##func); \ > + struct bpf_dispatcher name = BPF_DISPATCHER_INIT(name); The dispatcher function is a normal function. EXPORT_SYMBOL doesn't make it 'noinline'. struct bpf_dispatcher takes a pointer to it and that address is used for text_poke. In patch 3 __BPF_PROG_RUN calls dfunc() from two places. What stops compiler from inlining it? Or partially inlining it in one or the other place? I guess it works, because your compiler didn't inline it? Could you share how asm looks for bpf_prog_run_xdp() (where __BPF_PROG_RUN is called) and asm for name##func() ? I hope my guess that compiler didn't inline it is correct. Then extra noinline will not hurt and that's the only thing needed to avoid the issue.