Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4db25cc9 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Alexei Starovoitov
Browse files

bpf, mips64: remove ld_abs/ld_ind



Since LD_ABS/LD_IND instructions are now removed from the core and
reimplemented through a combination of inlined BPF instructions and
a slow-path helper, we can get rid of the complexity from mips64 JIT.

Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 0d2d0ced
Loading
Loading
Loading
Loading
+0 −104
Original line number Diff line number Diff line
@@ -1267,110 +1267,6 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
			return -EINVAL;
		break;

	case BPF_LD | BPF_B | BPF_ABS:
	case BPF_LD | BPF_H | BPF_ABS:
	case BPF_LD | BPF_W | BPF_ABS:
	case BPF_LD | BPF_DW | BPF_ABS:
		ctx->flags |= EBPF_SAVE_RA;

		gen_imm_to_reg(insn, MIPS_R_A1, ctx);
		emit_instr(ctx, addiu, MIPS_R_A2, MIPS_R_ZERO, size_to_len(insn));

		if (insn->imm < 0) {
			emit_const_to_reg(ctx, MIPS_R_T9, (u64)bpf_internal_load_pointer_neg_helper);
		} else {
			emit_const_to_reg(ctx, MIPS_R_T9, (u64)ool_skb_header_pointer);
			emit_instr(ctx, daddiu, MIPS_R_A3, MIPS_R_SP, ctx->tmp_offset);
		}
		goto ld_skb_common;

	case BPF_LD | BPF_B | BPF_IND:
	case BPF_LD | BPF_H | BPF_IND:
	case BPF_LD | BPF_W | BPF_IND:
	case BPF_LD | BPF_DW | BPF_IND:
		ctx->flags |= EBPF_SAVE_RA;
		src = ebpf_to_mips_reg(ctx, insn, src_reg_no_fp);
		if (src < 0)
			return src;
		ts = get_reg_val_type(ctx, this_idx, insn->src_reg);
		if (ts == REG_32BIT_ZERO_EX) {
			/* sign extend */
			emit_instr(ctx, sll, MIPS_R_A1, src, 0);
			src = MIPS_R_A1;
		}
		if (insn->imm >= S16_MIN && insn->imm <= S16_MAX) {
			emit_instr(ctx, daddiu, MIPS_R_A1, src, insn->imm);
		} else {
			gen_imm_to_reg(insn, MIPS_R_AT, ctx);
			emit_instr(ctx, daddu, MIPS_R_A1, MIPS_R_AT, src);
		}
		/* truncate to 32-bit int */
		emit_instr(ctx, sll, MIPS_R_A1, MIPS_R_A1, 0);
		emit_instr(ctx, daddiu, MIPS_R_A3, MIPS_R_SP, ctx->tmp_offset);
		emit_instr(ctx, slt, MIPS_R_AT, MIPS_R_A1, MIPS_R_ZERO);

		emit_const_to_reg(ctx, MIPS_R_T8, (u64)bpf_internal_load_pointer_neg_helper);
		emit_const_to_reg(ctx, MIPS_R_T9, (u64)ool_skb_header_pointer);
		emit_instr(ctx, addiu, MIPS_R_A2, MIPS_R_ZERO, size_to_len(insn));
		emit_instr(ctx, movn, MIPS_R_T9, MIPS_R_T8, MIPS_R_AT);

ld_skb_common:
		emit_instr(ctx, jalr, MIPS_R_RA, MIPS_R_T9);
		/* delay slot move */
		emit_instr(ctx, daddu, MIPS_R_A0, MIPS_R_S0, MIPS_R_ZERO);

		/* Check the error value */
		b_off = b_imm(exit_idx, ctx);
		if (is_bad_offset(b_off)) {
			target = j_target(ctx, exit_idx);
			if (target == (unsigned int)-1)
				return -E2BIG;

			if (!(ctx->offsets[this_idx] & OFFSETS_B_CONV)) {
				ctx->offsets[this_idx] |= OFFSETS_B_CONV;
				ctx->long_b_conversion = 1;
			}
			emit_instr(ctx, bne, MIPS_R_V0, MIPS_R_ZERO, 4 * 3);
			emit_instr(ctx, nop);
			emit_instr(ctx, j, target);
			emit_instr(ctx, nop);
		} else {
			emit_instr(ctx, beq, MIPS_R_V0, MIPS_R_ZERO, b_off);
			emit_instr(ctx, nop);
		}

#ifdef __BIG_ENDIAN
		need_swap = false;
#else
		need_swap = true;
#endif
		dst = MIPS_R_V0;
		switch (BPF_SIZE(insn->code)) {
		case BPF_B:
			emit_instr(ctx, lbu, dst, 0, MIPS_R_V0);
			break;
		case BPF_H:
			emit_instr(ctx, lhu, dst, 0, MIPS_R_V0);
			if (need_swap)
				emit_instr(ctx, wsbh, dst, dst);
			break;
		case BPF_W:
			emit_instr(ctx, lw, dst, 0, MIPS_R_V0);
			if (need_swap) {
				emit_instr(ctx, wsbh, dst, dst);
				emit_instr(ctx, rotr, dst, dst, 16);
			}
			break;
		case BPF_DW:
			emit_instr(ctx, ld, dst, 0, MIPS_R_V0);
			if (need_swap) {
				emit_instr(ctx, dsbh, dst, dst);
				emit_instr(ctx, dshd, dst, dst);
			}
			break;
		}

		break;
	case BPF_ALU | BPF_END | BPF_FROM_BE:
	case BPF_ALU | BPF_END | BPF_FROM_LE:
		dst = ebpf_to_mips_reg(ctx, insn, dst_reg);