[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <ZPehLN6cUFL+AT/B@shell.armlinux.org.uk>
Date: Tue, 5 Sep 2023 22:44:12 +0100
From: "Russell King (Oracle)" <linux@...linux.org.uk>
To: Puranjay Mohan <puranjay12@...il.com>
Cc: Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Andrii Nakryiko <andrii@...nel.org>,
Martin KaFai Lau <martin.lau@...ux.dev>,
Song Liu <song@...nel.org>,
Yonghong Song <yonghong.song@...ux.dev>,
John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...nel.org>,
Stanislav Fomichev <sdf@...gle.com>,
Hao Luo <haoluo@...gle.com>, Jiri Olsa <jolsa@...nel.org>,
Shubham Bansal <illusionist.neo@...il.com>,
Mykola Lysenko <mykolal@...com>, Shuah Khan <shuah@...nel.org>,
bpf@...r.kernel.org, linux-kselftest@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH bpf-next 5/8] arm32, bpf: add support for 32-bit signed
division
On Tue, Sep 05, 2023 at 09:06:18PM +0000, Puranjay Mohan wrote:
> The cpuv4 added a new BPF_SDIV instruction that does signed division.
> The encoding is similar to BPF_DIV but BPF_SDIV sets offset=1.
>
> ARM32 already supports 32-bit BPF_DIV which can be easily extended to
> support BPF_SDIV as ARM32 has the SDIV instruction. When the CPU is not
> ARM-v7, we implement that SDIV/SMOD with the function call similar to
> the implementation of DIV/MOD.
>
> Signed-off-by: Puranjay Mohan <puranjay12@...il.com>
> ---
> arch/arm/net/bpf_jit_32.c | 26 ++++++++++++++++++++------
> arch/arm/net/bpf_jit_32.h | 2 ++
> 2 files changed, 22 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
> index 09496203f13e..f580ecf75710 100644
> --- a/arch/arm/net/bpf_jit_32.c
> +++ b/arch/arm/net/bpf_jit_32.c
> @@ -228,6 +228,16 @@ static u32 jit_mod32(u32 dividend, u32 divisor)
> return dividend % divisor;
> }
>
> +static s32 jit_sdiv32(s32 dividend, s32 divisor)
> +{
> + return dividend / divisor;
> +}
> +
> +static s32 jit_smod32(s32 dividend, s32 divisor)
> +{
> + return dividend % divisor;
> +}
> +
> static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
> {
> inst |= (cond << 28);
> @@ -477,7 +487,7 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
> return to - from - 2;
> }
>
> -static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
> +static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op, u8 sign)
> {
> const int exclude_mask = BIT(ARM_R0) | BIT(ARM_R1);
> const s8 *tmp = bpf2a32[TMP_REG_1];
> @@ -485,9 +495,10 @@ static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
> #if __LINUX_ARM_ARCH__ == 7
> if (elf_hwcap & HWCAP_IDIVA) {
> if (op == BPF_DIV)
> - emit(ARM_UDIV(rd, rm, rn), ctx);
> + sign ? emit(ARM_SDIV(rd, rm, rn), ctx) : emit(ARM_UDIV(rd, rm, rn), ctx);
Oh no, let's not go using the ternary operator like that. If we want
to use the ternary operator, then:
emit(sign ? ARM_SDIV(rd, rm, rn) :
ARM_UDIV(rd, rm, rn), ctx);
would be _much_ better, since what is actually conditional is the value
passed to emit().
If we want to avoid the ternary operator altogether, then obviously
if() emit() else emit(), but I'd prefer my suggestion above.
> /* Call appropriate function */
> - emit_mov_i(ARM_IP, op == BPF_DIV ?
> - (u32)jit_udiv32 : (u32)jit_mod32, ctx);
> + if (sign)
> + emit_mov_i(ARM_IP, op == BPF_DIV ? (u32)jit_sdiv32 : (u32)jit_smod32, ctx);
> + else
> + emit_mov_i(ARM_IP, op == BPF_DIV ? (u32)jit_udiv32 : (u32)jit_mod32, ctx);
u32 dst;
if (sign) {
if (op == BPF_DIV)
dst = (u32)jit_sdiv32;
else
dst = (u32)jit_smod32;
} else {
if (op == BPF_DIV)
dst = (u32)jit_udiv32;
else
dst = (u32)hit_mod32;
}
emit_mov_i(ARM_IP, dst, dtx);
> emit_blx_r(ARM_IP, ctx);
>
> /* Restore caller-saved registers from stack */
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Powered by blists - more mailing lists