[Skiboot] [PATCH] hw/nx: Fix NX BAR assignments

Oliver O'Halloran oohall at gmail.com
Fri Nov 24 12:02:23 AEDT 2017


The NX rng BAR is used by each core to source random numbers for the
DARN instruction. Currently we configure each core to use the NX rng of
the chip that it exists on. Unfortunately, the NX can be deconfigured by
hostboot and in this case we need to use the NX of a different chip.

This patch moves the BAR assignments for the NX into the normal nx-rng
init path. This lets us check if the normal (chip local) NX is active
when configuring which NX a core should use so that we can fallback
gracefully.

Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
 hw/nx-rng.c | 26 ++++++++++++++++++++++++--
 hw/nx.c     | 47 ++++++++++++++++++++++-------------------------
 2 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/hw/nx-rng.c b/hw/nx-rng.c
index 48eba5695d40..a74fa45a710a 100644
--- a/hw/nx-rng.c
+++ b/hw/nx-rng.c
@@ -21,6 +21,29 @@
 #include <io.h>
 #include <cpu.h>
 #include <nx.h>
+#include <chip.h>
+#include <phys-map.h>
+#include <xscom-p9-regs.h>
+
+/*
+ * On P9 the DARN instruction is used to access the HW RNG. There is still
+ * an NX RNG BAR, but it is used to configure which NX a core will source
+ * random numbers from rather than being a MMIO window.
+ */
+static void nx_init_p9_rng(uint32_t chip_id)
+{
+	uint64_t bar, tmp;
+
+	if (chip_quirk(QUIRK_NO_RNG))
+		return;
+
+	phys_map_get(chip_id, NX_RNG, 0, &bar, NULL);
+	xscom_write(chip_id, P9X_NX_MMIO_BAR, bar | P9X_NX_MMIO_BAR_EN);
+
+	/* Read config register for pace info */
+	xscom_read(chip_id, P9X_NX_RNG_CFG, &tmp);
+	prlog(PR_INFO, "NX RNG[%x] pace:%lli\n", chip_id, 0xffff & (tmp >> 2));
+}
 
 void nx_create_rng_node(struct dt_node *node)
 {
@@ -44,8 +67,7 @@ void nx_create_rng_node(struct dt_node *node)
 		xcfg = pb_base + NX_P8_RNG_CFG;
 		addr_mask = NX_P8_RNG_BAR_ADDR;
 	} else if (dt_node_is_compatible(node, "ibm,power9-nx")) {
-		prlog(PR_INFO, "NX%d: POWER9 nx-rng not yet supported\n",
-		      gcid);
+		nx_init_p9_rng(gcid);
 		return;
 	} else {
 		prerror("NX%d: Unknown NX type!\n", gcid);
diff --git a/hw/nx.c b/hw/nx.c
index 64ac793c0ca5..f6e823f67b0a 100644
--- a/hw/nx.c
+++ b/hw/nx.c
@@ -25,40 +25,36 @@
 #include <xscom-p9-regs.h>
 #include <phys-map.h>
 
-extern void nx_p9_rng_init(void);
-
-void nx_p9_rng_init(void)
+static void p9_darn_init(void)
 {
+	struct dt_node *nx;
 	struct proc_chip *chip;
 	struct cpu_thread *c;
-	uint64_t bar, tmp;
+	uint64_t bar, default_bar;
 
-	if (proc_gen != proc_gen_p9)
-		return;
 	if (chip_quirk(QUIRK_NO_RNG))
 		return;
 
 	/*
-	 * Two things we need to setup here:
-	 *
-	 * 1) The per chip BAR for the NX RNG region. The location of
-	 *    this is determined by the global MMIO Map.
-
-	 * 2) The per core BAR for the DARN BAR, which points to the
-	 *    per chip RNG region set in 1.
-	 *
+	 * To allow the DARN instruction to function there must be at least
+	 * one NX available in the system. Otherwise using DARN will result
+	 * in a checkstop. I suppose we could mask the FIR...
 	 */
+	dt_for_each_compatible(dt_root, nx, "ibm,power9-nx")
+		break;
+	if (!nx) {
+		assert(nx);
+		return;
+	}
+
+	phys_map_get(dt_get_chip_id(nx), NX_RNG, 0, &default_bar, NULL);
+
 	for_each_chip(chip) {
-		/* 1) NX RNG BAR */
-		phys_map_get(chip->id, NX_RNG, 0, &bar, NULL);
-		xscom_write(chip->id, P9X_NX_MMIO_BAR,
-			    bar | P9X_NX_MMIO_BAR_EN);
-		/* Read config register for pace info */
-		xscom_read(chip->id, P9X_NX_RNG_CFG, &tmp);
-		prlog(PR_INFO, "NX RNG[%x] pace:%lli\n", chip->id,
-		      0xffff & (tmp >> 2));
+		/* is this NX enabled? */
+		xscom_read(chip->id, P9X_NX_MMIO_BAR, &bar);
+		if (!(bar & ~P9X_NX_MMIO_BAR_EN))
+			bar = default_bar;
 
-		/* 2) DARN BAR */
 		for_each_available_core_in_chip(c, chip->id) {
 			uint64_t addr;
 			addr = XSCOM_ADDR_P9_EX(pir_to_core_id(c->pir),
@@ -80,8 +76,6 @@ void nx_init(void)
 {
 	struct dt_node *node;
 
-	nx_p9_rng_init();
-
 	dt_for_each_compatible(dt_root, node, "ibm,power-nx") {
 		nx_init_one(node);
 	}
@@ -89,4 +83,7 @@ void nx_init(void)
 	dt_for_each_compatible(dt_root, node, "ibm,power9-nx") {
 		nx_init_one(node);
 	}
+
+	if (proc_gen == proc_gen_p9)
+		p9_darn_init();
 }
-- 
2.9.5



More information about the Skiboot mailing list