Index: agintc.c =================================================================== RCS file: /cvs/src/sys/arch/arm64/dev/agintc.c,v diff -u -p -r1.62 agintc.c --- agintc.c 24 Jan 2025 20:17:28 -0000 1.62 +++ agintc.c 3 Jul 2025 02:48:45 -0000 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -182,9 +183,9 @@ struct agintc_softc { struct agintc_dmamem *sc_prop; struct agintc_dmamem *sc_pend; struct interrupt_controller sc_ic; - int sc_ipi_num[3]; /* id for each ipi */ + int sc_ipi_num; /* id for ipi */ int sc_ipi_reason[MAXCPUS]; /* cause of ipi */ - void *sc_ipi_irq[3]; /* irqhandle for each ipi */ + void *sc_ipi_irq; /* ipi irqhandle */ }; struct agintc_softc *agintc_sc; @@ -317,7 +318,7 @@ agintc_attach(struct device *parent, str int i, nbits, nintr; int idx, offset, nredist; #ifdef MULTIPROCESSOR - int nipi, ipiirq[3]; + int ipiirq; #endif psw = intr_disable(); @@ -600,13 +601,7 @@ agintc_attach(struct device *parent, str #ifdef MULTIPROCESSOR /* setup IPI interrupts */ - /* - * Ideally we want three IPI interrupts, one for NOP, one for - * DDB and one for HALT. However we can survive if only one - * is available; it is possible that most are not available to - * the non-secure OS. - */ - nipi = 0; + ipiirq = -1; for (i = 0; i < 16; i++) { int hwcpu = sc->sc_cpuremap[cpu_number()]; int reg, oldreg; @@ -625,56 +620,19 @@ agintc_attach(struct device *parent, str /* return to original value, will be set when used */ bus_space_write_1(sc->sc_iot, sc->sc_r_ioh[hwcpu], GICR_IPRIORITYR(i), oldreg); - - if (nipi == 0) - printf(" ipi: %d", i); - else - printf(", %d", i); - ipiirq[nipi++] = i; - if (nipi == 3) - break; + ipiirq = i; + break; } - if (nipi == 0) + if (ipiirq == -1) panic("no irq available for IPI"); - switch (nipi) { - case 1: - sc->sc_ipi_irq[0] = agintc_intr_establish(ipiirq[0], - IST_EDGE_RISING, IPL_IPI|IPL_MPSAFE, NULL, - agintc_ipi_combined, sc, "ipi"); - sc->sc_ipi_num[ARM_IPI_NOP] = ipiirq[0]; - sc->sc_ipi_num[ARM_IPI_DDB] = ipiirq[0]; - sc->sc_ipi_num[ARM_IPI_HALT] = ipiirq[0]; - break; - case 2: - sc->sc_ipi_irq[0] = agintc_intr_establish(ipiirq[0], - IST_EDGE_RISING, IPL_IPI|IPL_MPSAFE, NULL, - agintc_ipi_nop, sc, "ipinop"); - sc->sc_ipi_num[ARM_IPI_NOP] = ipiirq[0]; - sc->sc_ipi_irq[1] = agintc_intr_establish(ipiirq[1], - IST_EDGE_RISING, IPL_IPI|IPL_MPSAFE, NULL, - agintc_ipi_combined, sc, "ipi"); - sc->sc_ipi_num[ARM_IPI_DDB] = ipiirq[1]; - sc->sc_ipi_num[ARM_IPI_HALT] = ipiirq[1]; - break; - case 3: - sc->sc_ipi_irq[0] = agintc_intr_establish(ipiirq[0], - IST_EDGE_RISING, IPL_IPI|IPL_MPSAFE, NULL, - agintc_ipi_nop, sc, "ipinop"); - sc->sc_ipi_num[ARM_IPI_NOP] = ipiirq[0]; - sc->sc_ipi_irq[1] = agintc_intr_establish(ipiirq[1], - IST_EDGE_RISING, IPL_IPI|IPL_MPSAFE, NULL, - agintc_ipi_ddb, sc, "ipiddb"); - sc->sc_ipi_num[ARM_IPI_DDB] = ipiirq[1]; - sc->sc_ipi_irq[2] = agintc_intr_establish(ipiirq[2], - IST_EDGE_RISING, IPL_IPI|IPL_MPSAFE, NULL, - agintc_ipi_halt, sc, "ipihalt"); - sc->sc_ipi_num[ARM_IPI_HALT] = ipiirq[2]; - break; - default: - panic("nipi unexpected number %d", nipi); - } + printf(" ipi %d", ipiirq); + + sc->sc_ipi_irq = agintc_intr_establish(ipiirq, + IST_EDGE_RISING, IPL_IPI|IPL_MPSAFE, NULL, + agintc_ipi_combined, sc, "ipi"); + sc->sc_ipi_num = ipiirq; intr_send_ipi_func = agintc_send_ipi; #endif @@ -764,12 +722,13 @@ void agintc_cpuinit(void) { struct agintc_softc *sc = agintc_sc; + struct cpu_info *ci = curcpu(); uint32_t waker; int timeout = 100000; int hwcpu; int i; - hwcpu = sc->sc_cpuremap[cpu_number()]; + hwcpu = sc->sc_cpuremap[ci->ci_cpuid]; waker = bus_space_read_4(sc->sc_iot, sc->sc_r_ioh[hwcpu], GICR_WAKER); waker &= ~(GICR_WAKER_PROCESSORSLEEP); @@ -798,12 +757,8 @@ agintc_cpuinit(void) bus_space_write_4(sc->sc_iot, sc->sc_r_ioh[hwcpu], GICR_IGRPMODR0, 0); - if (sc->sc_ipi_irq[0] != NULL) - agintc_route_irq(sc->sc_ipi_irq[0], IRQ_ENABLE, curcpu()); - if (sc->sc_ipi_irq[1] != NULL) - agintc_route_irq(sc->sc_ipi_irq[1], IRQ_ENABLE, curcpu()); - if (sc->sc_ipi_irq[2] != NULL) - agintc_route_irq(sc->sc_ipi_irq[2], IRQ_ENABLE, curcpu()); + if (sc->sc_ipi_irq != NULL) + agintc_route_irq(sc->sc_ipi_irq, IRQ_ENABLE, curcpu()); __asm volatile("msr "STR(ICC_PMR)", %x0" :: "r"(0xff)); __asm volatile("msr "STR(ICC_BPR1)", %x0" :: "r"(0)); @@ -1451,7 +1406,7 @@ agintc_ipi_halt(void *v) int old = curcpu()->ci_cpl; intr_disable(); - agintc_eoi(sc->sc_ipi_num[ARM_IPI_HALT]); + agintc_eoi(sc->sc_ipi_num); agintc_setipl(IPL_NONE); cpu_halt(); @@ -1472,37 +1427,37 @@ int agintc_ipi_combined(void *v) { struct agintc_softc *sc = v; + struct cpu_info *ci = curcpu(); + u_int reasons; - if (sc->sc_ipi_reason[cpu_number()] == ARM_IPI_DDB) { - sc->sc_ipi_reason[cpu_number()] = ARM_IPI_NOP; - return agintc_ipi_ddb(v); - } else if (sc->sc_ipi_reason[cpu_number()] == ARM_IPI_HALT) { - sc->sc_ipi_reason[cpu_number()] = ARM_IPI_NOP; - return agintc_ipi_halt(v); - } else { - return agintc_ipi_nop(v); + reasons = atomic_swap_uint(&sc->sc_ipi_reason[ci->ci_cpuid], 0); + if (reasons) { + if (ISSET(reasons, 1 << ARM_IPI_DDB)) + agintc_ipi_ddb(v); + if (ISSET(reasons, 1 << ARM_IPI_HALT)) + agintc_ipi_halt(v); } + + return (1); } void -agintc_send_ipi(struct cpu_info *ci, int id) +agintc_send_ipi(struct cpu_info *ci, int reason) { struct agintc_softc *sc = agintc_sc; uint64_t sendmask; - if (ci == curcpu() && id == ARM_IPI_NOP) + if (ci == curcpu() && reason == ARM_IPI_NOP) return; - /* never overwrite IPI_DDB or IPI_HALT with IPI_NOP */ - if (id == ARM_IPI_DDB || id == ARM_IPI_HALT) - sc->sc_ipi_reason[ci->ci_cpuid] = id; + atomic_setbits_int(&sc->sc_ipi_reason[ci->ci_cpuid], 1 << reason); /* will only send 1 cpu */ sendmask = (ci->ci_mpidr & MPIDR_AFF3) << 16; sendmask |= (ci->ci_mpidr & MPIDR_AFF2) << 16; sendmask |= (ci->ci_mpidr & MPIDR_AFF1) << 8; sendmask |= 1 << (ci->ci_mpidr & 0x0f); - sendmask |= (sc->sc_ipi_num[id] << 24); + sendmask |= (sc->sc_ipi_num << 24); __asm volatile ("msr " STR(ICC_SGI1R)", %x0" ::"r"(sendmask)); }