Commit df4a37d8 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Alexei Starovoitov

nfp: bpf: add support for bpf_get_prandom_u32()

NFP has a prng register, which we can read to obtain a u32 worth
of pseudo random data.  Generate code for it.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: default avatarJiong Wang <jiong.wang@netronome.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 41aed09c
...@@ -41,6 +41,7 @@ enum bpf_cap_tlv_type { ...@@ -41,6 +41,7 @@ enum bpf_cap_tlv_type {
NFP_BPF_CAP_TYPE_FUNC = 1, NFP_BPF_CAP_TYPE_FUNC = 1,
NFP_BPF_CAP_TYPE_ADJUST_HEAD = 2, NFP_BPF_CAP_TYPE_ADJUST_HEAD = 2,
NFP_BPF_CAP_TYPE_MAPS = 3, NFP_BPF_CAP_TYPE_MAPS = 3,
NFP_BPF_CAP_TYPE_RANDOM = 4,
}; };
struct nfp_bpf_cap_tlv_func { struct nfp_bpf_cap_tlv_func {
......
...@@ -405,7 +405,7 @@ __emit_lcsr(struct nfp_prog *nfp_prog, u16 areg, u16 breg, bool wr, u16 addr, ...@@ -405,7 +405,7 @@ __emit_lcsr(struct nfp_prog *nfp_prog, u16 areg, u16 breg, bool wr, u16 addr,
FIELD_PREP(OP_LCSR_A_SRC, areg) | FIELD_PREP(OP_LCSR_A_SRC, areg) |
FIELD_PREP(OP_LCSR_B_SRC, breg) | FIELD_PREP(OP_LCSR_B_SRC, breg) |
FIELD_PREP(OP_LCSR_WRITE, wr) | FIELD_PREP(OP_LCSR_WRITE, wr) |
FIELD_PREP(OP_LCSR_ADDR, addr) | FIELD_PREP(OP_LCSR_ADDR, addr / 4) |
FIELD_PREP(OP_LCSR_SRC_LMEXTN, src_lmextn) | FIELD_PREP(OP_LCSR_SRC_LMEXTN, src_lmextn) |
FIELD_PREP(OP_LCSR_DST_LMEXTN, dst_lmextn); FIELD_PREP(OP_LCSR_DST_LMEXTN, dst_lmextn);
...@@ -433,10 +433,16 @@ static void emit_csr_wr(struct nfp_prog *nfp_prog, swreg src, u16 addr) ...@@ -433,10 +433,16 @@ static void emit_csr_wr(struct nfp_prog *nfp_prog, swreg src, u16 addr)
return; return;
} }
__emit_lcsr(nfp_prog, reg.areg, reg.breg, true, addr / 4, __emit_lcsr(nfp_prog, reg.areg, reg.breg, true, addr,
false, reg.src_lmextn); false, reg.src_lmextn);
} }
/* CSR value is read in following immed[gpr, 0] */
static void __emit_csr_rd(struct nfp_prog *nfp_prog, u16 addr)
{
__emit_lcsr(nfp_prog, 0, 0, false, addr, false, false);
}
static void emit_nop(struct nfp_prog *nfp_prog) static void emit_nop(struct nfp_prog *nfp_prog)
{ {
__emit_immed(nfp_prog, UR_REG_IMM, UR_REG_IMM, 0, 0, 0, 0, 0, 0, 0); __emit_immed(nfp_prog, UR_REG_IMM, UR_REG_IMM, 0, 0, 0, 0, 0, 0, 0);
...@@ -1398,6 +1404,18 @@ map_call_stack_common(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -1398,6 +1404,18 @@ map_call_stack_common(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
return 0; return 0;
} }
static int
nfp_get_prandom_u32(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
__emit_csr_rd(nfp_prog, NFP_CSR_PSEUDO_RND_NUM);
/* CSR value is read in following immed[gpr, 0] */
emit_immed(nfp_prog, reg_both(0), 0,
IMMED_WIDTH_ALL, false, IMMED_SHIFT_0B);
emit_immed(nfp_prog, reg_both(1), 0,
IMMED_WIDTH_ALL, false, IMMED_SHIFT_0B);
return 0;
}
/* --- Callbacks --- */ /* --- Callbacks --- */
static int mov_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int mov_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{ {
...@@ -2431,6 +2449,8 @@ static int call(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -2431,6 +2449,8 @@ static int call(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
case BPF_FUNC_map_update_elem: case BPF_FUNC_map_update_elem:
case BPF_FUNC_map_delete_elem: case BPF_FUNC_map_delete_elem:
return map_call_stack_common(nfp_prog, meta); return map_call_stack_common(nfp_prog, meta);
case BPF_FUNC_get_prandom_u32:
return nfp_get_prandom_u32(nfp_prog, meta);
default: default:
WARN_ONCE(1, "verifier allowed unsupported function\n"); WARN_ONCE(1, "verifier allowed unsupported function\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -315,6 +315,14 @@ nfp_bpf_parse_cap_maps(struct nfp_app_bpf *bpf, void __iomem *value, u32 length) ...@@ -315,6 +315,14 @@ nfp_bpf_parse_cap_maps(struct nfp_app_bpf *bpf, void __iomem *value, u32 length)
return 0; return 0;
} }
static int
nfp_bpf_parse_cap_random(struct nfp_app_bpf *bpf, void __iomem *value,
u32 length)
{
bpf->pseudo_random = true;
return 0;
}
static int nfp_bpf_parse_capabilities(struct nfp_app *app) static int nfp_bpf_parse_capabilities(struct nfp_app *app)
{ {
struct nfp_cpp *cpp = app->pf->cpp; struct nfp_cpp *cpp = app->pf->cpp;
...@@ -353,6 +361,10 @@ static int nfp_bpf_parse_capabilities(struct nfp_app *app) ...@@ -353,6 +361,10 @@ static int nfp_bpf_parse_capabilities(struct nfp_app *app)
if (nfp_bpf_parse_cap_maps(app->priv, value, length)) if (nfp_bpf_parse_cap_maps(app->priv, value, length))
goto err_release_free; goto err_release_free;
break; break;
case NFP_BPF_CAP_TYPE_RANDOM:
if (nfp_bpf_parse_cap_random(app->priv, value, length))
goto err_release_free;
break;
default: default:
nfp_dbg(cpp, "unknown BPF capability: %d\n", type); nfp_dbg(cpp, "unknown BPF capability: %d\n", type);
break; break;
......
...@@ -133,6 +133,8 @@ enum pkt_vec { ...@@ -133,6 +133,8 @@ enum pkt_vec {
* @helpers.map_lookup: map lookup helper address * @helpers.map_lookup: map lookup helper address
* @helpers.map_update: map update helper address * @helpers.map_update: map update helper address
* @helpers.map_delete: map delete helper address * @helpers.map_delete: map delete helper address
*
* @pseudo_random: FW initialized the pseudo-random machinery (CSRs)
*/ */
struct nfp_app_bpf { struct nfp_app_bpf {
struct nfp_app *app; struct nfp_app *app;
...@@ -170,6 +172,8 @@ struct nfp_app_bpf { ...@@ -170,6 +172,8 @@ struct nfp_app_bpf {
u32 map_update; u32 map_update;
u32 map_delete; u32 map_delete;
} helpers; } helpers;
bool pseudo_random;
}; };
enum nfp_bpf_map_use { enum nfp_bpf_map_use {
......
...@@ -209,6 +209,13 @@ nfp_bpf_check_call(struct nfp_prog *nfp_prog, struct bpf_verifier_env *env, ...@@ -209,6 +209,13 @@ nfp_bpf_check_call(struct nfp_prog *nfp_prog, struct bpf_verifier_env *env,
meta->func_id ? &meta->arg2 : NULL)) meta->func_id ? &meta->arg2 : NULL))
return -EOPNOTSUPP; return -EOPNOTSUPP;
break; break;
case BPF_FUNC_get_prandom_u32:
if (bpf->pseudo_random)
break;
pr_vlog(env, "bpf_get_prandom_u32(): FW doesn't support random number generation\n");
return -EOPNOTSUPP;
default: default:
pr_vlog(env, "unsupported function id: %d\n", func_id); pr_vlog(env, "unsupported function id: %d\n", func_id);
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -284,6 +284,7 @@ enum lcsr_wr_src { ...@@ -284,6 +284,7 @@ enum lcsr_wr_src {
#define NFP_CSR_ACT_LM_ADDR1 0x6c #define NFP_CSR_ACT_LM_ADDR1 0x6c
#define NFP_CSR_ACT_LM_ADDR2 0x94 #define NFP_CSR_ACT_LM_ADDR2 0x94
#define NFP_CSR_ACT_LM_ADDR3 0x9c #define NFP_CSR_ACT_LM_ADDR3 0x9c
#define NFP_CSR_PSEUDO_RND_NUM 0x148
/* 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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment