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 <max@linux.ibm.com>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Link: https://lore.kernel.org/bpf/20260723140648.583055-7-max@linux.ibm.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
Maxim Khmelevskii 2026-07-23 16:03:50 +02:00 committed by Kumar Kartikeya Dwivedi
parent 2d7f576c9d
commit 898343edde
No known key found for this signature in database
GPG Key ID: 472D377B63542F83

View File

@ -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;