aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2020-08-04 19:01:11 +0200
committerOliver O'Halloran <oohall@gmail.com>2020-08-07 16:00:20 +1000
commit043725d49d3b2c0b6ea3c37395aa5d6e38d5e73a (patch)
treed0fcb8064a15fd76eeebc275796cdf045be5fbf8 /hw
parenta8191a205ef5f51b72cb7624770bf7b0522b5deb (diff)
downloadskiboot-043725d49d3b2c0b6ea3c37395aa5d6e38d5e73a.zip
skiboot-043725d49d3b2c0b6ea3c37395aa5d6e38d5e73a.tar.gz
skiboot-043725d49d3b2c0b6ea3c37395aa5d6e38d5e73a.tar.bz2
xive/p9: Enforce thread enablement before TIMA accesses
To activate the HW thread context ring, and its associated thread interrupt registers, a thread needs to raise the VT bit in word2. This requires access to the TIMA and this access is only granted if the thread was first enabled at the XIVE IC level. This is done in a sequence in xive_cpu_callin() but there is a chance that the accesses done on the TIMA do not see the update of the enable register. To make sure that the enablement has completed, add an extra load on the PC_THREAD_EN_REGx register. This guarantees that the TIMA accesses will see the latest state of the enable register. Signed-off-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/xive.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/hw/xive.c b/hw/xive.c
index 2e0b198..f8837ae 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -2741,6 +2741,7 @@ static void xive_reset_enable_thread(struct cpu_thread *c)
struct proc_chip *chip = get_chip(c->chip_id);
struct xive *x = chip->xive;
uint32_t fc, bit;
+ uint64_t enable;
/* Get fused core number */
fc = (c->pir >> 3) & 0xf;
@@ -2752,9 +2753,23 @@ static void xive_reset_enable_thread(struct cpu_thread *c)
if (fc < 8) {
xive_regw(x, PC_THREAD_EN_REG0_CLR, PPC_BIT(bit));
xive_regw(x, PC_THREAD_EN_REG0_SET, PPC_BIT(bit));
+
+ /*
+ * To guarantee that the TIMA accesses will see the
+ * latest state of the enable register, add an extra
+ * load on PC_THREAD_EN_REG.
+ */
+ enable = xive_regr(x, PC_THREAD_EN_REG0);
+ if (!(enable & PPC_BIT(bit)))
+ xive_cpu_err(c, "Failed to enable thread\n");
} else {
xive_regw(x, PC_THREAD_EN_REG1_CLR, PPC_BIT(bit));
xive_regw(x, PC_THREAD_EN_REG1_SET, PPC_BIT(bit));
+
+ /* Same as above */
+ enable = xive_regr(x, PC_THREAD_EN_REG1);
+ if (!(enable & PPC_BIT(bit)))
+ xive_cpu_err(c, "Failed to enable thread\n");
}
}