[Skiboot] [PATCH 19/22] xive/p9: remove XICS emulation

Cédric Le Goater clg at kaod.org
Wed Sep 4 03:04:10 AEST 2019


This emulation was required to run pre-POWER9 linux kernels.

Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
 hw/xive-p9.c | 925 +--------------------------------------------------
 1 file changed, 5 insertions(+), 920 deletions(-)

diff --git a/hw/xive-p9.c b/hw/xive-p9.c
index cdc44a123b08..320ec65ebe1f 100644
--- a/hw/xive-p9.c
+++ b/hw/xive-p9.c
@@ -27,28 +27,15 @@
 #include <phys-map.h>
 #include <p9_stop_api.H>
 
-/* Always notify from EQ to VP (no EOI on EQs). Will speed up
- * EOIs at the expense of potentially higher powerbus traffic.
- */
-#define EQ_ALWAYS_NOTIFY
-
 /* Verbose debug */
 #undef XIVE_VERBOSE_DEBUG
 
 /* Extra debug options used in debug builds */
 #ifdef DEBUG
-#define XIVE_DEBUG_DUPLICATES
 #define XIVE_PERCPU_LOG
-#define XIVE_DEBUG_INIT_CACHE_UPDATES
-#define XIVE_EXTRA_CHECK_INIT_CACHE
-#undef XIVE_CHECK_MISROUTED_IPI
 #define XIVE_CHECK_LOCKS
 #else
-#undef  XIVE_DEBUG_DUPLICATES
 #undef  XIVE_PERCPU_LOG
-#undef  XIVE_DEBUG_INIT_CACHE_UPDATES
-#undef  XIVE_EXTRA_CHECK_INIT_CACHE
-#undef  XIVE_CHECK_MISROUTED_IPI
 #undef  XIVE_CHECK_LOCKS
 #endif
 
@@ -178,9 +165,6 @@
 /* Number of priorities (and thus EQDs) we allocate for each VP */
 #define NUM_INT_PRIORITIES	8
 
-/* Priority used for the one queue in XICS emulation */
-#define XIVE_EMULATION_PRIO	7
-
 /* Max number of VPs. We allocate an indirect table big enough so
  * that when fully populated we can have that many VPs.
  *
@@ -214,7 +198,6 @@
  * to the "mode" parameter of the opal_xive_reset() call
  */
 static enum {
-	XIVE_MODE_EMU	= OPAL_XIVE_MODE_EMU,
 	XIVE_MODE_EXPL	= OPAL_XIVE_MODE_EXPL,
 	XIVE_MODE_NONE,
 } xive_mode = XIVE_MODE_NONE;
@@ -261,23 +244,8 @@ struct xive_cpu_state {
 	uint32_t	vp_idx;
 	uint32_t	eq_blk;
 	uint32_t	eq_idx; /* Base eq index of a block of 8 */
-	void		*eq_page;
 
-	/* Pre-allocated IPI */
-	uint32_t	ipi_irq;
-
-	/* Use for XICS emulation */
 	struct lock	lock;
-	uint8_t		cppr;
-	uint8_t		mfrr;
-	uint8_t		pending;
-	uint8_t		prev_cppr;
-	uint32_t	*eqbuf;
-	uint32_t	eqptr;
-	uint32_t	eqmsk;
-	uint8_t		eqgen;
-	void		*eqmmio;
-	uint64_t	total_irqs;
 };
 
 #ifdef XIVE_PERCPU_LOG
@@ -801,41 +769,6 @@ static void xive_init_default_vp(struct xive_vp *vp,
 	vp->w0 = VP_W0_VALID;
 }
 
-static void xive_init_emu_eq(uint32_t vp_blk, uint32_t vp_idx,
-			     struct xive_eq *eq, void *backing_page,
-			     uint8_t prio)
-{
-	memset(eq, 0, sizeof(struct xive_eq));
-
-	eq->w1 = EQ_W1_GENERATION;
-	eq->w3 = ((uint64_t)backing_page) & 0xffffffff;
-	eq->w2 = (((uint64_t)backing_page)) >> 32 & 0x0fffffff;
-	eq->w6 = SETFIELD(EQ_W6_NVT_BLOCK, 0ul, vp_blk) |
-		SETFIELD(EQ_W6_NVT_INDEX, 0ul, vp_idx);
-	eq->w7 = SETFIELD(EQ_W7_F0_PRIORITY, 0ul, prio);
-	eq->w0 = EQ_W0_VALID | EQ_W0_ENQUEUE |
-		SETFIELD(EQ_W0_QSIZE, 0ul, EQ_QSIZE_64K) |
-		EQ_W0_FIRMWARE;
-#ifdef EQ_ALWAYS_NOTIFY
-	eq->w0 |= EQ_W0_UCOND_NOTIFY;
-#endif
-}
-
-static uint32_t *xive_get_eq_buf(uint32_t eq_blk, uint32_t eq_idx)
-{
-	struct xive *x = xive_from_vc_blk(eq_blk);
-	struct xive_eq *eq;
-	uint64_t addr;
-
-	assert(x);
-	eq = xive_get_eq(x, eq_idx);
-	assert(eq);
-	assert(eq->w0 & EQ_W0_VALID);
-	addr = (((uint64_t)eq->w2) & 0x0fffffff) << 32 | eq->w3;
-
-	return (uint32_t *)addr;
-}
-
 static void *xive_get_donated_page(struct xive *x)
 {
 	return (void *)list_pop_(&x->donated_pages, 0);
@@ -2149,10 +2082,6 @@ static int64_t xive_set_irq_targetting(uint32_t isn, uint32_t target,
 
 	lock(&x->lock);
 
-	/* If using emulation mode, fixup prio to the only supported one */
-	if (xive_mode == XIVE_MODE_EMU && prio != 0xff)
-		prio = XIVE_EMULATION_PRIO;
-
 	/* Read existing IVE */
 	new_ive = ive->w;
 
@@ -2663,47 +2592,6 @@ static struct xive *init_one_xive(struct dt_node *np)
 	return NULL;
 }
 
-/*
- * XICS emulation
- */
-static void xive_ipi_init(struct xive *x, struct cpu_thread *cpu)
-{
-	struct xive_cpu_state *xs = cpu->xstate;
-
-	assert(xs);
-
-	__xive_set_irq_config(&x->ipis.is, xs->ipi_irq, cpu->pir,
-			      XIVE_EMULATION_PRIO, xs->ipi_irq,
-			      true, true);
-}
-
-static void xive_ipi_eoi(struct xive *x, uint32_t idx)
-{
-	uint8_t *mm = x->esb_mmio + idx * 0x20000;
-	uint8_t eoi_val;
-
-	/* For EOI, we use the special MMIO that does a clear of both
-	 * P and Q and returns the old Q.
-	 *
-	 * This allows us to then do a re-trigger if Q was set rather
-	 * than synthetizing an interrupt in software
-	 */
-	eoi_val = in_8(mm + 0x10c00);
-	if (eoi_val & 1) {
-		out_8(mm, 0);
-	}
-}
-
-static void xive_ipi_trigger(struct xive *x, uint32_t idx)
-{
-	uint8_t *mm = x->esb_mmio + idx * 0x20000;
-
-	xive_vdbg(x, "Trigger IPI 0x%x\n", idx);
-
-	out_8(mm, 0);
-}
-
-
 static void xive_reset_enable_thread(struct cpu_thread *c)
 {
 	struct proc_chip *chip = get_chip(c->chip_id);
@@ -2748,166 +2636,6 @@ static void xive_p9_cpu_callin(struct cpu_thread *cpu)
 		      old_w2, w2);
 }
 
