Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

s390/bpf: Emit a barrier for BPF_FETCH instructions

BPF_ATOMIC_OP() macro documentation states that "BPF_ADD | BPF_FETCH"
should be the same as atomic_fetch_add(), which is currently not the
case on s390x: the serialization instruction "bcr 14,0" is missing.
This applies to "and", "or" and "xor" variants too.

s390x is allowed to reorder stores with subsequent fetches from
different addresses, so code relying on BPF_FETCH acting as a barrier,
for example:

stw [%r0], 1
afadd [%r1], %r2
ldxw %r3, [%r4]

may be broken. Fix it by emitting "bcr 14,0".

Note that a separate serialization instruction is not needed for
BPF_XCHG and BPF_CMPXCHG, because COMPARE AND SWAP performs
serialization itself.

Fixes: ba3b86b9cef0 ("s390/bpf: Implement new atomic ops")
Reported-by: Puranjay Mohan <puranjay12@gmail.com>
Closes: https://lore.kernel.org/bpf/mb61p34qvq3wf.fsf@kernel.org/
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reviewed-by: Puranjay Mohan <puranjay@kernel.org>
Link: https://lore.kernel.org/r/20240507000557.12048-1-iii@linux.ibm.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Ilya Leoshkevich and committed by
Alexei Starovoitov
68378982 55302bc1

+6 -2
+6 -2
arch/s390/net/bpf_jit_comp.c
··· 1427 1427 EMIT6_DISP_LH(0xeb000000, is32 ? (op32) : (op64), \ 1428 1428 (insn->imm & BPF_FETCH) ? src_reg : REG_W0, \ 1429 1429 src_reg, dst_reg, off); \ 1430 - if (is32 && (insn->imm & BPF_FETCH)) \ 1431 - EMIT_ZERO(src_reg); \ 1430 + if (insn->imm & BPF_FETCH) { \ 1431 + /* bcr 14,0 - see atomic_fetch_{add,and,or,xor}() */ \ 1432 + _EMIT2(0x07e0); \ 1433 + if (is32) \ 1434 + EMIT_ZERO(src_reg); \ 1435 + } \ 1432 1436 } while (0) 1433 1437 case BPF_ADD: 1434 1438 case BPF_ADD | BPF_FETCH: