FIELD_PREP(OP_LCSR_A_SRC, areg) |
FIELD_PREP(OP_LCSR_B_SRC, breg) |
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_DST_LMEXTN, dst_lmextn);
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);
}
+/* 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)
{
__emit_immed(nfp_prog, UR_REG_IMM, UR_REG_IMM, 0, 0, 0, 0, 0, 0, 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 --- */
static int mov_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
case BPF_FUNC_map_update_elem:
case BPF_FUNC_map_delete_elem:
return map_call_stack_common(nfp_prog, meta);
+ case BPF_FUNC_get_prandom_u32:
+ return nfp_get_prandom_u32(nfp_prog, meta);
default:
WARN_ONCE(1, "verifier allowed unsupported function\n");
return -EOPNOTSUPP;
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)
{
struct nfp_cpp *cpp = app->pf->cpp;
if (nfp_bpf_parse_cap_maps(app->priv, value, length))
goto err_release_free;
break;
+ case NFP_BPF_CAP_TYPE_RANDOM:
+ if (nfp_bpf_parse_cap_random(app->priv, value, length))
+ goto err_release_free;
+ break;
default:
nfp_dbg(cpp, "unknown BPF capability: %d\n", type);
break;