From patchwork Sun Sep 10 07:33:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Herrenschmidt X-Patchwork-Id: 812057 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xqjXs25MQz9s8J for ; Sun, 10 Sep 2017 17:36:13 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3xqjXs0pLmzDrnY for ; Sun, 10 Sep 2017 17:36:13 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=permerror (mailfrom) smtp.mailfrom=kernel.crashing.org (client-ip=63.228.1.57; helo=gate.crashing.org; envelope-from=benh@kernel.crashing.org; receiver=) Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3xqjVY1lbrzDrd3 for ; Sun, 10 Sep 2017 17:34:12 +1000 (AEST) Received: from pasglop.au.ibm.com (localhost.localdomain [127.0.0.1]) by gate.crashing.org (8.14.1/8.13.8) with ESMTP id v8A7XVar032370; Sun, 10 Sep 2017 02:33:52 -0500 From: Benjamin Herrenschmidt To: skiboot@lists.ozlabs.org Date: Sun, 10 Sep 2017 17:33:27 +1000 Message-Id: <20170910073330.25824-11-benh@kernel.crashing.org> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170910073330.25824-1-benh@kernel.crashing.org> References: <20170910073330.25824-1-benh@kernel.crashing.org> Subject: [Skiboot] [PATCH v2 11/14] xive: Add debug option for detecting misrouted IPI in emulation X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This is high overhead so we don't enable it by default even in debug builds, it's also a bit messy, but it allowed me to detect and debug a locking issue earlier so it can be useful. Signed-off-by: Benjamin Herrenschmidt --- hw/xive.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 122 insertions(+), 15 deletions(-) diff --git a/hw/xive.c b/hw/xive.c index 0d3b24fd..ea81b2b3 100644 --- a/hw/xive.c +++ b/hw/xive.c @@ -45,6 +45,7 @@ #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 #define XIVE_INT_SAFETY_GAP 0x1000 #else @@ -52,6 +53,7 @@ #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 #define XIVE_INT_SAFETY_GAP 0x10 #endif @@ -3444,6 +3446,103 @@ static int64_t opal_xive_eoi(uint32_t xirr) 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 void checkstop(void) +{ + xscom_writeme(0x05011c02, PPC_BIT(0)); + for (;;) ; +} + +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); + checkstop(); + 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(); @@ -3548,6 +3647,8 @@ static int64_t opal_xive_get_xirr(uint32_t *out_xirr, bool just_poll) /* 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; @@ -4668,26 +4769,14 @@ static int64_t opal_xive_dump_vp(uint32_t vp_id) return OPAL_SUCCESS; } -static int64_t opal_xive_dump_emu(uint32_t pir) +static int64_t __opal_xive_dump_emu(struct xive_cpu_state *xs, uint32_t pir) { - struct cpu_thread *c = find_cpu_by_pir(pir); - struct xive_cpu_state *xs; struct xive_eq *eq; uint32_t ipi_target; uint8_t *mm, pq; - if (!c) - return OPAL_PARAMETER; - prlog(PR_INFO, "CPU[%04x]: XIVE emulation state\n", pir); - xs = c->xstate; - if (!xs) { - prlog(PR_INFO, " \n"); - return OPAL_SUCCESS; - } - lock(&xs->lock); - 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); @@ -4720,11 +4809,29 @@ static int64_t opal_xive_dump_emu(uint32_t pir) prlog(PR_INFO, "CPU[%04x]: EQ @%p W0=%08x W1=%08x qbuf @%p\n", pir, eq, eq->w0, eq->w1, xs->eqbuf); - log_print(xs); + 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, " \n"); + return OPAL_SUCCESS; + } + lock(&xs->lock); + rc = __opal_xive_dump_emu(xs, pir); + log_print(xs); unlock(&xs->lock); - return OPAL_SUCCESS; + return rc; } static int64_t opal_xive_sync_irq_src(uint32_t girq)