Skip to content

Commit ba3b86b

Browse files
iii-iAlexei Starovoitov
authored andcommitted
s390/bpf: Implement new atomic ops
Implement BPF_AND, BPF_OR and BPF_XOR as the existing BPF_ADD. Since the corresponding machine instructions return the old value, BPF_FETCH happens by itself, the only additional thing that is required is zero-extension. There is no single instruction that implements BPF_XCHG on s390, so use a COMPARE AND SWAP loop. BPF_CMPXCHG, on the other hand, can be implemented by a single COMPARE AND SWAP. Zero-extension is automatically inserted by the verifier. Signed-off-by: Ilya Leoshkevich <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 23f50b5 commit ba3b86b

File tree

1 file changed

+55
-9
lines changed

1 file changed

+55
-9
lines changed

arch/s390/net/bpf_jit_comp.c

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,21 +1209,67 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
12091209
*/
12101210
case BPF_STX | BPF_ATOMIC | BPF_DW:
12111211
case BPF_STX | BPF_ATOMIC | BPF_W:
1212-
if (insn->imm != BPF_ADD) {
1212+
{
1213+
bool is32 = BPF_SIZE(insn->code) == BPF_W;
1214+
1215+
switch (insn->imm) {
1216+
/* {op32|op64} {%w0|%src},%src,off(%dst) */
1217+
#define EMIT_ATOMIC(op32, op64) do { \
1218+
EMIT6_DISP_LH(0xeb000000, is32 ? (op32) : (op64), \
1219+
(insn->imm & BPF_FETCH) ? src_reg : REG_W0, \
1220+
src_reg, dst_reg, off); \
1221+
if (is32 && (insn->imm & BPF_FETCH)) \
1222+
EMIT_ZERO(src_reg); \
1223+
} while (0)
1224+
case BPF_ADD:
1225+
case BPF_ADD | BPF_FETCH:
1226+
/* {laal|laalg} */
1227+
EMIT_ATOMIC(0x00fa, 0x00ea);
1228+
break;
1229+
case BPF_AND:
1230+
case BPF_AND | BPF_FETCH:
1231+
/* {lan|lang} */
1232+
EMIT_ATOMIC(0x00f4, 0x00e4);
1233+
break;
1234+
case BPF_OR:
1235+
case BPF_OR | BPF_FETCH:
1236+
/* {lao|laog} */
1237+
EMIT_ATOMIC(0x00f6, 0x00e6);
1238+
break;
1239+
case BPF_XOR:
1240+
case BPF_XOR | BPF_FETCH:
1241+
/* {lax|laxg} */
1242+
EMIT_ATOMIC(0x00f7, 0x00e7);
1243+
break;
1244+
#undef EMIT_ATOMIC
1245+
case BPF_XCHG:
1246+
/* {ly|lg} %w0,off(%dst) */
1247+
EMIT6_DISP_LH(0xe3000000,
1248+
is32 ? 0x0058 : 0x0004, REG_W0, REG_0,
1249+
dst_reg, off);
1250+
/* 0: {csy|csg} %w0,%src,off(%dst) */
1251+
EMIT6_DISP_LH(0xeb000000, is32 ? 0x0014 : 0x0030,
1252+
REG_W0, src_reg, dst_reg, off);
1253+
/* brc 4,0b */
1254+
EMIT4_PCREL_RIC(0xa7040000, 4, jit->prg - 6);
1255+
/* {llgfr|lgr} %src,%w0 */
1256+
EMIT4(is32 ? 0xb9160000 : 0xb9040000, src_reg, REG_W0);
1257+
if (is32 && insn_is_zext(&insn[1]))
1258+
insn_count = 2;
1259+
break;
1260+
case BPF_CMPXCHG:
1261+
/* 0: {csy|csg} %b0,%src,off(%dst) */
1262+
EMIT6_DISP_LH(0xeb000000, is32 ? 0x0014 : 0x0030,
1263+
BPF_REG_0, src_reg, dst_reg, off);
1264+
break;
1265+
default:
12131266
pr_err("Unknown atomic operation %02x\n", insn->imm);
12141267
return -1;
12151268
}
12161269

1217-
/* *(u32/u64 *)(dst + off) += src
1218-
*
1219-
* BFW_W: laal %w0,%src,off(%dst)
1220-
* BPF_DW: laalg %w0,%src,off(%dst)
1221-
*/
1222-
EMIT6_DISP_LH(0xeb000000,
1223-
BPF_SIZE(insn->code) == BPF_W ? 0x00fa : 0x00ea,
1224-
REG_W0, src_reg, dst_reg, off);
12251270
jit->seen |= SEEN_MEM;
12261271
break;
1272+
}
12271273
/*
12281274
* BPF_LDX
12291275
*/

0 commit comments

Comments
 (0)