-#ifdef XIVE_DEBUG_INIT_CACHE_UPDATES
-static bool xive_check_eq_update(struct xive *x, uint32_t idx, struct xive_eq *eq)
-{
-	struct xive_eq *eq_p = xive_get_eq(x, idx);
-	struct xive_eq eq2;
-
-	assert(eq_p);
-	eq2 = *eq_p;
-	if (memcmp(eq, &eq2, sizeof(eq)) != 0) {
-		xive_err(x, "EQ update mismatch idx %d\n", idx);
-		xive_err(x, "want: %08x %08x %08x %08x\n",
-			 eq->w0, eq->w1, eq->w2, eq->w3);
-		xive_err(x, "      %08x %08x %08x %08x\n",
-			 eq->w4, eq->w5, eq->w6, eq->w7);
-		xive_err(x, "got : %08x %08x %08x %08x\n",
-			 eq2.w0, eq2.w1, eq2.w2, eq2.w3);
-		xive_err(x, "      %08x %08x %08x %08x\n",
-			 eq2.w4, eq2.w5, eq2.w6, eq2.w7);
-		return false;
-	}
-	return true;
-}
-
-static bool xive_check_vpc_update(struct xive *x, uint32_t idx, struct xive_vp *vp)
-{
-	struct xive_vp *vp_p = xive_get_vp(x, idx);
-	struct xive_vp vp2;
-
-	assert(vp_p);
-	vp2 = *vp_p;
-	if (memcmp(vp, &vp2, sizeof(vp)) != 0) {
-		xive_err(x, "VP update mismatch idx %d\n", idx);
-		xive_err(x, "want: %08x %08x %08x %08x\n",
-			 vp->w0, vp->w1, vp->w2, vp->w3);
-		xive_err(x, "      %08x %08x %08x %08x\n",
-			 vp->w4, vp->w5, vp->w6, vp->w7);
-		xive_err(x, "got : %08x %08x %08x %08x\n",
-			 vp2.w0, vp2.w1, vp2.w2, vp2.w3);
-		xive_err(x, "      %08x %08x %08x %08x\n",
-			 vp2.w4, vp2.w5, vp2.w6, vp2.w7);
-		return false;
-	}
-	return true;
-}
-#else
-static inline bool xive_check_eq_update(struct xive *x __unused,
-					uint32_t idx __unused,
-					struct xive_eq *eq __unused)
-{
-	return true;
-}
-
-static inline bool xive_check_vpc_update(struct xive *x __unused,
-					 uint32_t idx __unused,
-					 struct xive_vp *vp __unused)
-{
-	return true;
-}
-#endif
-
-#ifdef XIVE_EXTRA_CHECK_INIT_CACHE
-static void xive_special_cache_check(struct xive *x, uint32_t blk, uint32_t idx)
-{
-	struct xive_vp vp = {0};
-	uint32_t i;
-
-	for (i = 0; i < 1000; i++) {
-		struct xive_vp *vp_m = xive_get_vp(x, idx);
-
-		memset(vp_m, (~i) & 0xff, sizeof(*vp_m));
-		sync();
-		vp.w1 = (i << 16) | i;
-		xive_vpc_cache_update(x, blk, idx,
-				      0, 8, &vp, false, true);
-		if (!xive_check_vpc_update(x, idx, &vp)) {
-			xive_dbg(x, "Test failed at %d iterations\n", i);
-			return;
-		}
-	}
-	xive_dbg(x, "1000 iterations test success at %d/0x%x\n", blk, idx);
-}
-#else
-static inline void xive_special_cache_check(struct xive *x __unused,
-					    uint32_t blk __unused,
-					    uint32_t idx __unused)
-{
-}
-#endif
-
-static void xive_setup_hw_for_emu(struct xive_cpu_state *xs)
-{
-	struct xive_eq eq;
-	struct xive_vp vp;
-	struct xive *x_eq, *x_vp;
-
-	/* Grab the XIVE where the VP resides. It could be different from
-	 * the local chip XIVE if not using block group mode
-	 */
-	x_vp = xive_from_pc_blk(xs->vp_blk);
-	assert(x_vp);
-
-	/* Grab the XIVE where the EQ resides. It will be the same as the
-	 * VP one with the current provisioning but I prefer not making
-	 * this code depend on it.
-	 */
-	x_eq = xive_from_vc_blk(xs->eq_blk);
-	assert(x_eq);
-
-	/* Initialize the structure */
-	xive_init_emu_eq(xs->vp_blk, xs->vp_idx, &eq,
-			 xs->eq_page, XIVE_EMULATION_PRIO);
-
-	/* Use the cache watch to write it out */
-	lock(&x_eq->lock);
-	xive_eqc_cache_update(x_eq, xs->eq_blk,
-			      xs->eq_idx + XIVE_EMULATION_PRIO,
-			      0, 4, &eq, false, true);
-	xive_check_eq_update(x_eq, xs->eq_idx + XIVE_EMULATION_PRIO, &eq);
-
-	/* Extra testing of cache watch & scrub facilities */
-	xive_special_cache_check(x_vp, xs->vp_blk, xs->vp_idx);
-	unlock(&x_eq->lock);
-
-	/* Initialize/enable the VP */
-	xive_init_default_vp(&vp, xs->eq_blk, xs->eq_idx);
-
-	/* Use the cache watch to write it out */
-	lock(&x_vp->lock);
-	xive_vpc_cache_update(x_vp, xs->vp_blk, xs->vp_idx,
-			      0, 8, &vp, false, true);
-	xive_check_vpc_update(x_vp, xs->vp_idx, &vp);
-	unlock(&x_vp->lock);
-}
-
-static void xive_init_cpu_emulation(struct xive_cpu_state *xs,
-				    struct cpu_thread *cpu)
-{
-	struct xive *x;
-
-	/* Setup HW EQ and VP */
-	xive_setup_hw_for_emu(xs);
-
-	/* Setup and unmask the IPI */
-	xive_ipi_init(xs->xive, cpu);
-
-	/* Initialize remaining state */
-	xs->cppr = 0;
-	xs->mfrr = 0xff;
-	xs->eqbuf = xive_get_eq_buf(xs->vp_blk,
-				    xs->eq_idx + XIVE_EMULATION_PRIO);
-	assert(xs->eqbuf);
-	memset(xs->eqbuf, 0, 0x10000);
-
-	xs->eqptr = 0;
-	xs->eqmsk = (0x10000/4) - 1;
-	xs->eqgen = 0;
-	x = xive_from_vc_blk(xs->eq_blk);
-	assert(x);
-	xs->eqmmio = x->eq_mmio + (xs->eq_idx + XIVE_EMULATION_PRIO) * 0x20000;
-}
 
 static void xive_init_cpu_exploitation(struct xive_cpu_state *xs)
 {
@@ -2928,15 +2656,6 @@ static void xive_init_cpu_exploitation(struct xive_cpu_state *xs)
 	xive_vpc_cache_update(x_vp, xs->vp_blk, xs->vp_idx,
 			      0, 8, &vp, false, true);
 	unlock(&x_vp->lock);
-
-	/* Clenaup remaining state */
-	xs->cppr = 0;
-	xs->mfrr = 0xff;
-	xs->eqbuf = NULL;
-	xs->eqptr = 0;
-	xs->eqmsk = 0;
-	xs->eqgen = 0;
-	xs->eqmmio = NULL;
 }
 
 static void xive_configure_ex_special_bar(struct xive *x, struct cpu_thread *c)
