diff mbox series

hw/nx: Fix NX BAR assignments

Message ID 20171124010223.5574-1-oohall@gmail.com
State Accepted
Headers show
Series hw/nx: Fix NX BAR assignments | expand

Commit Message

Oliver O'Halloran Nov. 24, 2017, 1:02 a.m. UTC
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@gmail.com>
---
 hw/nx-rng.c | 26 ++++++++++++++++++++++++--
 hw/nx.c     | 47 ++++++++++++++++++++++-------------------------
 2 files changed, 46 insertions(+), 27 deletions(-)

Comments

Stewart Smith Dec. 1, 2017, 5:15 a.m. UTC | #1
Oliver O'Halloran <oohall@gmail.com> writes:
> 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@gmail.com>

Thanks, merged to master as of ac685bccd8899b6021f6441551e845151a9a1b94-- 
Stewart Smith
OPAL Architect, IBM.
diff mbox series

Patch

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();
 }