mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 08:02:30 +00:00
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: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8afd9c961e
commit
9f15d0f438
2 changed files with 85 additions and 0 deletions
|
@ -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)
|
static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst)
|
||||||
{
|
{
|
||||||
|
bool lm_id, lm_dec = false;
|
||||||
u16 val = swreg_value(reg);
|
u16 val = swreg_value(reg);
|
||||||
|
|
||||||
switch (swreg_type(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;
|
return UR_REG_NN | val;
|
||||||
case NN_REG_XFER:
|
case NN_REG_XFER:
|
||||||
return UR_REG_XFR | val;
|
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:
|
case NN_REG_IMM:
|
||||||
if (val & ~0xff) {
|
if (val & ~0xff) {
|
||||||
pr_err("immediate too large\n");
|
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)
|
static u16 nfp_swreg_to_rereg(swreg reg, bool is_dst, bool has_imm8, bool *i8)
|
||||||
{
|
{
|
||||||
u16 val = swreg_value(reg);
|
u16 val = swreg_value(reg);
|
||||||
|
bool lm_id;
|
||||||
|
|
||||||
switch (swreg_type(reg)) {
|
switch (swreg_type(reg)) {
|
||||||
case NN_REG_GPR_A:
|
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;
|
return val;
|
||||||
case NN_REG_XFER:
|
case NN_REG_XFER:
|
||||||
return RE_REG_XFR | val;
|
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:
|
case NN_REG_IMM:
|
||||||
if (val & ~(0x7f | has_imm8 << 7)) {
|
if (val & ~(0x7f | has_imm8 << 7)) {
|
||||||
pr_err("immediate too large\n");
|
pr_err("immediate too large\n");
|
||||||
|
|
|
@ -44,9 +44,17 @@
|
||||||
#define RE_REG_IMM_encode(x) \
|
#define RE_REG_IMM_encode(x) \
|
||||||
(RE_REG_IMM | ((x) & 0x1f) | (((x) & 0x60) << 1))
|
(RE_REG_IMM | ((x) & 0x1f) | (((x) & 0x60) << 1))
|
||||||
#define RE_REG_IMM_MAX 0x07fULL
|
#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 RE_REG_XFR 0x080
|
||||||
|
|
||||||
#define UR_REG_XFR 0x180
|
#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_NN 0x280
|
||||||
#define UR_REG_NO_DST 0x300
|
#define UR_REG_NO_DST 0x300
|
||||||
#define UR_REG_IMM UR_REG_NO_DST
|
#define UR_REG_IMM UR_REG_NO_DST
|
||||||
|
@ -235,6 +243,8 @@ enum lcsr_wr_src {
|
||||||
|
|
||||||
/* Software register representation, independent of operand type */
|
/* Software register representation, independent of operand type */
|
||||||
#define NN_REG_TYPE GENMASK(31, 24)
|
#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)
|
#define NN_REG_VAL GENMASK(7, 0)
|
||||||
|
|
||||||
enum nfp_bpf_reg_type {
|
enum nfp_bpf_reg_type {
|
||||||
|
@ -245,6 +255,13 @@ enum nfp_bpf_reg_type {
|
||||||
NN_REG_XFER = BIT(3),
|
NN_REG_XFER = BIT(3),
|
||||||
NN_REG_IMM = BIT(4),
|
NN_REG_IMM = BIT(4),
|
||||||
NN_REG_NONE = BIT(5),
|
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)
|
#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_xfer(x) __enc_swreg((x), NN_REG_XFER)
|
||||||
#define reg_imm(x) __enc_swreg((x), NN_REG_IMM)
|
#define reg_imm(x) __enc_swreg((x), NN_REG_IMM)
|
||||||
#define reg_none() __enc_swreg(0, NN_REG_NONE)
|
#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;
|
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));
|
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)
|
static inline u32 swreg_raw(swreg reg)
|
||||||
{
|
{
|
||||||
return (__force u32)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));
|
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 {
|
struct nfp_insn_ur_regs {
|
||||||
enum alu_dst_ab dst_ab;
|
enum alu_dst_ab dst_ab;
|
||||||
u16 dst;
|
u16 dst;
|
||||||
|
|
Loading…
Reference in a new issue