@@ -2989,7 +2708,6 @@ static void xive_p9_late_init(void)
 static void xive_provision_cpu(struct xive_cpu_state *xs, struct cpu_thread *c)
 {
 	struct xive *x;
-	void *p;
 
 	/* Physical VPs are pre-allocated */
 	xs->vp_blk = PIR2VP_BLK(c->pir);
@@ -3009,16 +2727,6 @@ static void xive_provision_cpu(struct xive_cpu_state *xs, struct cpu_thread *c)
 	/* Allocate a set of EQs for that VP */
 	xs->eq_idx = xive_alloc_eq_set(x, true);
 	assert(!XIVE_ALLOC_IS_ERR(xs->eq_idx));
-
-	/* Provision one of the queues. Allocate the memory on the
-	 * chip where the CPU resides
-	 */
-	p = local_alloc(c->chip_id, 0x10000, 0x10000);
-	if (!p) {
-		xive_err(x, "Failed to allocate EQ backing store\n");
-		assert(false);
-	}
-	xs->eq_page = p;
 }
 
 static void xive_init_cpu(struct cpu_thread *c)
@@ -3053,549 +2761,8 @@ static void xive_init_cpu(struct cpu_thread *c)
 	/* Shortcut to TM HV ring */
 	xs->tm_ring1 = x->tm_base + (1u << x->tm_shift);
 
-	/* Allocate an IPI */
-	xs->ipi_irq = xive_alloc_ipi_irqs(c->chip_id, 1, 1);
-
-	xive_cpu_vdbg(c, "CPU IPI is irq %08x\n", xs->ipi_irq);
-
 	/* Provision a VP and some EQDs for a physical CPU */
 	xive_provision_cpu(xs, c);
-
-	/* Initialize the XICS emulation related fields */
-	xive_init_cpu_emulation(xs, c);
-}
-
-static void xive_init_cpu_properties(struct cpu_thread *cpu)
-{
-	struct cpu_thread *t;
-	uint32_t iprop[8][2] = { };
-	uint32_t i;
-
-	assert(cpu_thread_count <= 8);
-
-	if (!cpu->node)
-		return;
-	for (i = 0; i < cpu_thread_count; i++) {
-		t = (i == 0) ? cpu : find_cpu_by_pir(cpu->pir + i);
-		if (!t)
-			continue;
-		iprop[i][0] = t->xstate->ipi_irq;
-		iprop[i][1] = 0; /* Edge */
-	}
-	dt_add_property(cpu->node, "interrupts", iprop, cpu_thread_count * 8);
-	dt_add_property_cells(cpu->node, "interrupt-parent", get_ics_phandle());
-}
-
-#ifdef XIVE_DEBUG_DUPLICATES
-static uint32_t xive_count_irq_copies(struct xive_cpu_state *xs, uint32_t ref)
-{
-	uint32_t i, irq;
-	uint32_t cnt = 0;
-	uint32_t pos = xs->eqptr;
-	uint32_t gen = xs->eqgen;
-
-	for (i = 0; i < 0x3fff; i++) {
-		irq = xs->eqbuf[pos];
-		if ((irq >> 31) == gen)
-			break;
-		if (irq == ref)
-			cnt++;
-		pos = (pos + 1) & xs->eqmsk;
-		if (!pos)
-			gen ^= 1;
-	}
-	return cnt;
-}
-#else
-static inline uint32_t xive_count_irq_copies(struct xive_cpu_state *xs __unused,
-					     uint32_t ref __unused)
-{
-	return 1;
-}
-#endif
-
-static uint32_t xive_read_eq(struct xive_cpu_state *xs, bool just_peek)
-{
-	uint32_t cur, copies;
-
-	xive_cpu_vdbg(this_cpu(), "  EQ %s... IDX=%x MSK=%x G=%d\n",
-		      just_peek ? "peek" : "read",
-		      xs->eqptr, xs->eqmsk, xs->eqgen);
-	cur = xs->eqbuf[xs->eqptr];
-	xive_cpu_vdbg(this_cpu(), "    cur: %08x [%08x %08x %08x ...]\n", cur,
-		      xs->eqbuf[(xs->eqptr + 1) & xs->eqmsk],
-		      xs->eqbuf[(xs->eqptr + 2) & xs->eqmsk],
-		      xs->eqbuf[(xs->eqptr + 3) & xs->eqmsk]);
-	if ((cur >> 31) == xs->eqgen)
-		return 0;
-
-	/* Debug: check for duplicate interrupts in the queue */
-	copies = xive_count_irq_copies(xs, cur);
-	if (copies > 1) {
-		struct xive_eq *eq;
-
-		prerror("Wow ! Dups of irq %x, found %d copies !\n",
-			cur & 0x7fffffff, copies);
-		prerror("[%08x > %08x %08x %08x %08x ...] eqgen=%x eqptr=%x jp=%d\n",
-			xs->eqbuf[(xs->eqptr - 1) & xs->eqmsk],
-			xs->eqbuf[(xs->eqptr + 0) & xs->eqmsk],
-			xs->eqbuf[(xs->eqptr + 1) & xs->eqmsk],
-			xs->eqbuf[(xs->eqptr + 2) & xs->eqmsk],
-			xs->eqbuf[(xs->eqptr + 3) & xs->eqmsk],
-			xs->eqgen, xs->eqptr, just_peek);
-		lock(&xs->xive->lock);
-		__xive_cache_scrub(xs->xive, xive_cache_eqc, xs->eq_blk,
-				   xs->eq_idx + XIVE_EMULATION_PRIO,
-				   false, false);
-		unlock(&xs->xive->lock);
-		eq = xive_get_eq(xs->xive, xs->eq_idx + XIVE_EMULATION_PRIO);
-		prerror("EQ @%p W0=%08x W1=%08x qbuf @%p\n",
-			eq, eq->w0, eq->w1, xs->eqbuf);
-	}
-	log_add(xs, LOG_TYPE_POPQ, 7, cur,
-		xs->eqbuf[(xs->eqptr + 1) & xs->eqmsk],
-		xs->eqbuf[(xs->eqptr + 2) & xs->eqmsk],
-		copies,
-		xs->eqptr, xs->eqgen, just_peek);
-	if (!just_peek) {
-		xs->eqptr = (xs->eqptr + 1) & xs->eqmsk;
-		if (xs->eqptr == 0)
-			xs->eqgen ^= 1;
-		xs->total_irqs++;
-	}
-	return cur & 0x00ffffff;
-}
-
-static uint8_t xive_sanitize_cppr(uint8_t cppr)
-{
-	if (cppr == 0xff || cppr == 0)
-		return cppr;
-	else
-		return XIVE_EMULATION_PRIO;
-}
-
-static inline uint8_t opal_xive_check_pending(struct xive_cpu_state *xs,
-					      uint8_t cppr)
-{
-	uint8_t mask = (cppr > 7) ? 0xff : ~((0x100 >> cppr) - 1);
-
-	return xs->pending & mask;
-}
-
-static void opal_xive_update_cppr(struct xive_cpu_state *xs, u8 cppr)
-{
-	/* Peform the update */
-	xs->cppr = cppr;
-	out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, cppr);
-
-	/* Trigger the IPI if it's still more favored than the CPPR
-	 *
-	 * This can lead to a bunch of spurrious retriggers if the
-	 * IPI is queued up behind other interrupts but that's not
-	 * a big deal and keeps the code simpler
-	 */
-	if (xs->mfrr < cppr)
-		xive_ipi_trigger(xs->xive, GIRQ_TO_IDX(xs->ipi_irq));
-}
-
-static int64_t opal_xive_eoi(uint32_t xirr)
-{
-	struct cpu_thread *c = this_cpu();
-	struct xive_cpu_state *xs = c->xstate;
-	uint32_t isn = xirr & 0x00ffffff;
-	struct xive *src_x;
-	bool special_ipi = false;
-	uint8_t cppr;
-
-	/*
-	 * In exploitation mode, this is supported as a way to perform
-	 * an EOI via a FW calls. This can be needed to workaround HW
-	 * implementation bugs for example. In this case interrupts will
-	 * have the OPAL_XIVE_IRQ_EOI_VIA_FW flag set.
-	 *
-	 * In that mode the entire "xirr" argument is interpreterd as
-	 * a global IRQ number (including the escalation bit), ther is
-	 * no split between the top 8 bits for CPPR and bottom 24 for
-	 * the interrupt number.
-	 */
-	if (xive_mode != XIVE_MODE_EMU)
-		return irq_source_eoi(xirr) ? OPAL_SUCCESS : OPAL_PARAMETER;
-
-	if (!xs)
-		return OPAL_INTERNAL_ERROR;
-
-	xive_cpu_vdbg(c, "EOI xirr=%08x cur_cppr=%d\n", xirr, xs->cppr);
-
-	/* Limit supported CPPR values from OS */
-	cppr = xive_sanitize_cppr(xirr >> 24);
-
-	lock(&xs->lock);
-
-	log_add(xs, LOG_TYPE_EOI, 3, isn, xs->eqptr, xs->eqgen);
-
-	/* If this was our magic IPI, convert to IRQ number */
-	if (isn == 2) {
-		isn = xs->ipi_irq;
-		special_ipi = true;
-		xive_cpu_vdbg(c, "User EOI for IPI !\n");
-	}
-
-	/* First check if we have stuff in that queue. If we do, don't bother with
-	 * doing an EOI on the EQ. Just mark that priority pending, we'll come
-	 * back later.
-	 *
-	 * If/when supporting multiple queues we would have to check them all
-	 * in ascending prio order up to the passed-in CPPR value (exclusive).
-	 */
-	if (xive_read_eq(xs, true)) {
-		xive_cpu_vdbg(c, "  isn %08x, skip, queue non empty\n", xirr);
-		xs->pending |= 1 << XIVE_EMULATION_PRIO;
-	}
-#ifndef EQ_ALWAYS_NOTIFY
-	else {
-		uint8_t eoi_val;
-
-		/* Perform EQ level EOI. Only one EQ for now ...
-		 *
-		 * Note: We aren't doing an actual EOI. Instead we are clearing
-		 * both P and Q and will re-check the queue if Q was set.
-		 */
-		eoi_val = in_8(xs->eqmmio + XIVE_ESB_SET_PQ_00);
-		xive_cpu_vdbg(c, "  isn %08x, eoi_val=%02x\n", xirr, eoi_val);
-
-		/* Q was set ? Check EQ again after doing a sync to ensure
-		 * ordering.
-		 */
-		if (eoi_val & 1) {
-			sync();
-			if (xive_read_eq(xs, true))
-				xs->pending |= 1 << XIVE_EMULATION_PRIO;
-		}
-	}
-#endif
-
-	/* Perform source level EOI if it's not our emulated MFRR IPI
-	 * otherwise EOI ourselves
-	 */
-	src_x = xive_from_isn(isn);
-	if (src_x) {
-		uint32_t idx = GIRQ_TO_IDX(isn);
-
-		/* Is it an IPI ? */
-		if (special_ipi) {
-			xive_ipi_eoi(src_x, idx);
-		} else {
-			/* Otherwise go through the source mechanism */
-			xive_vdbg(src_x, "EOI of IDX %x in EXT range\n", idx);
-			irq_source_eoi(isn);
-		}
-	} else {
-		xive_cpu_err(c, "  EOI unknown ISN %08x\n", isn);
-	}
-
-	/* Finally restore CPPR */
-	opal_xive_update_cppr(xs, cppr);
-
-	xive_cpu_vdbg(c, "  pending=0x%x cppr=%d\n", xs->pending, cppr);
-
-	unlock(&xs->lock);
-
-	/* Return whether something is pending that is suitable for
-	 * delivery considering the new CPPR value. This can be done
-	 * without lock as these fields are per-cpu.
-	 */
-	return opal_xive_check_pending(xs, cppr) ? 1 : 0;
-}
-
-#ifdef XIVE_CHECK_MISROUTED_IPI
-static void xive_dump_eq(uint32_t eq_blk, uint32_t eq_idx)
-{
-	struct cpu_thread *me = this_cpu();
-	struct xive *x;
-	struct xive_eq *eq;
-
-	x = xive_from_vc_blk(eq_blk);
-	if (!x)
-		return;
-	eq = xive_get_eq(x, eq_idx);
-	if (!eq)
-		return;
-	xive_cpu_err(me, "EQ: %08x %08x %08x %08x (@%p)\n",
-		     eq->w0, eq->w1, eq->w2, eq->w3, eq);
-	xive_cpu_err(me, "    %08x %08x %08x %08x\n",
-		     eq->w4, eq->w5, eq->w6, eq->w7);
-}
-static int64_t __opal_xive_dump_emu(struct xive_cpu_state *xs, uint32_t pir);
-
-static bool check_misrouted_ipi(struct cpu_thread *me, uint32_t irq)
-{
-	struct cpu_thread *c;
-
-	for_each_present_cpu(c) {
-		struct xive_cpu_state *xs = c->xstate;
-		struct xive_ive *ive;
-		uint32_t ipi_target, i, eq_blk, eq_idx;
-		struct proc_chip *chip;
-		struct xive *x;
-
-		if (!xs)
-			continue;
-		if (irq == xs->ipi_irq) {
-			xive_cpu_err(me, "misrouted IPI 0x%x, should"
-				     " be aimed at CPU 0x%x\n",
-				     irq, c->pir);
-			xive_cpu_err(me, " my eq_page=%p eqbuff=%p eq=0x%x/%x\n",
-				     me->xstate->eq_page, me->xstate->eqbuf,
-				     me->xstate->eq_blk, me->xstate->eq_idx + XIVE_EMULATION_PRIO);
-			xive_cpu_err(me, "tgt eq_page=%p eqbuff=%p eq=0x%x/%x\n",
-				     c->xstate->eq_page, c->xstate->eqbuf,
-				     c->xstate->eq_blk, c->xstate->eq_idx + XIVE_EMULATION_PRIO);
-			__opal_xive_dump_emu(me->xstate, me->pir);
-			__opal_xive_dump_emu(c->xstate, c->pir);
-			if (xive_get_irq_targetting(xs->ipi_irq, &ipi_target, NULL, NULL))
-				xive_cpu_err(me, "target=%08x\n", ipi_target);
-			else
-				xive_cpu_err(me, "target=???\n");
-				/* Find XIVE on which the IVE resides */
-			x = xive_from_isn(irq);
-			if (!x) {
-				xive_cpu_err(me, "no xive attached\n");
-				return true;
-			}
-			ive = xive_get_ive(x, irq);
-			if (!ive) {
-				xive_cpu_err(me, "no ive attached\n");
-				return true;
-			}
-			xive_cpu_err(me, "ive=%016llx\n", ive->w);
-			for_each_chip(chip) {
-				x = chip->xive;
-				if (!x)
-					continue;
-				ive = x->ivt_base;
-				for (i = 0; i < MAX_INT_ENTRIES; i++) {
-					if ((ive[i].w & IVE_EQ_DATA) == irq) {
-						eq_blk = GETFIELD(IVE_EQ_BLOCK, ive[i].w);
-						eq_idx = GETFIELD(IVE_EQ_INDEX, ive[i].w);
-						xive_cpu_err(me, "Found source: 0x%x ive=%016llx\n"
-							     " eq 0x%x/%x",
-							     BLKIDX_TO_GIRQ(x->block_id, i),
-							     ive[i].w, eq_blk, eq_idx);
-						xive_dump_eq(eq_blk, eq_idx);
-					}
-				}
-			}
-			return true;
-		}
-	}
-	return false;
-}
-#else
-static inline bool check_misrouted_ipi(struct cpu_thread  *c __unused,
-				       uint32_t irq __unused)
-{
-	return false;
-}
-#endif
-
-static int64_t opal_xive_get_xirr(uint32_t *out_xirr, bool just_poll)
-{
-	struct cpu_thread *c = this_cpu();
-	struct xive_cpu_state *xs = c->xstate;
-	uint16_t ack;
-	uint8_t active, old_cppr;
-
-	if (xive_mode != XIVE_MODE_EMU)
-		return OPAL_WRONG_STATE;
-	if (!xs)
-		return OPAL_INTERNAL_ERROR;
-	if (!out_xirr)
-		return OPAL_PARAMETER;
-
-	*out_xirr = 0;
-
-	lock(&xs->lock);
-
-	/*
-	 * Due to the need to fetch multiple interrupts from the EQ, we
-	 * need to play some tricks.
-	 *
-	 * The "pending" byte in "xs" keeps track of the priorities that
-	 * are known to have stuff to read (currently we only use one).
-	 *
-	 * It is set in EOI and cleared when consumed here. We don't bother
-	 * looking ahead here, EOI will do it.
-	 *
-	 * We do need to still do an ACK every time in case a higher prio
-	 * exception occurred (though we don't do prio yet... right ? still
-	 * let's get the basic design right !).
-	 *
-	 * Note that if we haven't found anything via ack, but did find
-	 * something in the queue, we must also raise CPPR back.
-	 */
-
-	xive_cpu_vdbg(c, "get_xirr W01=%016llx W2=%08x\n",
-		      __in_be64(xs->tm_ring1 + TM_QW3_HV_PHYS),
-		      __in_be32(xs->tm_ring1 + TM_QW3_HV_PHYS + 8));
-
-	/* Perform the HV Ack cycle */
-	if (just_poll)
-		ack = __in_be64(xs->tm_ring1 + TM_QW3_HV_PHYS) >> 48;
-	else
-		ack = __in_be16(xs->tm_ring1 + TM_SPC_ACK_HV_REG);
-	sync();
-	xive_cpu_vdbg(c, "get_xirr,%s=%04x\n", just_poll ? "POLL" : "ACK", ack);
-
-	/* Capture the old CPPR which we will return with the interrupt */
-	old_cppr = xs->cppr;
-
-	switch(GETFIELD(TM_QW3_NSR_HE, (ack >> 8))) {
-	case TM_QW3_NSR_HE_NONE:
-		break;
-	case TM_QW3_NSR_HE_POOL:
-		break;
-	case TM_QW3_NSR_HE_PHYS:
-		/* Mark pending and keep track of the CPPR update */
-		if (!just_poll && (ack & 0xff) != 0xff) {
-			xs->cppr = ack & 0xff;
-			xs->pending |= 1 << xs->cppr;
-		}
-		break;
-	case TM_QW3_NSR_HE_LSI:
-		break;
-	}
-
-	/* Calculate "active" lines as being the pending interrupts
-	 * masked by the "old" CPPR
-	 */
-	active = opal_xive_check_pending(xs, old_cppr);
-
-	log_add(xs, LOG_TYPE_XIRR, 6, old_cppr, xs->cppr, xs->pending, active,
-		xs->eqptr, xs->eqgen);
-
-#ifdef XIVE_PERCPU_LOG
-	{
-		struct xive_eq *eq;
-		lock(&xs->xive->lock);
-		__xive_cache_scrub(xs->xive, xive_cache_eqc, xs->eq_blk,
-				   xs->eq_idx + XIVE_EMULATION_PRIO,
-				   false, false);
-		unlock(&xs->xive->lock);
-		eq = xive_get_eq(xs->xive, xs->eq_idx + XIVE_EMULATION_PRIO);
-		log_add(xs, LOG_TYPE_EQD, 2, eq->w0, eq->w1);
-	}
-#endif /* XIVE_PERCPU_LOG */
-
-	xive_cpu_vdbg(c, "  cppr=%d->%d pending=0x%x active=%x\n",
-		      old_cppr, xs->cppr, xs->pending, active);
-	if (active) {
-		/* Find highest pending */
-		uint8_t prio = ffs(active) - 1;
-		uint32_t val;
-
-		/* XXX Use "p" to select queue */
-		val = xive_read_eq(xs, just_poll);
-
-		if (val && val < XIVE_INT_FIRST)
-			xive_cpu_err(c, "Bogus interrupt 0x%x received !\n", val);
-
-		/* Convert to magic IPI if needed */
-		if (val == xs->ipi_irq)
-			val = 2;
-		if (check_misrouted_ipi(c, val))
-			val = 2;
-
-		*out_xirr = (old_cppr << 24) | val;
-
-		/* If we are polling, that's it */
-		if (just_poll)
-			goto skip;
-
-		/* Clear the pending bit. EOI will set it again if needed. We
-		 * could check the queue but that's not really critical here.
-		 */
-		xs->pending &= ~(1 << prio);
-
-		/* Spurrious IPB bit, nothing to fetch, bring CPPR back */
-		if (!val)
-			prio = old_cppr;
-
-		/* We could have fetched a pending interrupt left over
-		 * by a previous EOI, so the CPPR might need adjusting
-		 * Also if we had a spurrious one as well.
-		 */
-		if (xs->cppr != prio) {
-			xs->cppr = prio;
-			out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, prio);
-			xive_cpu_vdbg(c, "  adjusted CPPR to %d\n", prio);
-		}
-
-		if (val)
-			xive_cpu_vdbg(c, "  found irq, prio=%d\n", prio);
-
-	} else {
-		/* Nothing was active, this is a fluke, restore CPPR */
-		opal_xive_update_cppr(xs, old_cppr);
-		xive_cpu_vdbg(c, "  nothing active, restored CPPR to %d\n",
-			      old_cppr);
-	}
- skip:
-
-	log_add(xs, LOG_TYPE_XIRR2, 5, xs->cppr, xs->pending,
-		*out_xirr, xs->eqptr, xs->eqgen);
-	xive_cpu_vdbg(c, "  returning XIRR=%08x, pending=0x%x\n",
-		      *out_xirr, xs->pending);
-
-	unlock(&xs->lock);
-
-	return OPAL_SUCCESS;
-}
-
-static int64_t opal_xive_set_cppr(uint8_t cppr)
-{
-	struct cpu_thread *c = this_cpu();
-	struct xive_cpu_state *xs = c->xstate;
-
-	if (xive_mode != XIVE_MODE_EMU)
-		return OPAL_WRONG_STATE;
-
-	/* Limit supported CPPR values */
-	cppr = xive_sanitize_cppr(cppr);
-
-	if (!xs)
-		return OPAL_INTERNAL_ERROR;
-	xive_cpu_vdbg(c, "CPPR setting to %d\n", cppr);
-
-	lock(&xs->lock);
-	opal_xive_update_cppr(xs, cppr);
-	unlock(&xs->lock);
-
-	return OPAL_SUCCESS;
-}
-
-static int64_t opal_xive_set_mfrr(uint32_t cpu, uint8_t mfrr)
-{
-	struct cpu_thread *c = find_cpu_by_server(cpu);
-	struct xive_cpu_state *xs;
-	uint8_t old_mfrr;
-
-	if (xive_mode != XIVE_MODE_EMU)
-		return OPAL_WRONG_STATE;
-	if (!c)
-		return OPAL_PARAMETER;
-	xs = c->xstate;
-	if (!xs)
-		return OPAL_INTERNAL_ERROR;
-
-	lock(&xs->lock);
-	old_mfrr = xs->mfrr;
-	xive_cpu_vdbg(c, "  Setting MFRR to %x, old is %x\n", mfrr, old_mfrr);
-	xs->mfrr = mfrr;
-	if (old_mfrr > mfrr && mfrr < xs->cppr)
-		xive_ipi_trigger(xs->xive, GIRQ_TO_IDX(xs->ipi_irq));
-	unlock(&xs->lock);
-
-	return OPAL_SUCCESS;
 }
 
 static uint64_t xive_convert_irq_flags(uint64_t iflags)
@@ -4474,17 +3641,14 @@ static void xive_reset_one(struct xive *x)
 	/* The rest must not be called with the lock held */
 	unlock(&x->lock);
 
-	/* Re-configure VPs and emulation */
+	/* Re-configure VPs */
 	for_each_present_cpu(c) {
 		struct xive_cpu_state *xs = c->xstate;
 
 		if (c->chip_id != x->chip_id || !xs)
 			continue;
 
-		if (xive_mode == XIVE_MODE_EMU)
-			xive_init_cpu_emulation(xs, c);
-		else
-			xive_init_cpu_exploitation(xs);
+		xive_init_cpu_exploitation(xs);
 	}
 }
 
@@ -4521,7 +3685,6 @@ static void xive_p9_cpu_reset(void)
 	struct cpu_thread *c = this_cpu();
 	struct xive_cpu_state *xs = c->xstate;
 
-	xs->cppr = 0;
 	out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_CPPR, 0);
 
 	in_be64(xs->tm_ring1 + TM_SPC_PULL_POOL_CTX);
@@ -4568,7 +3731,7 @@ static int64_t xive_p9_reset(void)
 {
 	if (xive_mode == XIVE_MODE_NONE)
 		return OPAL_SUCCESS;
-	return __xive_reset(XIVE_MODE_EMU);
+	return __xive_reset(XIVE_MODE_EXPL);
 }
 
 static int64_t opal_xive_reset(uint64_t version)
