Index: sys/arm64/arm64/gic_v3.c =================================================================== --- sys/arm64/arm64/gic_v3.c +++ sys/arm64/arm64/gic_v3.c @@ -154,7 +154,8 @@ /* Helper routines starting with gic_v3_ */ static int gic_v3_dist_init(struct gic_v3_softc *); static int gic_v3_redist_alloc(struct gic_v3_softc *); -static int gic_v3_redist_find(struct gic_v3_softc *); +static int gic_v3_redist_find_all(struct gic_v3_softc *); +static int gic_v3_redist_find(struct gic_v3_softc *, u_int cpuid); static int gic_v3_redist_init(struct gic_v3_softc *); static int gic_v3_cpu_init(struct gic_v3_softc *); static void gic_v3_wait_for_rwp(struct gic_v3_softc *, enum gic_v3_xdist); @@ -165,6 +166,7 @@ static gic_v3_initseq_t gic_v3_primary_init[] = { gic_v3_dist_init, gic_v3_redist_alloc, + gic_v3_redist_find_all, gic_v3_redist_init, gic_v3_cpu_init, NULL @@ -192,12 +194,19 @@ uint64_t gic_r_read_8(device_t dev, bus_size_t offset) +{ + + return (gic_r_read_nth_8(dev, PCPU_GET(cpuid), offset)); +} + +uint64_t +gic_r_read_nth_8(device_t dev, int which, bus_size_t offset) { struct gic_v3_softc *sc; struct resource *rdist; sc = device_get_softc(dev); - rdist = &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res; + rdist = &sc->gic_redists.pcpu[which]->res; return (bus_read_8(rdist, offset)); } @@ -393,6 +402,9 @@ case GICV3_IVAR_REDIST: *result = (uintptr_t)sc->gic_redists.pcpu[PCPU_GET(cpuid)]; return (0); + case GICV3_IVAR_REDISTS: + *result = (uintptr_t)sc->gic_redists.pcpu; + return (0); case GIC_IVAR_HW_REV: KASSERT( GICR_PIDR2_ARCH(sc->gic_pidr2) == GICR_PIDR2_ARCH_GICv3 || @@ -1136,18 +1148,15 @@ } static int -gic_v3_redist_find(struct gic_v3_softc *sc) +gic_v3_redist_find(struct gic_v3_softc *sc, u_int cpuid) { struct resource r_res; bus_space_handle_t r_bsh; uint64_t aff; uint64_t typer; uint32_t pidr2; - u_int cpuid; size_t i; - cpuid = PCPU_GET(cpuid); - aff = CPU_AFFINITY(cpuid); /* Affinity in format for comparison with typer */ aff = (CPU_AFF3(aff) << 24) | (CPU_AFF2(aff) << 16) | @@ -1204,6 +1213,19 @@ return (ENXIO); } +static int +gic_v3_redist_find_all(struct gic_v3_softc *sc) +{ + int i, err; + + CPU_FOREACH(i) { + err = gic_v3_redist_find(sc, i); + if (err != 0) + return err; + } + return (0); +} + static int gic_v3_redist_wake(struct gic_v3_softc *sc) { @@ -1240,10 +1262,6 @@ int err; size_t i; - err = gic_v3_redist_find(sc); - if (err != 0) - return (err); - err = gic_v3_redist_wake(sc); if (err != 0) return (err); Index: sys/arm64/arm64/gic_v3_var.h =================================================================== --- sys/arm64/arm64/gic_v3_var.h +++ sys/arm64/arm64/gic_v3_var.h @@ -95,9 +95,11 @@ #define GICV3_IVAR_NIRQS 1000 /* 1001 was GICV3_IVAR_REDIST_VADDR */ #define GICV3_IVAR_REDIST 1002 +#define GICV3_IVAR_REDISTS 1003 __BUS_ACCESSOR(gicv3, nirqs, GICV3, NIRQS, u_int); __BUS_ACCESSOR(gicv3, redist, GICV3, REDIST, void *); +__BUS_ACCESSOR(gicv3, redists, GICV3, REDISTS, struct redist_pcpu **); /* Device methods */ int gic_v3_attach(device_t dev); @@ -106,6 +108,7 @@ uint32_t gic_r_read_4(device_t, bus_size_t); uint64_t gic_r_read_8(device_t, bus_size_t); +uint64_t gic_r_read_nth_8(device_t, int, bus_size_t); void gic_r_write_4(device_t, bus_size_t, uint32_t var); void gic_r_write_8(device_t, bus_size_t, uint64_t var); Index: sys/arm64/arm64/gicv3_its.c =================================================================== --- sys/arm64/arm64/gicv3_its.c +++ sys/arm64/arm64/gicv3_its.c @@ -680,7 +680,6 @@ its_init_cpu(device_t dev, struct gicv3_its_softc *sc) { device_t gicv3; - vm_paddr_t target; u_int cpuid; struct redist_pcpu *rpcpu; @@ -701,20 +700,42 @@ rpcpu->lpi_enabled = true; } - if ((gic_its_read_8(sc, GITS_TYPER) & GITS_TYPER_PTA) != 0) { - /* This ITS wants the redistributor physical address */ - target = vtophys(rman_get_virtual(&rpcpu->res)); - } else { - /* This ITS wants the unique processor number */ - target = GICR_TYPER_CPUNUM(gic_r_read_8(gicv3, GICR_TYPER)) << - CMD_TARGET_SHIFT; - } + return (0); +} - sc->sc_its_cols[cpuid]->col_target = target; - sc->sc_its_cols[cpuid]->col_id = cpuid; +static int +its_init_collections(device_t dev, struct gicv3_its_softc *sc) +{ + device_t gicv3; + struct redist_pcpu **rpcpus; + uint64_t gicr_typer; + vm_paddr_t target; + int i; + bool gits_typer_pta; - its_cmd_mapc(dev, sc->sc_its_cols[cpuid], 1); - its_cmd_invall(dev, sc->sc_its_cols[cpuid]); + gicv3 = device_get_parent(dev); + rpcpus = gicv3_get_redists(dev); + gits_typer_pta = (gic_its_read_8(sc, GITS_TYPER) & GITS_TYPER_PTA) != 0; + CPU_FOREACH(i) { + if (CPU_ISSET(i, &sc->sc_cpus) == 0) + continue; + + if (gits_typer_pta) { + /* This ITS wants the redistributor physical address */ + target = vtophys(rman_get_virtual(&rpcpus[i]->res)); + } else { + /* This ITS wants the unique processor number */ + gicr_typer = gic_r_read_nth_8(gicv3, i, GICR_TYPER); + target = GICR_TYPER_CPUNUM(gicr_typer) << + CMD_TARGET_SHIFT; + } + + sc->sc_its_cols[i]->col_target = target; + sc->sc_its_cols[i]->col_id = i; + + its_cmd_mapc(dev, sc->sc_its_cols[i], 1); + its_cmd_invall(dev, sc->sc_its_cols[i]); + } return (0); } @@ -876,6 +897,8 @@ /* Enable LPIs on this CPU */ its_init_cpu(dev, sc); + its_init_collections(dev, sc); + TAILQ_INIT(&sc->sc_its_dev_list); TAILQ_INIT(&sc->sc_free_irqs);