[Skiboot] [PATCH 32/32] xive: Implement xive_reset
Benjamin Herrenschmidt
benh at kernel.crashing.org
Tue Nov 22 13:13:34 AEDT 2016
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
hw/xive.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
include/xive.h | 6 ++-
2 files changed, 154 insertions(+), 12 deletions(-)
diff --git a/hw/xive.c b/hw/xive.c
index cf7f932..baddd1b 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -3047,16 +3047,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,
@@ -3300,6 +3290,156 @@ 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 = {};
+ 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 = {};
+
+ /* 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;
diff --git a/include/xive.h b/include/xive.h
index 7db7ee0..c7b96fa 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -299,12 +299,14 @@
*/
#define TM_SPC_ACK_EBB 0x800 /* Load8 ack EBB to reg*/
#define TM_SPC_ACK_OS_REG 0x810 /* Load16 ack OS irq to reg */
-#define TM_SPC_ACK_OS_EL 0xc10 /* Store8 ack OS irq to even line */
#define TM_SPC_PUSH_USR_CTX 0x808 /* Store32 Push/Validate user context */
#define TM_SPC_PULL_USR_CTX 0x808 /* Load32 Pull/Invalidate user context */
-#define TM_SPC_PULL_USR_CTX_OL 0xc08 /* Store8 Pull/Inval usr ctx to odd line */
#define TM_SPC_SET_OS_PENDING 0x812 /* Store8 Set OS irq pending bit */
+#define TM_SPC_PULL_OS_CTX 0x818 /* Load32/Load64 Pull/Invalidate OS context to reg */
+#define TM_SPC_PULL_POOL_CTX 0x828 /* Load32/Load64 Pull/Invalidate Pool context to reg*/
#define TM_SPC_ACK_HV_REG 0x830 /* Load16 ack HV irq to reg */
+#define TM_SPC_PULL_USR_CTX_OL 0xc08 /* Store8 Pull/Inval usr ctx to odd line */
+#define TM_SPC_ACK_OS_EL 0xc10 /* Store8 ack OS irq to even line */
#define TM_SPC_ACK_HV_POOL_EL 0xc20 /* Store8 ack HV evt pool to even line */
#define TM_SPC_ACK_HV_EL 0xc30 /* Store8 ack HV irq to even line */
/* XXX more... */
--
2.7.4
More information about the Skiboot
mailing list