@@ -4941,71 +4104,6 @@ static int64_t opal_xive_dump_vp(uint32_t vp_id)
 	return OPAL_SUCCESS;
 }
 
-static int64_t __opal_xive_dump_emu(struct xive_cpu_state *xs, uint32_t pir)
-{
-	struct xive_eq *eq;
-	uint32_t ipi_target;
-	uint8_t *mm, pq;
-
-	prlog(PR_INFO, "CPU[%04x]: XIVE emulation state\n", pir);
-
-	prlog(PR_INFO, "CPU[%04x]: cppr=%02x mfrr=%02x pend=%02x"
-	      " prev_cppr=%02x total_irqs=%llx\n", pir,
-	      xs->cppr, xs->mfrr, xs->pending, xs->prev_cppr, xs->total_irqs);
-
-	prlog(PR_INFO, "CPU[%04x]: EQ IDX=%x MSK=%x G=%d [%08x %08x %08x > %08x %08x %08x %08x ...]\n",
-	      pir,  xs->eqptr, xs->eqmsk, xs->eqgen,
-	      xs->eqbuf[(xs->eqptr - 3) & xs->eqmsk],
-	      xs->eqbuf[(xs->eqptr - 2) & xs->eqmsk],
-	      xs->eqbuf[(xs->eqptr - 1) & xs->eqmsk],
-	      xs->eqbuf[(xs->eqptr + 0) & xs->eqmsk],
-	      xs->eqbuf[(xs->eqptr + 1) & xs->eqmsk],
-	      xs->eqbuf[(xs->eqptr + 2) & xs->eqmsk],
-	      xs->eqbuf[(xs->eqptr + 3) & xs->eqmsk]);
-
-	mm = xs->xive->esb_mmio + GIRQ_TO_IDX(xs->ipi_irq) * 0x20000;
-	pq = in_8(mm + 0x10800);
-	if (xive_get_irq_targetting(xs->ipi_irq, &ipi_target, NULL, NULL))
-		prlog(PR_INFO, "CPU[%04x]: IPI #%08x PQ=%x target=%08x\n",
-				pir, xs->ipi_irq, pq, ipi_target);
-	else
-		prlog(PR_INFO, "CPU[%04x]: IPI #%08x PQ=%x target=??\n",
-				pir, xs->ipi_irq, pq);
-
-
-
-	__xive_cache_scrub(xs->xive, xive_cache_eqc, xs->eq_blk,
-			   xs->eq_idx + XIVE_EMULATION_PRIO,
-			   false, false);
-	eq = xive_get_eq(xs->xive, xs->eq_idx + XIVE_EMULATION_PRIO);
-	prlog(PR_INFO, "CPU[%04x]: EQ @%p W0=%08x W1=%08x qbuf @%p\n",
-	      pir, eq, eq->w0, eq->w1, xs->eqbuf);
-
-	return OPAL_SUCCESS;
-}
-
-static int64_t opal_xive_dump_emu(uint32_t pir)
-{
-	struct cpu_thread *c = find_cpu_by_pir(pir);
-	struct xive_cpu_state *xs;
-	int64_t rc;
-
-	if (!c)
-		return OPAL_PARAMETER;
-
-	xs = c->xstate;
-	if (!xs) {
-		prlog(PR_INFO, "  <none>\n");
-		return OPAL_SUCCESS;
-	}
-	lock(&xs->lock);
-	rc = __opal_xive_dump_emu(xs, pir);
-	log_print(xs);
-	unlock(&xs->lock);
-
-	return rc;
-}
-
 static int64_t opal_xive_sync_irq_src(uint32_t girq)
 {
 	struct xive *x = xive_from_isn(girq);
@@ -5061,8 +4159,6 @@ static int64_t opal_xive_dump(uint32_t type, uint32_t id)
 		return opal_xive_dump_tm(TM_QW0_USER, "USER", id);
 	case XIVE_DUMP_VP:
 		return opal_xive_dump_vp(id);
-	case XIVE_DUMP_EMU_STATE:
-		return opal_xive_dump_emu(id);
 	default:
 		return OPAL_PARAMETER;
 	}
