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

Commit 61dd8f00 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Daniel Borkmann
Browse files

nfp: bpf: tabularize generations of compare operations



There are quite a few compare instructions now, use a table
to translate BPF instruction code to NFP instruction parameters
instead of parameterizing helpers.  This saves LOC and makes
future extensions easier.

Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 6c59500c
Loading
Loading
Loading
Loading
+61 −107
Original line number Diff line number Diff line
@@ -1214,45 +1214,79 @@ wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
	return 0;
}

static int
wrp_cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
	    enum br_mask br_mask, bool swap)
static const struct jmp_code_map {
	enum br_mask br_mask;
	bool swap;
} jmp_code_map[] = {
	[BPF_JGT >> 4]	= { BR_BLO, true },
	[BPF_JGE >> 4]	= { BR_BHS, false },
	[BPF_JLT >> 4]	= { BR_BLO, false },
	[BPF_JLE >> 4]	= { BR_BHS, true },
	[BPF_JSGT >> 4]	= { BR_BLT, true },
	[BPF_JSGE >> 4]	= { BR_BGE, false },
	[BPF_JSLT >> 4]	= { BR_BLT, false },
	[BPF_JSLE >> 4]	= { BR_BGE, true },
};

static const struct jmp_code_map *nfp_jmp_code_get(struct nfp_insn_meta *meta)
{
	unsigned int op;

	op = BPF_OP(meta->insn.code) >> 4;
	/* br_mask of 0 is BR_BEQ which we don't use in jump code table */
	if (WARN_ONCE(op >= ARRAY_SIZE(jmp_code_map) ||
		      !jmp_code_map[op].br_mask,
		      "no code found for jump instruction"))
		return NULL;

	return &jmp_code_map[op];
}

static int cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	const struct bpf_insn *insn = &meta->insn;
	u64 imm = insn->imm; /* sign extend */
	const struct jmp_code_map *code;
	u8 reg = insn->dst_reg * 2;
	swreg tmp_reg;

	code = nfp_jmp_code_get(meta);
	if (!code)
		return -EINVAL;

	tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
	if (!swap)
	if (!code->swap)
		emit_alu(nfp_prog, reg_none(), reg_a(reg), ALU_OP_SUB, tmp_reg);
	else
		emit_alu(nfp_prog, reg_none(), tmp_reg, ALU_OP_SUB, reg_a(reg));

	tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
	if (!swap)
	if (!code->swap)
		emit_alu(nfp_prog, reg_none(),
			 reg_a(reg + 1), ALU_OP_SUB_C, tmp_reg);
	else
		emit_alu(nfp_prog, reg_none(),
			 tmp_reg, ALU_OP_SUB_C, reg_a(reg + 1));

	emit_br(nfp_prog, br_mask, insn->off, 0);
	emit_br(nfp_prog, code->br_mask, insn->off, 0);

	return 0;
}

static int
wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
	    enum br_mask br_mask, bool swap)
static int cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	const struct bpf_insn *insn = &meta->insn;
	const struct jmp_code_map *code;
	u8 areg, breg;

	code = nfp_jmp_code_get(meta);
	if (!code)
		return -EINVAL;

	areg = insn->dst_reg * 2;
	breg = insn->src_reg * 2;

	if (swap) {
	if (code->swap) {
		areg ^= breg;
		breg ^= areg;
		areg ^= breg;
@@ -1261,7 +1295,7 @@ wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
	emit_alu(nfp_prog, reg_none(), reg_a(areg), ALU_OP_SUB, reg_b(breg));
	emit_alu(nfp_prog, reg_none(),
		 reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1));
	emit_br(nfp_prog, br_mask, insn->off, 0);
	emit_br(nfp_prog, code->br_mask, insn->off, 0);

	return 0;
}
@@ -2283,46 +2317,6 @@ static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
	return 0;
}

static int jgt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BLO, true);
}

static int jge_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BHS, false);
}

static int jlt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BLO, false);
}

static int jle_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BHS, true);
}

static int jsgt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BLT, true);
}

static int jsge_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BGE, false);
}

static int jslt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BLT, false);
}

static int jsle_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_imm(nfp_prog, meta, BR_BGE, true);
}

