From 65112709115f48f16d7082bcabf173d08622e69f Mon Sep 17 00:00:00 2001 From: Hari Bathini Date: Fri, 10 Jun 2022 21:25:48 +0530 Subject: powerpc/bpf/64: add support for BPF_ATOMIC bitwise operations Adding instructions for ppc64 for atomic[64]_and atomic[64]_or atomic[64]_xor Signed-off-by: Hari Bathini Tested-by: Naveen N. Rao (ppc64le) Reviewed-by: Naveen N. Rao Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20220610155552.25892-2-hbathini@linux.ibm.com --- arch/powerpc/net/bpf_jit_comp64.c | 57 ++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 594c54931e20..c421bedd0e98 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -777,41 +777,42 @@ emit_clear: * BPF_STX ATOMIC (atomic ops) */ case BPF_STX | BPF_ATOMIC | BPF_W: - if (imm != BPF_ADD) { - pr_err_ratelimited( - "eBPF filter atomic op code %02x (@%d) unsupported\n", - code, i); - return -ENOTSUPP; - } - - /* *(u32 *)(dst + off) += src */ - - /* Get EA into TMP_REG_1 */ - EMIT(PPC_RAW_ADDI(tmp1_reg, dst_reg, off)); + case BPF_STX | BPF_ATOMIC | BPF_DW: + /* Get offset into TMP_REG_1 */ + EMIT(PPC_RAW_LI(tmp1_reg, off)); tmp_idx = ctx->idx * 4; /* load value from memory into TMP_REG_2 */ - EMIT(PPC_RAW_LWARX(tmp2_reg, 0, tmp1_reg, 0)); - /* add value from src_reg into this */ - EMIT(PPC_RAW_ADD(tmp2_reg, tmp2_reg, src_reg)); - /* store result back */ - EMIT(PPC_RAW_STWCX(tmp2_reg, 0, tmp1_reg)); - /* we're done if this succeeded */ - PPC_BCC_SHORT(COND_NE, tmp_idx); - break; - case BPF_STX | BPF_ATOMIC | BPF_DW: - if (imm != BPF_ADD) { + if (size == BPF_DW) + EMIT(PPC_RAW_LDARX(tmp2_reg, tmp1_reg, dst_reg, 0)); + else + EMIT(PPC_RAW_LWARX(tmp2_reg, tmp1_reg, dst_reg, 0)); + + switch (imm) { + case BPF_ADD: + EMIT(PPC_RAW_ADD(tmp2_reg, tmp2_reg, src_reg)); + break; + case BPF_AND: + EMIT(PPC_RAW_AND(tmp2_reg, tmp2_reg, src_reg)); + break; + case BPF_OR: + EMIT(PPC_RAW_OR(tmp2_reg, tmp2_reg, src_reg)); + break; + case BPF_XOR: + EMIT(PPC_RAW_XOR(tmp2_reg, tmp2_reg, src_reg)); + break; + default: pr_err_ratelimited( "eBPF filter atomic op code %02x (@%d) unsupported\n", code, i); - return -ENOTSUPP; + return -EOPNOTSUPP; } - /* *(u64 *)(dst + off) += src */ - EMIT(PPC_RAW_ADDI(tmp1_reg, dst_reg, off)); - tmp_idx = ctx->idx * 4; - EMIT(PPC_RAW_LDARX(tmp2_reg, 0, tmp1_reg, 0)); - EMIT(PPC_RAW_ADD(tmp2_reg, tmp2_reg, src_reg)); - EMIT(PPC_RAW_STDCX(tmp2_reg, 0, tmp1_reg)); + /* store result back */ + if (size == BPF_DW) + EMIT(PPC_RAW_STDCX(tmp2_reg, tmp1_reg, dst_reg)); + else + EMIT(PPC_RAW_STWCX(tmp2_reg, tmp1_reg, dst_reg)); + /* we're done if this succeeded */ PPC_BCC_SHORT(COND_NE, tmp_idx); break; -- cgit