diff mbox series

[bpf-next,13/14] nfp: bpf: add support for bpf_get_prandom_u32()

Message ID 20180329004839.4506-14-jakub.kicinski@netronome.com
State Accepted, archived
Delegated to: BPF Maintainers
Headers show
Series nfp: bpf: add updates, deletes, atomic ops, prandom and packet cache | expand

Commit Message

Jakub Kicinski March 29, 2018, 12:48 a.m. UTC
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: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jiong Wang <jiong.wang@netronome.com>
---
 drivers/net/ethernet/netronome/nfp/bpf/fw.h       |  1 +
 drivers/net/ethernet/netronome/nfp/bpf/jit.c      | 24 +++++++++++++++++++++--
 drivers/net/ethernet/netronome/nfp/bpf/main.c     | 12 ++++++++++++
 drivers/net/ethernet/netronome/nfp/bpf/main.h     |  4 ++++
 drivers/net/ethernet/netronome/nfp/bpf/verifier.c |  7 +++++++
 drivers/net/ethernet/netronome/nfp/nfp_asm.h      |  1 +
 6 files changed, 47 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/netronome/nfp/bpf/fw.h b/drivers/net/ethernet/netronome/nfp/bpf/fw.h
index cfcc7bcb2c67..39639ac28b01 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/fw.h
+++ b/drivers/net/ethernet/netronome/nfp/bpf/fw.h
@@ -41,6 +41,7 @@  enum bpf_cap_tlv_type {
 	NFP_BPF_CAP_TYPE_FUNC		= 1,
 	NFP_BPF_CAP_TYPE_ADJUST_HEAD	= 2,
 	NFP_BPF_CAP_TYPE_MAPS		= 3,
+	NFP_BPF_CAP_TYPE_RANDOM		= 4,
 };
 
 struct nfp_bpf_cap_tlv_func {
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
index 62431a0aa0f5..4b631e26f199 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
@@ -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_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);
 
@@ -433,10 +433,16 @@  static void emit_csr_wr(struct nfp_prog *nfp_prog, swreg src, u16 addr)
 		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);
@@ -1398,6 +1404,18 @@  map_call_stack_common(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 	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)
 {
@@ -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_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;
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index a7e217c5204f..f2214101a1b5 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -315,6 +315,14 @@  nfp_bpf_parse_cap_maps(struct nfp_app_bpf *bpf, void __iomem *value, u32 length)
 	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;
@@ -353,6 +361,10 @@  static int nfp_bpf_parse_capabilities(struct nfp_app *app)
 			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;
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h
index a73b86c6ce52..4981c8944ca3 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.h
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h
@@ -133,6 +133,8 @@  enum pkt_vec {
  * @helpers.map_lookup:		map lookup helper address
  * @helpers.map_update:		map update 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 *app;
@@ -170,6 +172,8 @@  struct nfp_app_bpf {
 		u32 map_update;
 		u32 map_delete;
 	} helpers;
+
+	bool pseudo_random;
 };
 
 enum nfp_bpf_map_use {
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
index 486ffd1d5913..06ad53ce4ad9 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c
@@ -209,6 +209,13 @@  nfp_bpf_check_call(struct nfp_prog *nfp_prog, struct bpf_verifier_env *env,
 					  meta->func_id ? &meta->arg2 : NULL))
 			return -EOPNOTSUPP;
 		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:
 		pr_vlog(env, "unsupported function id: %d\n", func_id);
 		return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_asm.h b/drivers/net/ethernet/netronome/nfp/nfp_asm.h
index 36524dd6021b..5f2b2f24f4fa 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_asm.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_asm.h
@@ -284,6 +284,7 @@  enum lcsr_wr_src {
 #define NFP_CSR_ACT_LM_ADDR1	0x6c
 #define NFP_CSR_ACT_LM_ADDR2	0x94
 #define NFP_CSR_ACT_LM_ADDR3	0x9c
+#define NFP_CSR_PSEUDO_RND_NUM	0x148
 
 /* Software register representation, independent of operand type */
 #define NN_REG_TYPE	GENMASK(31, 24)