From 898343edde4797d58e3b6ced72e9b9497a1c82c7 Mon Sep 17 00:00:00 2001 From: Maxim Khmelevskii Date: Thu, 23 Jul 2026 16:03:50 +0200 Subject: [PATCH] s390/bpf: Support load-acquire and store-release instructions Support load-acquire (BPF_LOAD_ACQ) and store-release (BPF_STORE_REL) instructions. Since s390 has strong memory model, implement them as regular BPF_LDX/BPF_STX instructions. Tested with: ./test_progs -t verifier_load_acquire,verifier_store_release,atomics Signed-off-by: Maxim Khmelevskii Reviewed-by: Ilya Leoshkevich Link: https://lore.kernel.org/bpf/20260723140648.583055-7-max@linux.ibm.com Signed-off-by: Kumar Kartikeya Dwivedi --- arch/s390/net/bpf_jit_comp.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 20c9533f2368..b60877478b45 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -743,10 +743,12 @@ static void bpf_jit_probe_load_pre(struct bpf_jit *jit, struct bpf_insn *insn, { if (BPF_MODE(insn->code) != BPF_PROBE_MEM && BPF_MODE(insn->code) != BPF_PROBE_MEMSX && - BPF_MODE(insn->code) != BPF_PROBE_MEM32) + BPF_MODE(insn->code) != BPF_PROBE_MEM32 && + BPF_MODE(insn->code) != BPF_PROBE_ATOMIC) return; - if (BPF_MODE(insn->code) == BPF_PROBE_MEM32) { + if (BPF_MODE(insn->code) == BPF_PROBE_MEM32 || + BPF_MODE(insn->code) == BPF_PROBE_ATOMIC) { /* lgrl %r1,kern_arena */ EMIT6_PCREL_RILB(0xc4080000, REG_W1, jit->kern_arena); probe->arena_reg = REG_W1; @@ -758,7 +760,8 @@ static void bpf_jit_probe_load_pre(struct bpf_jit *jit, struct bpf_insn *insn, static void bpf_jit_probe_store_pre(struct bpf_jit *jit, struct bpf_insn *insn, struct bpf_jit_probe *probe) { - if (BPF_MODE(insn->code) != BPF_PROBE_MEM32) + if (BPF_MODE(insn->code) != BPF_PROBE_MEM32 && + BPF_MODE(insn->code) != BPF_PROBE_ATOMIC) return; /* lgrl %r1,kern_arena */ @@ -1621,11 +1624,11 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, bool is32 = BPF_SIZE(insn->code) == BPF_W; /* - * Unlike loads and stores, atomics have only a base register, - * but no index register. For the non-arena case, simply use - * %dst as a base. For the arena case, use the work register - * %r1: first, load the arena base into it, and then add %dst - * to it. + * Unlike loads and stores, s390 atomics have only a base + * register, but no index register. For the non-arena case, + * simply use %dst as a base. For the arena case, use the + * work register %r1: first, load the arena base into it, + * and then add %dst to it. */ probe.arena_reg = dst_reg; @@ -1712,6 +1715,18 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, if (err < 0) return err; break; + case BPF_LOAD_ACQ: + /* s390 has strong ordering, just use load */ + err = emit_ldx(jit, fp, insn); + if (err < 0) + return err; + break; + case BPF_STORE_REL: + /* s390 has strong ordering, just use store */ + err = emit_stx(jit, fp, insn); + if (err < 0) + return err; + break; default: pr_err("Unknown atomic operation %02x\n", insn->imm); return -1;