On Wed, Dec 6, 2023 at 6:13 AM Anton Protopopov <aspsk@xxxxxxxxxxxxx> wrote: > > + > +static __always_inline int __bpf_static_branch_jump(void *static_key) > +{ > + asm goto("1:\n\t" > + "goto %l[l_yes]\n\t" > + ".pushsection .jump_table, \"aw\"\n\t" > + ".balign 8\n\t" > + ".long 1b - .\n\t" > + ".long %l[l_yes] - .\n\t" > + ".quad %c0 - . + 1\n\t" > + ".popsection\n\t" > + :: "i" (static_key) > + :: l_yes); > + return 0; > +l_yes: > + return 1; > +} Could you add a test to patch 7 where the same subprog is used by multiple main progs and another test where a prog with static_keys is statically linked by libbpf into another prog? I suspect these cases are not handled by libbpf in the series. The adjustment of insn offsets is tricky and I don't see this logic in patch 5. The special handling of JA insn (if it's listed in static_branches_info[]) is fragile. The check_cfg() and the verifier main loop are two places so far, but JA is an unconditional jump. Every tool that understands BPF ISA would have to treat JA as "maybe it's not a jump in this case" and that is concerning. I certainly see the appeal of copy-pasting kernel's static_branch logic, but we can do better since we're not bound by x86 ISA. How about we introduce a new insn JA_MAYBE insn, and check_cfg and the verifier will process it as insn_idx += insn->off/imm _or_ insn_idx += 1. The new instruction will indicate that it may jump or fall through. Another bit could be used to indicate a "default" action (jump vs fallthrough) which will be used by JITs to translate into nop or jmp. Once it's a part of the instruction stream we can have bpf prog callable kfunc that can flip JA_MAYBE target (I think this feature is missing in the patch set. It's necessary to add an ability for bpf prog to flip static_branch. Currently you're proposing to do it from user space only), and there will be no need to supply static_branches_info[] at prog load time. The libbpf static linking will work as-is without extra code. JA_MAYBE will also remove the need for extra bpf map type. The bpf prog can _optionally_ do '.long 1b - .' asm trick and store the address of JA_MAYBE insn into an arbitrary 8 byte value (either in a global variable, a section or somewhere else). I think it's necessary to decouple patching of JA_MAYBE vs naming the location. The ".pushsection .jump_table" should be optional. The kernel's static_key approach hard codes them together, but it's due to x86 limitations. We can introduce JA_MAYBE and use it everywhere in the bpf prog and do not add names or addresses next to them. Then 'bpftool prog dump' can retrieve the insn stream and another command can patch a specific instruction (because JA_MAYBE is easy to spot vs regular JA). At the end it's just a text_poke_bp() to convert a target of JA_MAYBE. The bpf prog can be written with asm goto("go_maybe +0, %l[l_yes]") without names and maps, and the jumps will follow the indicated 'default' branch (how about, the 1st listed is default, the 2nd is maybe). The kernel static keys cannot be flipped atomically anyway, so multiple branches using the same static key is equivalent to an array of addresses that are flipped one by one. I suspect the main use case for isovalent is to compile a bpf prog with debug code that is not running by default and then flip various parts when debugging is necessary. With JA_MAYBE it's still going to be bpf_static_branch_[un]likely(), but no extra map and the prog will load fine. Then you can patch all of such insns or subset of them on demand. (The verifier will allow patching of JA_MAYBE only between two targets, so no safety issues). I think it's more flexible than the new map type and static_branches_info[]. wdyt?