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

Commit 9f15d0f4 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

nfp: bpf: encode LMEM accesses



NFP LMEM is a large, indirectly accessed register file.  There
are two basic indirect access registers.  Each access operation
may either use offset (up to 8 or 16 words) or perform post
decrement/increment.

Add encodings of LMEM indexes as instruction operands.

Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarSimon Horman <simon.horman@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8afd9c96
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ const struct cmd_tgt_act cmd_tgt_act[__CMD_TGT_MAP_SIZE] = {

static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst)
{
	bool lm_id, lm_dec = false;
	u16 val = swreg_value(reg);

	switch (swreg_type(reg)) {
@@ -59,6 +60,33 @@ static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst)
		return UR_REG_NN | val;
	case NN_REG_XFER:
		return UR_REG_XFR | val;
	case NN_REG_LMEM:
		lm_id = swreg_lm_idx(reg);

		switch (swreg_lm_mode(reg)) {
		case NN_LM_MOD_NONE:
			if (val & ~UR_REG_LM_IDX_MAX) {
				pr_err("LM offset too large\n");
				return 0;
			}
			return UR_REG_LM | FIELD_PREP(UR_REG_LM_IDX, lm_id) |
				val;
		case NN_LM_MOD_DEC:
			lm_dec = true;
			/* fall through */
		case NN_LM_MOD_INC:
			if (val) {
				pr_err("LM offset in inc/dev mode\n");
				return 0;
			}
			return UR_REG_LM | UR_REG_LM_POST_MOD |
				FIELD_PREP(UR_REG_LM_IDX, lm_id) |
				FIELD_PREP(UR_REG_LM_POST_MOD_DEC, lm_dec);
		default:
			pr_err("bad LM mode for unrestricted operands %d\n",
			       swreg_lm_mode(reg));
			return 0;
		}
	case NN_REG_IMM:
		if (val & ~0xff) {
			pr_err("immediate too large\n");
@@ -108,6 +136,7 @@ int swreg_to_unrestricted(swreg dst, swreg lreg, swreg rreg,
static u16 nfp_swreg_to_rereg(swreg reg, bool is_dst, bool has_imm8, bool *i8)
{
	u16 val = swreg_value(reg);
	bool lm_id;

	switch (swreg_type(reg)) {
	case NN_REG_GPR_A:
@@ -116,6 +145,21 @@ static u16 nfp_swreg_to_rereg(swreg reg, bool is_dst, bool has_imm8, bool *i8)
		return val;
	case NN_REG_XFER:
		return RE_REG_XFR | val;
	case NN_REG_LMEM:
		lm_id = swreg_lm_idx(reg);

		if (swreg_lm_mode(reg) != NN_LM_MOD_NONE) {
			pr_err("bad LM mode for restricted operands %d\n",
			       swreg_lm_mode(reg));
			return 0;
		}

		if (val & ~RE_REG_LM_IDX_MAX) {
			pr_err("LM offset too large\n");
			return 0;
		}

		return RE_REG_LM | FIELD_PREP(RE_REG_LM_IDX, lm_id) | val;
	case NN_REG_IMM:
		if (val & ~(0x7f | has_imm8 << 7)) {
			pr_err("immediate too large\n");
+41 −0
Original line number Diff line number Diff line
@@ -44,9 +44,17 @@
#define RE_REG_IMM_encode(x)					\
	(RE_REG_IMM | ((x) & 0x1f) | (((x) & 0x60) << 1))
#define RE_REG_IMM_MAX	 0x07fULL
#define RE_REG_LM	0x050
#define RE_REG_LM_IDX	0x008
#define RE_REG_LM_IDX_MAX	0x7
#define RE_REG_XFR	0x080

#define UR_REG_XFR	0x180
#define UR_REG_LM	0x200
#define UR_REG_LM_IDX	0x020
#define UR_REG_LM_POST_MOD	0x010
#define UR_REG_LM_POST_MOD_DEC	0x001
#define UR_REG_LM_IDX_MAX	0xf
#define UR_REG_NN	0x280
#define UR_REG_NO_DST	0x300
#define UR_REG_IMM	UR_REG_NO_DST
@@ -235,6 +243,8 @@ enum lcsr_wr_src {

/* Software register representation, independent of operand type */
#define NN_REG_TYPE	GENMASK(31, 24)
#define NN_REG_LM_IDX	BIT(22)
#define NN_REG_LM_MOD	GENMASK(21, 20)
#define NN_REG_VAL	GENMASK(7, 0)

enum nfp_bpf_reg_type {
@@ -245,6 +255,13 @@ enum nfp_bpf_reg_type {
	NN_REG_XFER =	BIT(3),
	NN_REG_IMM =	BIT(4),
	NN_REG_NONE =	BIT(5),
	NN_REG_LMEM =	BIT(6),
};

enum nfp_bpf_lm_mode {
	NN_LM_MOD_NONE = 0,
	NN_LM_MOD_INC,
	NN_LM_MOD_DEC,
};

#define reg_both(x)	__enc_swreg((x), NN_REG_GPR_BOTH)
@@ -254,6 +271,10 @@ enum nfp_bpf_reg_type {
#define reg_xfer(x)	__enc_swreg((x), NN_REG_XFER)
#define reg_imm(x)	__enc_swreg((x), NN_REG_IMM)
#define reg_none()	__enc_swreg(0, NN_REG_NONE)
#define reg_lm(x, off)	__enc_swreg_lm((x), NN_LM_MOD_NONE, (off))
#define reg_lm_inc(x)	__enc_swreg_lm((x), NN_LM_MOD_INC, 0)
#define reg_lm_dec(x)	__enc_swreg_lm((x), NN_LM_MOD_DEC, 0)
#define __reg_lm(x, mod, off)	__enc_swreg_lm((x), (mod), (off))

typedef __u32 __bitwise swreg;

@@ -262,6 +283,16 @@ static inline swreg __enc_swreg(u16 id, u8 type)
	return (__force swreg)(id | FIELD_PREP(NN_REG_TYPE, type));
}

static inline swreg __enc_swreg_lm(u8 id, enum nfp_bpf_lm_mode mode, u8 off)
{
	WARN_ON(id > 1 || (off && mode != NN_LM_MOD_NONE));

	return (__force swreg)(FIELD_PREP(NN_REG_TYPE, NN_REG_LMEM) |
			       FIELD_PREP(NN_REG_LM_IDX, id) |
			       FIELD_PREP(NN_REG_LM_MOD, mode) |
			       off);
}

static inline u32 swreg_raw(swreg reg)
{
	return (__force u32)reg;
@@ -277,6 +308,16 @@ static inline u16 swreg_value(swreg reg)
	return FIELD_GET(NN_REG_VAL, swreg_raw(reg));
}

static inline bool swreg_lm_idx(swreg reg)
{
	return FIELD_GET(NN_REG_LM_IDX, swreg_raw(reg));
}

static inline enum nfp_bpf_lm_mode swreg_lm_mode(swreg reg)
{
	return FIELD_GET(NN_REG_LM_MOD, swreg_raw(reg));
}

struct nfp_insn_ur_regs {
	enum alu_dst_ab dst_ab;
	u16 dst;