aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver O'Halloran <oohall@gmail.com>2017-11-24 12:02:23 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-11-30 22:28:33 -0600
commitac685bccd8899b6021f6441551e845151a9a1b94 (patch)
tree147a85bd21bc75a28a89d690e86863f5c5ef7f66
parent73ad014b8785caa249a6d305d8c8502064912908 (diff)
downloadskiboot-ac685bccd8899b6021f6441551e845151a9a1b94.zip
skiboot-ac685bccd8899b6021f6441551e845151a9a1b94.tar.gz
skiboot-ac685bccd8899b6021f6441551e845151a9a1b94.tar.bz2
hw/nx: Fix NX BAR assignments
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> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--hw/nx-rng.c26
-rw-r--r--hw/nx.c47
2 files changed, 46 insertions, 27 deletions
diff --git a/hw/nx-rng.c b/hw/nx-rng.c
index 48eba56..a74fa45 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 64ac793..f6e823f 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();
}