static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	const struct bpf_insn *insn = &meta->insn;
@@ -2392,46 +2386,6 @@ static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
	return 0;
}

static int jgt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BLO, true);
}

static int jge_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BHS, false);
}

static int jlt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BLO, false);
}

static int jle_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BHS, true);
}

static int jsgt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BLT, true);
}

static int jsge_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BGE, false);
}

static int jslt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BLT, false);
}

static int jsle_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_cmp_reg(nfp_prog, meta, BR_BGE, true);
}

static int jset_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
	return wrp_test_reg(nfp_prog, meta, ALU_OP_AND, BR_BNE);
@@ -2520,25 +2474,25 @@ static const instr_cb_t instr_cb[256] = {
	[BPF_ST | BPF_MEM | BPF_DW] =	mem_st8,
	[BPF_JMP | BPF_JA | BPF_K] =	jump,
	[BPF_JMP | BPF_JEQ | BPF_K] =	jeq_imm,
	[BPF_JMP | BPF_JGT | BPF_K] =	jgt_imm,
	[BPF_JMP | BPF_JGE | BPF_K] =	jge_imm,
	[BPF_JMP | BPF_JLT | BPF_K] =	jlt_imm,
	[BPF_JMP | BPF_JLE | BPF_K] =	jle_imm,
	[BPF_JMP | BPF_JSGT | BPF_K] =  jsgt_imm,
	[BPF_JMP | BPF_JSGE | BPF_K] =  jsge_imm,
	[BPF_JMP | BPF_JSLT | BPF_K] =  jslt_imm,
	[BPF_JMP | BPF_JSLE | BPF_K] =  jsle_imm,
	[BPF_JMP | BPF_JGT | BPF_K] =	cmp_imm,
	[BPF_JMP | BPF_JGE | BPF_K] =	cmp_imm,
	[BPF_JMP | BPF_JLT | BPF_K] =	cmp_imm,
	[BPF_JMP | BPF_JLE | BPF_K] =	cmp_imm,
	[BPF_JMP | BPF_JSGT | BPF_K] =  cmp_imm,
	[BPF_JMP | BPF_JSGE | BPF_K] =  cmp_imm,
	[BPF_JMP | BPF_JSLT | BPF_K] =  cmp_imm,
	[BPF_JMP | BPF_JSLE | BPF_K] =  cmp_imm,
	[BPF_JMP | BPF_JSET | BPF_K] =	jset_imm,
	[BPF_JMP | BPF_JNE | BPF_K] =	jne_imm,
	[BPF_JMP | BPF_JEQ | BPF_X] =	jeq_reg,
	[BPF_JMP | BPF_JGT | BPF_X] =	jgt_reg,
	[BPF_JMP | BPF_JGE | BPF_X] =	jge_reg,
	[BPF_JMP | BPF_JLT | BPF_X] =	jlt_reg,
	[BPF_JMP | BPF_JLE | BPF_X] =	jle_reg,
	[BPF_JMP | BPF_JSGT | BPF_X] =  jsgt_reg,
	[BPF_JMP | BPF_JSGE | BPF_X] =  jsge_reg,
	[BPF_JMP | BPF_JSLT | BPF_X] =  jslt_reg,
	[BPF_JMP | BPF_JSLE | BPF_X] =  jsle_reg,
	[BPF_JMP | BPF_JGT | BPF_X] =	cmp_reg,
	[BPF_JMP | BPF_JGE | BPF_X] =	cmp_reg,
	[BPF_JMP | BPF_JLT | BPF_X] =	cmp_reg,
	[BPF_JMP | BPF_JLE | BPF_X] =	cmp_reg,
	[BPF_JMP | BPF_JSGT | BPF_X] =  cmp_reg,
	[BPF_JMP | BPF_JSGE | BPF_X] =  cmp_reg,
	[BPF_JMP | BPF_JSLT | BPF_X] =  cmp_reg,
	[BPF_JMP | BPF_JSLE | BPF_X] =  cmp_reg,
	[BPF_JMP | BPF_JSET | BPF_X] =	jset_reg,
	[BPF_JMP | BPF_JNE | BPF_X] =	jne_reg,
	[BPF_JMP | BPF_CALL] =		call,