@@ -5101,7 +4197,7 @@ static void xive_p9_init(const char *compat)
 	if (first)
 		return;
 
-	xive_mode = XIVE_MODE_EMU;
+	xive_mode = XIVE_MODE_EXPL;
 
 	/* Init VP allocator */
 	xive_init_vp_allocator();
@@ -5117,25 +4213,14 @@ static void xive_p9_init(const char *compat)
 			late_init_one_xive(chip->xive);
 	}
 
-	/* Initialize XICS emulation per-cpu structures */
+	/* Initialize per-cpu structures */
 	for_each_present_cpu(cpu) {
 		xive_init_cpu(cpu);
 	}
-	/* Add interrupts propertie to each CPU node */
-	for_each_present_cpu(cpu) {
-		if (cpu_is_thread0(cpu))
-			xive_init_cpu_properties(cpu);
-	}
 
 	/* Calling boot CPU */
 	xive_cpu_callin(this_cpu());
 
-	/* Register XICS emulation calls */
-	opal_register(OPAL_INT_GET_XIRR, opal_xive_get_xirr, 2);
-	opal_register(OPAL_INT_SET_CPPR, opal_xive_set_cppr, 1);
-	opal_register(OPAL_INT_EOI, opal_xive_eoi, 1);
-	opal_register(OPAL_INT_SET_MFRR, opal_xive_set_mfrr, 2);
-
 	/* Register XIVE exploitation calls */
 	opal_register(OPAL_XIVE_RESET, opal_xive_reset, 1);
 	opal_register(OPAL_XIVE_GET_IRQ_INFO, opal_xive_get_irq_info, 6);
-- 
2.21.0



More information about the Skiboot mailing list