Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,18 @@ config TOOLCHAIN_HAS_ZBB
depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900
depends on AS_HAS_OPTION_ARCH

config RISCV_ISA_ZBA
bool "Zba extension support for bit manipulation instructions"
default y
help
Add support for enabling optimisations in the kernel when the Zba
extension is detected at boot.

The Zba extension provides instructions to accelerate the generation
of addresses that index into arrays of basic data types.

If you don't know what to do here, say Y.

config RISCV_ISA_ZBB
bool "Zbb extension support for bit manipulation instructions"
depends on TOOLCHAIN_HAS_ZBB
Expand Down
185 changes: 185 additions & 0 deletions arch/riscv/net/bpf_jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ static inline bool rvc_enabled(void)
return IS_ENABLED(CONFIG_RISCV_ISA_C);
}

static inline bool rvzba_enabled(void)
{
return IS_ENABLED(CONFIG_RISCV_ISA_ZBA) && riscv_has_extension_likely(RISCV_ISA_EXT_ZBA);
}

static inline bool rvzbb_enabled(void)
{
return IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && riscv_has_extension_likely(RISCV_ISA_EXT_ZBB);
}

enum {
RV_REG_ZERO = 0, /* The constant value 0 */
RV_REG_RA = 1, /* Return address */
Expand Down Expand Up @@ -730,6 +740,44 @@ static inline u16 rvc_swsp(u32 imm8, u8 rs2)
return rv_css_insn(0x6, imm, rs2, 0x2);
}

/* RVZBA instructions. */
static inline u32 rvzba_sh2add(u8 rd, u8 rs1, u8 rs2)
{
return rv_r_insn(0x10, rs2, rs1, 0x4, rd, 0x33);
}

static inline u32 rvzba_sh3add(u8 rd, u8 rs1, u8 rs2)
{
return rv_r_insn(0x10, rs2, rs1, 0x6, rd, 0x33);
}

/* RVZBB instrutions. */
static inline u32 rvzbb_sextb(u8 rd, u8 rs1)
{
return rv_i_insn(0x604, rs1, 1, rd, 0x13);
}

static inline u32 rvzbb_sexth(u8 rd, u8 rs1)
{
return rv_i_insn(0x605, rs1, 1, rd, 0x13);
}

static inline u32 rvzbb_zexth(u8 rd, u8 rs)
{
if (IS_ENABLED(CONFIG_64BIT))
return rv_i_insn(0x80, rs, 4, rd, 0x3b);

return rv_i_insn(0x80, rs, 4, rd, 0x33);
}

static inline u32 rvzbb_rev8(u8 rd, u8 rs)
{
if (IS_ENABLED(CONFIG_64BIT))
return rv_i_insn(0x6b8, rs, 5, rd, 0x13);

return rv_i_insn(0x698, rs, 5, rd, 0x13);
}

/*
* RV64-only instructions.
*
Expand Down Expand Up @@ -905,6 +953,14 @@ static inline u16 rvc_sdsp(u32 imm9, u8 rs2)
return rv_css_insn(0x7, imm, rs2, 0x2);
}

/* RV64-only ZBA instructions. */

static inline u32 rvzba_zextw(u8 rd, u8 rs1)
{
/* add.uw rd, rs1, ZERO */
return rv_r_insn(0x04, RV_REG_ZERO, rs1, 0, rd, 0x3b);
}

#endif /* __riscv_xlen == 64 */

/* Helper functions that emit RVC instructions when possible. */
Expand Down Expand Up @@ -1048,6 +1104,28 @@ static inline void emit_sw(u8 rs1, s32 off, u8 rs2, struct rv_jit_context *ctx)
emit(rv_sw(rs1, off, rs2), ctx);
}

static inline void emit_sh2add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
{
if (rvzba_enabled()) {
emit(rvzba_sh2add(rd, rs1, rs2), ctx);
return;
}

emit_slli(rd, rs1, 2, ctx);
emit_add(rd, rd, rs2, ctx);
}

static inline void emit_sh3add(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
{
if (rvzba_enabled()) {
emit(rvzba_sh3add(rd, rs1, rs2), ctx);
return;
}

emit_slli(rd, rs1, 3, ctx);
emit_add(rd, rd, rs2, ctx);
}

/* RV64-only helper functions. */
#if __riscv_xlen == 64

Expand Down Expand Up @@ -1087,6 +1165,113 @@ static inline void emit_subw(u8 rd, u8 rs1, u8 rs2, struct rv_jit_context *ctx)
emit(rv_subw(rd, rs1, rs2), ctx);
}

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

emit_slli(rd, rs, 56, ctx);
emit_srai(rd, rd, 56, ctx);
}

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

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

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)
{
if (rvzba_enabled()) {
emit(rvzba_zextw(rd, rs), ctx);
return;
}

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);
Expand Down
3 changes: 1 addition & 2 deletions arch/riscv/net/bpf_jit_comp32.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,8 +811,7 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
* if (!prog)
* goto out;
*/
emit(rv_slli(RV_REG_T0, lo(idx_reg), 2), ctx);
emit(rv_add(RV_REG_T0, RV_REG_T0, lo(arr_reg)), ctx);
emit_sh2add(RV_REG_T0, lo(idx_reg), lo(arr_reg), ctx);
off = offsetof(struct bpf_array, ptrs);
if (is_12b_check(off, insn))
return -1;
Expand Down
Loading