]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
powerpc64/bpf: Implement PROBE_ATOMIC instructions
authorSaket Kumar Bhaskar <skb99@linux.ibm.com>
Thu, 4 Sep 2025 10:08:35 +0000 (15:38 +0530)
committerMadhavan Srinivasan <maddy@linux.ibm.com>
Sat, 6 Sep 2025 10:19:44 +0000 (15:49 +0530)
powerpc supports BPF atomic operations using a loop around
Load-And-Reserve(LDARX/LWARX) and Store-Conditional(STDCX/STWCX)
instructions gated by sync instructions to enforce full ordering.

To implement arena_atomics, arena vm start address is added to the
dst_reg to be used for both the LDARX/LWARX and STDCX/STWCX instructions.
Further, an exception table entry is added for LDARX/LWARX
instruction to land after the loop on fault. At the end of sequence,
dst_reg is restored by subtracting arena vm start address.

bpf_jit_supports_insn() is introduced to selectively enable instruction
support as in other architectures like x86 and arm64.

Reviewed-by: Hari Bathini <hbathini@linux.ibm.com>
Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Signed-off-by: Saket Kumar Bhaskar <skb99@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20250904100835.1100423-5-skb99@linux.ibm.com
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/net/bpf_jit_comp64.c

index cfa84cab0a1814238737880b1d341d5ae8c16ad0..88ad5ba7b87fd01166c9c3556d0ddf24032ab0f3 100644 (file)
@@ -450,6 +450,22 @@ bool bpf_jit_supports_far_kfunc_call(void)
        return IS_ENABLED(CONFIG_PPC64);
 }
 
+bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
+{
+       if (!in_arena)
+               return true;
+       switch (insn->code) {
+       case BPF_STX | BPF_ATOMIC | BPF_H:
+       case BPF_STX | BPF_ATOMIC | BPF_B:
+       case BPF_STX | BPF_ATOMIC | BPF_W:
+       case BPF_STX | BPF_ATOMIC | BPF_DW:
+               if (bpf_atomic_is_load_store(insn))
+                       return false;
+               return IS_ENABLED(CONFIG_PPC64);
+       }
+       return true;
+}
+
 void *arch_alloc_bpf_trampoline(unsigned int size)
 {
        return bpf_prog_pack_alloc(size, bpf_jit_fill_ill_insns);
index cb4d1e95496132313fdb075e7ff3f39d902e4224..1fe37128c87640dd61d3debdd3596884f2e2f9f2 100644 (file)
@@ -1163,6 +1163,32 @@ emit_clear:
 
                        break;
 
+               /*
+                * BPF_STX PROBE_ATOMIC (arena atomic ops)
+                */
+               case BPF_STX | BPF_PROBE_ATOMIC | BPF_W:
+               case BPF_STX | BPF_PROBE_ATOMIC | BPF_DW:
+                       EMIT(PPC_RAW_ADD(dst_reg, dst_reg, bpf_to_ppc(ARENA_VM_START)));
+                       ret = bpf_jit_emit_atomic_ops(image, ctx, &insn[i],
+                                                     &jmp_off, &tmp_idx, &addrs[i + 1]);
+                       if (ret) {
+                               if (ret == -EOPNOTSUPP) {
+                                       pr_err_ratelimited(
+                                               "eBPF filter atomic op code %02x (@%d) unsupported\n",
+                                               code, i);
+                               }
+                               return ret;
+                       }
+                       /* LDARX/LWARX should land here on exception. */
+                       ret = bpf_add_extable_entry(fp, image, fimage, pass, ctx,
+                                                   tmp_idx, jmp_off, dst_reg, code);
+                       if (ret)
+                               return ret;
+
+                       /* Retrieve the dst_reg */
+                       EMIT(PPC_RAW_SUB(dst_reg, dst_reg, bpf_to_ppc(ARENA_VM_START)));
+                       break;
+
                /*
                 * BPF_STX ATOMIC (atomic ops)
                 */