> Was it compiled with -O0 ? > clang didn't even inline what was marked as __always_inline which is strange. > Make sure to use the latest clang with -O2 -target bpf -g -mcpu=v3 You're right, the optimisations got disabled somewhere along the road when I was debugging the problem. Re-tested with the compiler args you listed: libbpf: prog 'bpf_iden_max_ra': BPF program load failed: Permission denied libbpf: prog 'bpf_iden_max_ra': -- BEGIN PROG LOAD LOG -- 0: R1=ctx() R10=fp0 ; int BPF_PROG(bpf_iden_max_ra, struct bpf_fs_readahead_state *s) @ readahead_noop.c:7 0: (79) r1 = *(u64 *)(r1 +0) ; R1_w=scalar() ; return s->ra_pages; @ readahead_noop.c:9 1: (61) r0 = *(u32 *)(r1 +12) R1 invalid mem access 'scalar' processed 2 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0 -- END PROG LOAD LOG -- libbpf: prog 'bpf_iden_max_ra': failed to load: -13 libbpf: failed to load object '/root/readahead_noop.o' Stepping through the verifier in a debugger still shows the same problem, somehow the verifier thinks that the register is a `SCALAR_VALUE` instead of valid pointer. > You should see something like: > > llvm-objdump -S -r bpf_cubic.bpf.o|head -50 > > bpf_cubic.bpf.o: file format elf64-bpf > > Disassembly of section struct_ops/bpf_cubic_init: > > <... snip ...> Yep, the output matches. I'm building with `vmlinux.h` instead of linux/bpf.h but otherwise nothing has changed. Thanks, Isaac Khor