From 832e6ede23587bc3cad0250821e86e4999165113 Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 31 Jan 2020 11:33:11 +0000 Subject: [PATCH] Call the MAPTI command earlier in the ITS driver The GICv3 Software Overview suggests when allocating a new MSI/MSI-X interrupt we need to call MAPD followed by MAPTI. Unfortunately the code would place a MOVI command between these. This is invalid as it needs values set by the MAPTI to be present. Re-order so we allocate a temporary CPU for the interrupt, then use the MAPTI command to assign the MSI to it. MFC after: 2 weeks Sponsored by: DARPA, AFRL --- sys/arm64/arm64/gicv3_its.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/sys/arm64/arm64/gicv3_its.c b/sys/arm64/arm64/gicv3_its.c index dcc0fdf160a7..4fa471c14120 100644 --- a/sys/arm64/arm64/gicv3_its.c +++ b/sys/arm64/arm64/gicv3_its.c @@ -928,21 +928,29 @@ gicv3_its_post_filter(device_t dev, struct intr_irqsrc *isrc) } static int -gicv3_its_bind_intr(device_t dev, struct intr_irqsrc *isrc) +gicv3_its_select_cpu(device_t dev, struct intr_irqsrc *isrc) { - struct gicv3_its_irqsrc *girq; struct gicv3_its_softc *sc; sc = device_get_softc(dev); - girq = (struct gicv3_its_irqsrc *)isrc; if (CPU_EMPTY(&isrc->isrc_cpu)) { sc->gic_irq_cpu = intr_irq_next_cpu(sc->gic_irq_cpu, &sc->sc_cpus); CPU_SETOF(sc->gic_irq_cpu, &isrc->isrc_cpu); } - its_cmd_movi(dev, girq); + return (0); +} +static int +gicv3_its_bind_intr(device_t dev, struct intr_irqsrc *isrc) +{ + struct gicv3_its_irqsrc *girq; + + gicv3_its_select_cpu(dev, isrc); + + girq = (struct gicv3_its_irqsrc *)isrc; + its_cmd_movi(dev, girq); return (0); } @@ -1129,6 +1137,10 @@ gicv3_its_alloc_msi(device_t dev, device_t child, int count, int maxcount, girq = &sc->sc_irqs[irq]; girq->gi_its_dev = its_dev; srcs[i] = (struct intr_irqsrc *)girq; + + /* Map the message to the given IRQ */ + gicv3_its_select_cpu(dev, (struct intr_irqsrc *)girq); + its_cmd_mapti(dev, girq); } its_dev->lpis.lpi_busy += count; *pic = dev; @@ -1189,6 +1201,10 @@ gicv3_its_alloc_msix(device_t dev, device_t child, device_t *pic, girq = &sc->sc_irqs[irq]; girq->gi_its_dev = its_dev; + /* Map the message to the given IRQ */ + gicv3_its_select_cpu(dev, (struct intr_irqsrc *)girq); + its_cmd_mapti(dev, girq); + *pic = dev; *isrcp = (struct intr_irqsrc *)girq; @@ -1229,9 +1245,6 @@ gicv3_its_map_msi(device_t dev, device_t child, struct intr_irqsrc *isrc, sc = device_get_softc(dev); girq = (struct gicv3_its_irqsrc *)isrc; - /* Map the message to the given IRQ */ - its_cmd_mapti(dev, girq); - *addr = vtophys(rman_get_virtual(sc->sc_its_res)) + GITS_TRANSLATER; *data = girq->gi_irq - girq->gi_its_dev->lpis.lpi_base;