[RFC 12/15] riscv: bpf: big endian fixes, updated BPF_ALU ops

Ben Dooks ben.dooks at codethink.co.uk
Fri Dec 20 07:57:58 PST 2024


If running big endian then the instruction stream needs to
be written le16/le323 and the BPF BSWAP instrictions need
to correctly set the endian.

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
---
 arch/riscv/net/bpf_jit.h        | 14 +++++++++-----
 arch/riscv/net/bpf_jit_comp64.c | 29 +++++++++++++++++------------
 2 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/arch/riscv/net/bpf_jit.h b/arch/riscv/net/bpf_jit.h
index 1d1c78d4cff1..eb2908cc42fd 100644
--- a/arch/riscv/net/bpf_jit.h
+++ b/arch/riscv/net/bpf_jit.h
@@ -28,6 +28,12 @@ static inline bool rvzbb_enabled(void)
 	return IS_ENABLED(CONFIG_RISCV_ISA_ZBB) && riscv_has_extension_likely(RISCV_ISA_EXT_ZBB);
 }
 
+static inline bool alu_end_should_swap(u32 code)
+{
+	u32 endian = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ? BPF_FROM_BE : BPF_FROM_LE;
+	return (code & BPF_FROM_BE) != endian;
+}
+
 enum {
 	RV_REG_ZERO =	0,	/* The constant value 0 */
 	RV_REG_RA =	1,	/* Return address */
@@ -117,10 +123,8 @@ static inline void bpf_flush_icache(void *start, void *end)
 /* Emit a 4-byte riscv instruction. */
 static inline void emit(const u32 insn, struct rv_jit_context *ctx)
 {
-	if (ctx->insns) {
-		ctx->insns[ctx->ninsns] = insn;
-		ctx->insns[ctx->ninsns + 1] = (insn >> 16);
-	}
+	if (ctx->insns)
+		put_unaligned_le32(insn, ctx->insns+ctx->ninsns);
 
 	ctx->ninsns += 2;
 }
@@ -131,7 +135,7 @@ static inline void emitc(const u16 insn, struct rv_jit_context *ctx)
 	BUILD_BUG_ON(!rvc_enabled());
 
 	if (ctx->insns)
-		ctx->insns[ctx->ninsns] = insn;
+		ctx->insns[ctx->ninsns] = cpu_to_le16(insn);
 
 	ctx->ninsns++;
 }
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 4cc631fa7039..05f5b1a88423 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -1273,20 +1273,25 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 
 	/* dst = BSWAP##imm(dst) */
 	case BPF_ALU | BPF_END | BPF_FROM_LE:
-		switch (imm) {
-		case 16:
-			emit_zexth(rd, rd, ctx);
-			break;
-		case 32:
-			if (!aux->verifier_zext)
-				emit_zextw(rd, rd, ctx);
-			break;
-		case 64:
-			/* Do nothing */
-			break;
+	case BPF_ALU | BPF_END | BPF_FROM_BE:
+		if (alu_end_should_swap(code)) {
+			emit_bswap(rd, imm, ctx);
+		} else {
+			switch (imm) {
+			case 16:
+				emit_zexth(rd, rd, ctx);
+				break;
+			case 32:
+				if (!aux->verifier_zext)
+					emit_zextw(rd, rd, ctx);
+				break;
+			case 64:
+				/* Do nothing */
+				break;
+			}
 		}
 		break;
-	case BPF_ALU | BPF_END | BPF_FROM_BE:
+
 	case BPF_ALU64 | BPF_END | BPF_FROM_LE:
 		emit_bswap(rd, imm, ctx);
 		break;
-- 
2.37.2.352.g3c44437643




More information about the linux-riscv mailing list