]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
riscv, bpf: Extract emit_st() helper
authorPu Lehui <pulehui@huawei.com>
Sat, 19 Jul 2025 09:17:22 +0000 (09:17 +0000)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 15 Aug 2025 08:46:51 +0000 (10:46 +0200)
There's a lot of redundant code related to store from immediate
operations, let's extract emit_st() to make code more compact.

Signed-off-by: Pu Lehui <pulehui@huawei.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Tested-by: Björn Töpel <bjorn@rivosinc.com>
Reviewed-by: Björn Töpel <bjorn@rivosinc.com>
Acked-by: Björn Töpel <bjorn@kernel.org>
Link: https://lore.kernel.org/bpf/20250719091730.2660197-3-pulehui@huaweicloud.com
arch/riscv/net/bpf_jit_comp64.c

index ba75ba179b260d96833a7e1716f01859fc469e13..5e354f686ea3b3741148fea7d208ea1f21551e05 100644 (file)
@@ -577,6 +577,24 @@ static void emit_stx_insn(u8 rd, s16 off, u8 rs, u8 size, struct rv_jit_context
        }
 }
 
+static int emit_st(u8 rd, s16 off, s32 imm, u8 size, struct rv_jit_context *ctx)
+{
+       int insns_start;
+
+       emit_imm(RV_REG_T1, imm, ctx);
+       if (is_12b_int(off)) {
+               insns_start = ctx->ninsns;
+               emit_stx_insn(rd, off, RV_REG_T1, size, ctx);
+               return ctx->ninsns - insns_start;
+       }
+
+       emit_imm(RV_REG_T2, off, ctx);
+       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
+       insns_start = ctx->ninsns;
+       emit_stx_insn(RV_REG_T2, 0, RV_REG_T1, size, ctx);
+       return ctx->ninsns - insns_start;
+}
+
 static int emit_stx(u8 rd, s16 off, u8 rs, u8 size, struct rv_jit_context *ctx)
 {
        int insns_start;
@@ -1870,128 +1888,27 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 
        /* ST: *(size *)(dst + off) = imm */
        case BPF_ST | BPF_MEM | BPF_B:
-               emit_imm(RV_REG_T1, imm, ctx);
-               if (is_12b_int(off)) {
-                       emit(rv_sb(rd, off, RV_REG_T1), ctx);
-                       break;
-               }
-
-               emit_imm(RV_REG_T2, off, ctx);
-               emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-               emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
-               break;
-
        case BPF_ST | BPF_MEM | BPF_H:
-               emit_imm(RV_REG_T1, imm, ctx);
-               if (is_12b_int(off)) {
-                       emit(rv_sh(rd, off, RV_REG_T1), ctx);
-                       break;
-               }
-
-               emit_imm(RV_REG_T2, off, ctx);
-               emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-               emit(rv_sh(RV_REG_T2, 0, RV_REG_T1), ctx);
-               break;
        case BPF_ST | BPF_MEM | BPF_W:
-               emit_imm(RV_REG_T1, imm, ctx);
-               if (is_12b_int(off)) {
-                       emit_sw(rd, off, RV_REG_T1, ctx);
-                       break;
-               }
-
-               emit_imm(RV_REG_T2, off, ctx);
-               emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-               emit_sw(RV_REG_T2, 0, RV_REG_T1, ctx);
-               break;
        case BPF_ST | BPF_MEM | BPF_DW:
-               emit_imm(RV_REG_T1, imm, ctx);
-               if (is_12b_int(off)) {
-                       emit_sd(rd, off, RV_REG_T1, ctx);
-                       break;
-               }
-
-               emit_imm(RV_REG_T2, off, ctx);
-               emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-               emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
-               break;
-
+       /* ST | PROBE_MEM32: *(size *)(dst + RV_REG_ARENA + off) = imm */
        case BPF_ST | BPF_PROBE_MEM32 | BPF_B:
        case BPF_ST | BPF_PROBE_MEM32 | BPF_H:
        case BPF_ST | BPF_PROBE_MEM32 | BPF_W:
        case BPF_ST | BPF_PROBE_MEM32 | BPF_DW:
        {
-               int insn_len, insns_start;
-
-               emit_add(RV_REG_T3, rd, RV_REG_ARENA, ctx);
-               rd = RV_REG_T3;
-
-               /* Load imm to a register then store it */
-               emit_imm(RV_REG_T1, imm, ctx);
-
-               switch (BPF_SIZE(code)) {
-               case BPF_B:
-                       if (is_12b_int(off)) {
-                               insns_start = ctx->ninsns;
-                               emit(rv_sb(rd, off, RV_REG_T1), ctx);
-                               insn_len = ctx->ninsns - insns_start;
-                               break;
-                       }
-
-                       emit_imm(RV_REG_T2, off, ctx);
-                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-                       insns_start = ctx->ninsns;
-                       emit(rv_sb(RV_REG_T2, 0, RV_REG_T1), ctx);
-                       insn_len = ctx->ninsns - insns_start;
-                       break;
-               case BPF_H:
-                       if (is_12b_int(off)) {
-                               insns_start = ctx->ninsns;
-                               emit(rv_sh(rd, off, RV_REG_T1), ctx);
-                               insn_len = ctx->ninsns - insns_start;
-                               break;
-                       }
-
-                       emit_imm(RV_REG_T2, off, ctx);
-                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-                       insns_start = ctx->ninsns;
-                       emit(rv_sh(RV_REG_T2, 0, RV_REG_T1), ctx);
-                       insn_len = ctx->ninsns - insns_start;
-                       break;
-               case BPF_W:
-                       if (is_12b_int(off)) {
-                               insns_start = ctx->ninsns;
-                               emit_sw(rd, off, RV_REG_T1, ctx);
-                               insn_len = ctx->ninsns - insns_start;
-                               break;
-                       }
-
-                       emit_imm(RV_REG_T2, off, ctx);
-                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-                       insns_start = ctx->ninsns;
-                       emit_sw(RV_REG_T2, 0, RV_REG_T1, ctx);
-                       insn_len = ctx->ninsns - insns_start;
-                       break;
-               case BPF_DW:
-                       if (is_12b_int(off)) {
-                               insns_start = ctx->ninsns;
-                               emit_sd(rd, off, RV_REG_T1, ctx);
-                               insn_len = ctx->ninsns - insns_start;
-                               break;
-                       }
+               int insn_len;
 
-                       emit_imm(RV_REG_T2, off, ctx);
-                       emit_add(RV_REG_T2, RV_REG_T2, rd, ctx);
-                       insns_start = ctx->ninsns;
-                       emit_sd(RV_REG_T2, 0, RV_REG_T1, ctx);
-                       insn_len = ctx->ninsns - insns_start;
-                       break;
+               if (BPF_MODE(insn->code) == BPF_PROBE_MEM32) {
+                       emit_add(RV_REG_T3, rd, RV_REG_ARENA, ctx);
+                       rd = RV_REG_T3;
                }
 
-               ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER,
-                                           insn_len);
+               insn_len = emit_st(rd, off, imm, BPF_SIZE(code), ctx);
+
+               ret = add_exception_handler(insn, ctx, REG_DONT_CLEAR_MARKER, insn_len);
                if (ret)
                        return ret;
-
                break;
        }