Commit 06a33d02 authored by Pu Lehui's avatar Pu Lehui Committed by Daniel Borkmann
Browse files

riscv, bpf: Optimize bswap insns with Zbb support



Optimize bswap instructions by rev8 Zbb instruction conbined with srli
instruction. And Optimize 16-bit zero-extension with Zbb support.

Signed-off-by: default avatarPu Lehui <pulehui@huawei.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Tested-by: default avatarBjörn Töpel <bjorn@rivosinc.com>
Acked-by: default avatarBjörn Töpel <bjorn@kernel.org>
Link: https://lore.kernel.org/bpf/20240115131235.2914289-7-pulehui@huaweicloud.com
parent 519fb722
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -1146,12 +1146,81 @@ static inline void emit_sextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
	emit_addiw(rd, rs, 0, ctx);
}

static inline void emit_zexth(u8 rd, u8 rs, struct rv_jit_context *ctx)
{
	if (rvzbb_enabled()) {
		emit(rvzbb_zexth(rd, rs), ctx);
		return;
	}

	emit_slli(rd, rs, 48, ctx);
	emit_srli(rd, rd, 48, ctx);
}

static inline void emit_zextw(u8 rd, u8 rs, struct rv_jit_context *ctx)
{
	emit_slli(rd, rs, 32, ctx);
	emit_srli(rd, rd, 32, ctx);
}

static inline void emit_bswap(u8 rd, s32 imm, struct rv_jit_context *ctx)
{
	if (rvzbb_enabled()) {
		int bits = 64 - imm;

		emit(rvzbb_rev8(rd, rd), ctx);
		if (bits)
			emit_srli(rd, rd, bits, ctx);
		return;
	}

	emit_li(RV_REG_T2, 0, ctx);

	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
	emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
	emit_srli(rd, rd, 8, ctx);
	if (imm == 16)
		goto out_be;

	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
	emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
	emit_srli(rd, rd, 8, ctx);

	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
	emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
	emit_srli(rd, rd, 8, ctx);
	if (imm == 32)
		goto out_be;

	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
	emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
	emit_srli(rd, rd, 8, ctx);

	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
	emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
	emit_srli(rd, rd, 8, ctx);

	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
	emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
	emit_srli(rd, rd, 8, ctx);

	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
	emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
	emit_srli(rd, rd, 8, ctx);
out_be:
	emit_andi(RV_REG_T1, rd, 0xff, ctx);
	emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);

	emit_mv(rd, RV_REG_T2, ctx);
}

#endif /* __riscv_xlen == 64 */

void bpf_jit_build_prologue(struct rv_jit_context *ctx);
+2 −48
Original line number Diff line number Diff line
@@ -1177,8 +1177,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
	case BPF_ALU | BPF_END | BPF_FROM_LE:
		switch (imm) {
		case 16:
			emit_slli(rd, rd, 48, ctx);
			emit_srli(rd, rd, 48, ctx);
			emit_zexth(rd, rd, ctx);
			break;
		case 32:
			if (!aux->verifier_zext)
@@ -1189,54 +1188,9 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
			break;
		}
		break;

	case BPF_ALU | BPF_END | BPF_FROM_BE:
	case BPF_ALU64 | BPF_END | BPF_FROM_LE:
		emit_li(RV_REG_T2, 0, ctx);

		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
		emit_srli(rd, rd, 8, ctx);
		if (imm == 16)
			goto out_be;

		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
		emit_srli(rd, rd, 8, ctx);

		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
		emit_srli(rd, rd, 8, ctx);
		if (imm == 32)
			goto out_be;

		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
		emit_srli(rd, rd, 8, ctx);

		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
		emit_srli(rd, rd, 8, ctx);

		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
		emit_srli(rd, rd, 8, ctx);

		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);
		emit_slli(RV_REG_T2, RV_REG_T2, 8, ctx);
		emit_srli(rd, rd, 8, ctx);
out_be:
		emit_andi(RV_REG_T1, rd, 0xff, ctx);
		emit_add(RV_REG_T2, RV_REG_T2, RV_REG_T1, ctx);

		emit_mv(rd, RV_REG_T2, ctx);
		emit_bswap(rd, imm, ctx);
		break;

	/* dst = imm */