[Skiboot] [PATCH 2/2] xive: Fixes/improvements to xive reset for multi-chip systems
Michael Neuling
mikey at neuling.org
Wed Apr 19 15:09:53 AEST 2017
These two are now upstream as of 7184ed2d281aefb010109068bb7d2b91b30047c7
On Fri, 2017-04-07 at 16:01 +1000, Benjamin Herrenschmidt wrote:
> On such systems, we really need to mask all the sources first,
> then synchronize all the XIVEs, before we start whacking their
> EQs, VPs etc...
>
> So this reworks the reset sequence to do that, using the new
> irq_for_each_source() iterator to get all the registered sources
> into a clean off state, and separating the sync pass from the
> reset pass.
>
> This also fixes a problem where the ipi_alloc_map wasn't being
> properly reset.
>
> Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
> ---
> hw/xive.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
> ---
> 1 file changed, 75 insertions(+), 19 deletions(-)
>
> diff --git a/hw/xive.c b/hw/xive.c
> index 9713e8f..8b83f96 100644
> --- a/hw/xive.c
> +++ b/hw/xive.c
> @@ -2373,7 +2373,7 @@ static int64_t xive_sync(struct xive *x)
>
> static int64_t __xive_set_irq_config(struct irq_source *is, uint32_t girq,
> uint64_t vp, uint8_t prio, uint32_t
> lirq,
> - bool update_esb)
> + bool update_esb, bool no_sync)
> {
> struct xive_src *s = container_of(is, struct xive_src, is);
> uint32_t old_target, vp_blk;
> @@ -2417,6 +2417,8 @@ static int64_t __xive_set_irq_config(struct irq_source
> *is, uint32_t girq,
> * WARNING: This assumes the VP and it's queues are on the same
> * XIVE instance !
> */
> + if (no_sync)
> + return OPAL_SUCCESS;
> xive_sync(s->xive);
> if (xive_decode_vp(old_target, &vp_blk, NULL, NULL, NULL)) {
> struct xive *x = xive_from_pc_blk(vp_blk);
> @@ -2432,10 +2434,11 @@ static int64_t xive_set_irq_config(uint32_t girq,
> uint64_t vp, uint8_t prio,
> {
> struct irq_source *is = irq_find_source(girq);
>
> - return __xive_set_irq_config(is, girq, vp, prio, lirq, update_esb);
> + return __xive_set_irq_config(is, girq, vp, prio, lirq, update_esb,
> + false);
> }
>
> -static int64_t xive_source_set_xive(struct irq_source *is __unused,
> +static int64_t xive_source_set_xive(struct irq_source *is,
> uint32_t isn, uint16_t server, uint8_t
> prio)
> {
> /*
> @@ -2457,7 +2460,7 @@ static int64_t xive_source_set_xive(struct irq_source
> *is __unused,
> server >>= 2;
>
> /* Set logical irq to match isn */
> - return xive_set_irq_config(isn, server, prio, isn, true);
> + return __xive_set_irq_config(is, isn, server, prio, isn, true,
> false);
> }
>
> void __xive_source_eoi(struct irq_source *is, uint32_t isn)
> @@ -2740,7 +2743,8 @@ static void xive_ipi_init(struct xive *x, struct
> cpu_thread *cpu)
> assert(xs);
>
> __xive_set_irq_config(&x->ipis.is, xs->ipi_irq, cpu->pir,
> - XIVE_EMULATION_PRIO, xs->ipi_irq, true);
> + XIVE_EMULATION_PRIO, xs->ipi_irq,
> + true, false);
> }
>
> static void xive_ipi_eoi(struct xive *x, uint32_t idx)
> @@ -2809,7 +2813,9 @@ void xive_cpu_callin(struct cpu_thread *cpu)
> /* Set VT to 1 */
> out_8(xs->tm_ring1 + TM_QW3_HV_PHYS + TM_WORD2, 0x80);
>
> - xive_cpu_dbg(cpu, "Initialized interrupt management area\n");
> + xive_cpu_dbg(cpu, "Initialized TMA (VP: %x/%x W01=%016llx)\n",
> + xs->vp_blk, xs->vp_idx,
> + in_be64(xs->tm_ring1 + TM_QW3_HV_PHYS));
> }
>
> static void xive_setup_hw_for_emu(struct xive_cpu_state *xs)
> @@ -3741,7 +3747,7 @@ static int64_t opal_xive_set_vp_info(uint64_t vp_id,
> return OPAL_SUCCESS;
> }
>
> -static void xive_cleanup_cpu_cam(struct cpu_thread *c)
> +static void xive_cleanup_cpu_tma(struct cpu_thread *c)
> {
> struct xive_cpu_state *xs = c->xstate;
> struct xive *x = xs->xive;
> @@ -3760,6 +3766,11 @@ static void xive_cleanup_cpu_cam(struct cpu_thread *c)
> /* Set HV CPPR to 0 */
> out_8(ind_tm_base + TM_QW3_HV_PHYS + TM_CPPR, 0);
>
> + /* Dump HV state */
> + xive_cpu_dbg(c, "[reset] VP %x/%x W01 state: %016llx\n",
> + xs->vp_blk, xs->vp_idx,
> + in_be64(ind_tm_base + TM_QW3_HV_PHYS));
> +
> /* Reset indirect access */
> xive_regw(x, PC_TCTXT_INDIR0, 0);
> }
> @@ -3768,19 +3779,24 @@ static void xive_reset_one(struct xive *x)
> {
> struct cpu_thread *c;
> bool eq_firmware;
> - int i = 0;
> + int i;
>
> - /* Mask all interrupt sources */
> - while ((i = bitmap_find_one_bit(*x->int_enabled_map,
> - i, MAX_INT_ENTRIES - i)) >= 0) {
> - xive_set_irq_config(x->int_base + i, 0, 0xff,
> - x->int_base + i, true);
> - i++;
> - }
> - xive_sync(x);
> + xive_dbg(x, "Resetting one xive...\n");
>
> lock(&x->lock);
> - memset(x->int_enabled_map, 0, BITMAP_BYTES(MAX_INT_ENTRIES));
> +
> + /* Check all interrupts are disabled */
> + i = bitmap_find_one_bit(*x->int_enabled_map, 0, MAX_INT_ENTRIES);
> + if (i >= 0)
> + xive_warn(x, "Interrupt %d (and maybe more) not disabled"
> + " at reset !\n", i);
> +
> + /* Reset IPI allocation */
> + xive_dbg(x, "freeing alloc map %p/%p\n",
> + x->ipi_alloc_map, *x->ipi_alloc_map);
> + memset(x->ipi_alloc_map, 0, BITMAP_BYTES(MAX_INT_ENTRIES));
> +
> + xive_dbg(x, "Resetting EQs...\n");
>
> /* Reset all allocated EQs and free the user ones */
> bitmap_for_each_one(*x->eq_map, MAX_EQ_COUNT >> 3, i) {
> @@ -3819,7 +3835,7 @@ static void xive_reset_one(struct xive *x)
> continue;
> if (!c->xstate)
> continue;
> - xive_cleanup_cpu_cam(c);
> + xive_cleanup_cpu_tma(c);
> }
>
> /* Reset all user-allocated VPs. This is inefficient, we should
> @@ -3873,16 +3889,56 @@ static void xive_reset_one(struct xive *x)
> }
> }
>
> +static void xive_reset_mask_source_cb(struct irq_source *is,
> + void *data __unused)
> +{
> + struct xive_src *s = container_of(is, struct xive_src, is);
> + struct xive *x;
> + uint32_t isn;
> +
> + if (is->ops != &xive_irq_source_ops)
> + return;
> +
> + /* Skip escalation sources */
> + if (GIRQ_IS_ESCALATION(is->start))
> + return;
> +
> + x = s->xive;
> +
> + /* Iterate all interrupts */
> + for (isn = is->start; isn < is->end; isn++) {
> + /* Has it ever been enabled ? */
> + if (!bitmap_tst_bit(*x->int_enabled_map, GIRQ_TO_IDX(isn)))
> + continue;
> + /* Mask it and clear the enabled map bit */
> + xive_dbg(x, "[reset] disabling source 0x%x\n", isn);
> + __xive_set_irq_config(is, isn, 0, 0xff, isn, true, true);
> + bitmap_clr_bit(*x->int_enabled_map, GIRQ_TO_IDX(isn));
> + }
> +}
> +
> static int64_t opal_xive_reset(uint64_t version)
> {
> struct proc_chip *chip;
>
> + prlog(PR_DEBUG, "XIVE reset, version: %d...\n", (int)version);
> +
> if (version > 1)
> return OPAL_PARAMETER;
>
> xive_mode = version;
>
> - /* For each XIVE ... */
> + /* Mask all interrupt sources */
> + irq_for_each_source(xive_reset_mask_source_cb, NULL);
> +
> + /* For each XIVE do a sync... */
> + for_each_chip(chip) {
> + if (!chip->xive)
> + continue;
> + xive_sync(chip->xive);
> + }
> +
> + /* For each XIVE reset everything else... */
> for_each_chip(chip) {
> if (!chip->xive)
> continue;
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list