aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2016-12-22 14:16:42 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-01-05 15:41:01 +1100
commit9b95afb521b1e2634e518b1851e2c902e83a888a (patch)
tree8b74d883332f8d0d64d00b75947797247ed5fd98 /hw
parent6e1b56ecf2fa9e5537887879852b53186341f4ba (diff)
downloadskiboot-9b95afb521b1e2634e518b1851e2c902e83a888a.zip
skiboot-9b95afb521b1e2634e518b1851e2c902e83a888a.tar.gz
skiboot-9b95afb521b1e2634e518b1851e2c902e83a888a.tar.bz2
xive: Implement xive_reset
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [stewart@linux.vnet.ibm.com: fix build failure on older GCC - e.g. 4.8] Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/xive.c159
1 files changed, 149 insertions, 10 deletions
diff --git a/hw/xive.c b/hw/xive.c
index f7f4937..c5fb6c7 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -3051,16 +3051,6 @@ static int64_t opal_xive_set_mfrr(uint32_t cpu, uint8_t mfrr)
return OPAL_SUCCESS;
}
-static int64_t opal_xive_reset(uint64_t version)
-{
- if (version > 1)
- return OPAL_PARAMETER;
-
- xive_mode = version;
-
- return OPAL_SUCCESS;
-}
-
static int64_t opal_xive_get_irq_info(uint32_t girq,
uint64_t *out_flags,
uint64_t *out_eoi_page,
@@ -3310,6 +3300,155 @@ static int64_t opal_xive_donate_page(uint32_t chip_id, uint64_t addr)
return OPAL_SUCCESS;
}
+static void xive_cleanup_cpu_cam(struct cpu_thread *c)
+{
+ struct xive_cpu_state *xs = c->xstate;
+ struct xive *x = xs->xive;
+ void *ind_tm_base = x->ic_base + 4 * IC_PAGE_SIZE;
+
+ /* Setup indirect access to the corresponding thread */
+ xive_regw(x, PC_TCTXT_INDIR0,
+ PC_TCTXT_INDIR_VALID |
+ SETFIELD(PC_TCTXT_INDIR_THRDID, 0ull, c->pir & 0xff));
+
+ /* Pull user context, OS context and Pool context if any */
+ in_be32(ind_tm_base + TM_SPC_PULL_USR_CTX);
+ in_be32(ind_tm_base + TM_SPC_PULL_OS_CTX);
+ in_be32(ind_tm_base + TM_SPC_PULL_POOL_CTX);
+
+ /* Set HV CPPR to 0 */
+ out_8(ind_tm_base + TM_QW3_HV_PHYS + TM_CPPR, 0);
+
+ /* Reset indirect access */
+ xive_regw(x, PC_TCTXT_INDIR0, 0);
+}
+
+static void xive_reset_one(struct xive *x)
+{
+ struct cpu_thread *c;
+ int i = 0;
+
+ /* Mask all interrupt sources */
+ while ((i = bitmap_find_one_bit(*x->int_enabled_map,
+ i, MAX_INT_ENTRIES - i)) >= 0) {
+ opal_xive_set_irq_config(x->int_base + i, 0, 0xff,
+ x->int_base + i);
+ i++;
+ }
+
+ lock(&x->lock);
+ memset(x->int_enabled_map, 0, BITMAP_BYTES(MAX_INT_ENTRIES));
+
+ /* Reset all allocated EQs and free the user ones */
+ bitmap_for_each_one(*x->eq_map, MAX_EQ_COUNT >> 3, i) {
+ struct xive_eq eq0 = {0};
+ struct xive_eq *eq;
+
+ eq = xive_get_eq(x, i);
+ if (!eq)
+ continue;
+ xive_eqc_cache_update(x, x->block_id,
+ i, 0, 4, &eq0, false, true);
+ if (!(eq->w0 & EQ_W0_FIRMWARE))
+ bitmap_clr_bit(*x->eq_map, i);
+ }
+
+ /* Take out all VPs from HW and reset all CPPRs to 0 */
+ for_each_cpu(c) {
+ if (c->chip_id != x->chip_id)
+ continue;
+ if (!c->xstate)
+ continue;
+ xive_cleanup_cpu_cam(c);
+ }
+
+ /* Reset all user-allocated VPs. This is inefficient, we should
+ * either keep a bitmap of allocated VPs or add an iterator to
+ * the buddy which is trickier but doable.
+ */
+ for (i = 0; i < MAX_VP_COUNT; i++) {
+ struct xive_vp *vp;
+ struct xive_vp vp0 = {0};
+
+ /* Ignore the physical CPU VPs */
+#ifdef USE_BLOCK_GROUP_MODE
+ if (i >= INITIAL_VP_BASE &&
+ i < (INITIAL_VP_BASE + INITIAL_VP_COUNT))
+ continue;
+#else
+ if (x->block_id == 0 &&
+ i >= INITIAL_BLK0_VP_BASE &&
+ i < (INITIAL_BLK0_VP_BASE + INITIAL_BLK0_VP_BASE))
+ continue;
+#endif
+ /* Is the VP valid ? */
+ vp = xive_get_vp(x, i);
+ if (!vp || !(vp->w0 & VP_W0_VALID))
+ continue;
+
+ /* Clear it */
+ xive_vpc_cache_update(x, x->block_id,
+ i, 0, 8, &vp0, false, true);
+ }
+
+#ifndef USE_BLOCK_GROUP_MODE
+ /* If block group mode isn't enabled, reset VP alloc buddy */
+ buddy_reset(x->vp_buddy);
+#endif
+
+ /* Re-configure the CPUs */
+ for_each_cpu(c) {
+ struct xive_cpu_state *xs = c->xstate;
+
+ if (c->chip_id != x->chip_id || !xs)
+ continue;
+
+ /* Setup default VP and EQ */
+ xive_init_cpu_defaults(xs);
+
+ /* Re-Initialize the XICS emulation related fields
+ * and re-enable IPI
+ */
+ if (xive_mode == XIVE_MODE_EMU) {
+ xive_init_xics_emulation(xs);
+ xive_ipi_init(x, c);
+ }
+ }
+
+ unlock(&x->lock);
+}
+
+static int64_t opal_xive_reset(uint64_t version)
+{
+ struct proc_chip *chip;
+
+ if (version > 1)
+ return OPAL_PARAMETER;
+
+ xive_mode = version;
+
+ /* For each XIVE ... */
+ for_each_chip(chip) {
+ if (!chip->xive)
+ continue;
+ xive_reset_one(chip->xive);
+ }
+
+#ifdef USE_BLOCK_GROUP_MODE
+ /* Cleanup global VP allocator */
+ buddy_reset(xive_vp_buddy);
+
+ /* We reserve the whole range of VPs representing HW chips.
+ *
+ * These are 0x80..0xff, so order 7 starting at 0x80. This will
+ * reserve that range on each chip.
+ */
+ assert(buddy_reserve(xive_vp_buddy, 0x80, 7));
+#endif /* USE_BLOCK_GROUP_MODE */
+
+ return OPAL_SUCCESS;
+}
+
static void xive_init_globals(void)
{
uint32_t i;