From patchwork Thu Mar 9 00:45:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Herrenschmidt X-Patchwork-Id: 736798 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vdsJ34pQBz9s8B for ; Thu, 9 Mar 2017 11:50:27 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3vdsJ343MwzDqZb for ; Thu, 9 Mar 2017 11:50:27 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org 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 3vdsHN5bZGzDqYR for ; Thu, 9 Mar 2017 11:49:52 +1100 (AEDT) Received: from pasglop.ozlabs.ibm.com (localhost.localdomain [127.0.0.1]) by gate.crashing.org (8.14.1/8.13.8) with ESMTP id v290k2Dg026078; Wed, 8 Mar 2017 18:46:08 -0600 From: Benjamin Herrenschmidt To: skiboot@lists.ozlabs.org Date: Thu, 9 Mar 2017 11:45:37 +1100 Message-Id: <20170309004543.16745-4-benh@kernel.crashing.org> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170309004543.16745-1-benh@kernel.crashing.org> References: <20170309004543.16745-1-benh@kernel.crashing.org> Subject: [Skiboot] [PATCH 04/10] xive: Sync HW when moving interrupts around 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" For now sync all queues, ensure any interrupt routed at the old queue has reached memory. Signed-off-by: Benjamin Herrenschmidt --- hw/xive.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- include/xive.h | 7 ++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/hw/xive.c b/hw/xive.c index d18bc46..8cc0aa1 100644 --- a/hw/xive.c +++ b/hw/xive.c @@ -2325,11 +2325,52 @@ static void xive_update_irq_mask(struct xive_src *s, uint32_t idx, bool masked) in_be64(mmio_base + offset); } +static void xive_sync(struct xive *x) +{ + uint64_t r; + void *p; + + lock(&x->lock); + + /* Second 2K range of second page */ + p = x->ic_base + (1 << x->ic_shift) + 0x800; + + /* TODO: Make this more fine grained */ + out_be64(p + (10 << 7), 0); /* Sync OS escalations */ + out_be64(p + (11 << 7), 0); /* Sync Hyp escalations */ + out_be64(p + (12 << 7), 0); /* Sync Redistribution */ + out_be64(p + ( 8 << 7), 0); /* Sync IPI */ + out_be64(p + ( 9 << 7), 0); /* Sync HW */ + +#define SYNC_MASK \ + (VC_EQC_CONF_SYNC_IPI | \ + VC_EQC_CONF_SYNC_HW | \ + VC_EQC_CONF_SYNC_ESC1 | \ + VC_EQC_CONF_SYNC_ESC2 | \ + VC_EQC_CONF_SYNC_REDI) + + /* XXX Add timeout */ + for (;;) { + r = xive_regrx(x, VC_EQC_CONFIG); + if ((r & SYNC_MASK) == SYNC_MASK) + break; + cpu_relax(); + } + xive_regw(x, VC_EQC_CONFIG, r & ~SYNC_MASK); + + /* Workaround HW issue, read back before allowing a new sync */ + xive_regr(x, VC_GLOBAL_CONFIG); + + unlock(&x->lock); +} + static int64_t xive_source_set_xive(struct irq_source *is, uint32_t isn, uint16_t server, uint8_t prio) { struct xive_src *s = container_of(is, struct xive_src, is); uint8_t old_prio; + uint32_t old_target; + uint32_t vp_blk; int64_t rc; /* @@ -2351,7 +2392,7 @@ static int64_t xive_source_set_xive(struct irq_source *is, uint32_t isn, server >>= 2; /* Grab existing prio/mask */ - if (!xive_get_irq_targetting(isn, NULL, &old_prio, NULL)) + if (!xive_get_irq_targetting(isn, &old_target, &old_prio, NULL)) return OPAL_PARAMETER; /* Let XIVE configure the EQ synchronously */ @@ -2368,6 +2409,21 @@ static int64_t xive_source_set_xive(struct irq_source *is, uint32_t isn, xive_update_irq_mask(s, isn - s->esb_base, prio == 0xff); } + + /* + * Synchronize the source and old target XIVEs to ensure that + * all pending interrupts to the old target have reached their + * respective queue. + * + * WARNING: This assumes the VP and it's queues are on the same + * XIVE instance ! + */ + xive_sync(s->xive); + if (xive_decode_vp(old_target, &vp_blk, NULL, NULL, NULL)) { + struct xive *x = xive_from_pc_blk(vp_blk); + if (x) + xive_sync(x); + } return OPAL_SUCCESS; } @@ -3334,6 +3390,7 @@ static int64_t opal_xive_set_irq_config(uint32_t girq, { struct irq_source *is = irq_find_source(girq); struct xive_src *s = container_of(is, struct xive_src, is); + uint32_t old_target, vp_blk; int64_t rc; /* @@ -3343,6 +3400,10 @@ static int64_t opal_xive_set_irq_config(uint32_t girq, if (xive_mode != XIVE_MODE_EXPL) return OPAL_WRONG_STATE; + /* Grab existing target */ + if (!xive_get_irq_targetting(girq, &old_target, NULL, NULL)) + return OPAL_PARAMETER; + /* Let XIVE configure the EQ. We do the update without the * synchronous flag, thus a cache update failure will result * in us returning OPAL_BUSY @@ -3358,6 +3419,21 @@ static int64_t opal_xive_set_irq_config(uint32_t girq, /* Ensure it's enabled/disabled in the source controller */ xive_update_irq_mask(s, girq - s->esb_base, prio == 0xff); + /* + * Synchronize the source and old target XIVEs to ensure that + * all pending interrupts to the old target have reached their + * respective queue. + * + * WARNING: This assumes the VP and it's queues are on the same + * XIVE instance ! + */ + xive_sync(s->xive); + if (xive_decode_vp(old_target, &vp_blk, NULL, NULL, NULL)) { + struct xive *x = xive_from_pc_blk(vp_blk); + if (x) + xive_sync(x); + } + return OPAL_SUCCESS; } diff --git a/include/xive.h b/include/xive.h index 58c4da9..06aad8b 100644 --- a/include/xive.h +++ b/include/xive.h @@ -180,6 +180,13 @@ #define X_VC_EQC_SCRUB_MASK 0x213 #define VC_EQC_SCRUB_MASK 0x918 #define X_VC_EQC_CWATCH_SPEC 0x215 +#define VC_EQC_CONFIG 0x920 +#define X_VC_EQC_CONFIG 0x214 +#define VC_EQC_CONF_SYNC_IPI PPC_BIT(32) +#define VC_EQC_CONF_SYNC_HW PPC_BIT(33) +#define VC_EQC_CONF_SYNC_ESC1 PPC_BIT(34) +#define VC_EQC_CONF_SYNC_ESC2 PPC_BIT(35) +#define VC_EQC_CONF_SYNC_REDI PPC_BIT(36) #define VC_EQC_CWATCH_SPEC 0x928 #define VC_EQC_CWATCH_CONFLICT PPC_BIT(0) #define VC_EQC_CWATCH_FULL PPC_BIT(8)