2 * Copyright (c) 2015 The FreeBSD Foundation
5 * This software was developed by Semihalf under
6 * the sponsorship of the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
43 #include <sys/cpuset.h>
45 #include <sys/mutex.h>
51 #include <machine/bus.h>
52 #include <machine/cpu.h>
53 #include <machine/intr.h>
57 #include "gic_v3_reg.h"
58 #include "gic_v3_var.h"
60 /* Device and PIC methods */
61 static int gic_v3_bind(device_t, u_int, u_int);
62 static void gic_v3_dispatch(device_t, struct trapframe *);
63 static void gic_v3_eoi(device_t, u_int);
64 static void gic_v3_mask_irq(device_t, u_int);
65 static void gic_v3_unmask_irq(device_t, u_int);
67 static void gic_v3_init_secondary(device_t);
68 static void gic_v3_ipi_send(device_t, cpuset_t, u_int);
71 static device_method_t gic_v3_methods[] = {
72 /* Device interface */
73 DEVMETHOD(device_detach, gic_v3_detach),
76 DEVMETHOD(pic_bind, gic_v3_bind),
77 DEVMETHOD(pic_dispatch, gic_v3_dispatch),
78 DEVMETHOD(pic_eoi, gic_v3_eoi),
79 DEVMETHOD(pic_mask, gic_v3_mask_irq),
80 DEVMETHOD(pic_unmask, gic_v3_unmask_irq),
82 DEVMETHOD(pic_init_secondary, gic_v3_init_secondary),
83 DEVMETHOD(pic_ipi_send, gic_v3_ipi_send),
89 DEFINE_CLASS_0(gic, gic_v3_driver, gic_v3_methods,
90 sizeof(struct gic_v3_softc));
93 * Driver-specific definitions.
95 MALLOC_DEFINE(M_GIC_V3, "GICv3", GIC_V3_DEVSTR);
98 * Helper functions and definitions.
100 /* Destination registers, either Distributor or Re-Distributor */
106 /* Helper routines starting with gic_v3_ */
107 static int gic_v3_dist_init(struct gic_v3_softc *);
108 static int gic_v3_redist_alloc(struct gic_v3_softc *);
109 static int gic_v3_redist_find(struct gic_v3_softc *);
110 static int gic_v3_redist_init(struct gic_v3_softc *);
111 static int gic_v3_cpu_init(struct gic_v3_softc *);
112 static void gic_v3_wait_for_rwp(struct gic_v3_softc *, enum gic_v3_xdist);
114 /* A sequence of init functions for primary (boot) CPU */
115 typedef int (*gic_v3_initseq_t) (struct gic_v3_softc *);
116 /* Primary CPU initialization sequence */
117 static gic_v3_initseq_t gic_v3_primary_init[] = {
126 /* Secondary CPU initialization sequence */
127 static gic_v3_initseq_t gic_v3_secondary_init[] = {
138 gic_v3_attach(device_t dev)
140 struct gic_v3_softc *sc;
141 gic_v3_initseq_t *init_func;
147 sc = device_get_softc(dev);
148 sc->gic_registered = FALSE;
152 /* Initialize mutex */
153 mtx_init(&sc->gic_mtx, "GICv3 lock", NULL, MTX_SPIN);
156 * Allocate array of struct resource.
157 * One entry for Distributor and all remaining for Re-Distributor.
159 sc->gic_res = malloc(
160 sizeof(*sc->gic_res) * (sc->gic_redists.nregions + 1),
163 /* Now allocate corresponding resources */
164 for (i = 0, rid = 0; i < (sc->gic_redists.nregions + 1); i++, rid++) {
165 sc->gic_res[rid] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
167 if (sc->gic_res[rid] == NULL)
172 * Distributor interface
174 sc->gic_dist = sc->gic_res[0];
177 * Re-Dristributor interface
179 /* Allocate space under region descriptions */
180 sc->gic_redists.regions = malloc(
181 sizeof(*sc->gic_redists.regions) * sc->gic_redists.nregions,
184 /* Fill-up bus_space information for each region. */
185 for (i = 0, rid = 1; i < sc->gic_redists.nregions; i++, rid++)
186 sc->gic_redists.regions[i] = sc->gic_res[rid];
188 /* Get the number of supported SPI interrupts */
189 typer = gic_d_read(sc, 4, GICD_TYPER);
190 sc->gic_nirqs = GICD_TYPER_I_NUM(typer);
191 if (sc->gic_nirqs > GIC_I_NUM_MAX)
192 sc->gic_nirqs = GIC_I_NUM_MAX;
194 /* Get the number of supported interrupt identifier bits */
195 sc->gic_idbits = GICD_TYPER_IDBITS(typer);
198 device_printf(dev, "SPIs: %u, IDs: %u\n",
199 sc->gic_nirqs, (1 << sc->gic_idbits) - 1);
202 /* Train init sequence for boot CPU */
203 for (init_func = gic_v3_primary_init; *init_func != NULL; init_func++) {
204 err = (*init_func)(sc);
210 * Now register PIC to the interrupts handling layer.
212 arm_register_root_pic(dev, sc->gic_nirqs);
213 sc->gic_registered = TRUE;
219 gic_v3_detach(device_t dev)
221 struct gic_v3_softc *sc;
225 sc = device_get_softc(dev);
227 if (device_is_attached(dev)) {
229 * XXX: We should probably deregister PIC
231 if (sc->gic_registered)
232 panic("Trying to detach registered PIC");
234 for (rid = 0; rid < (sc->gic_redists.nregions + 1); rid++)
235 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->gic_res[rid]);
237 for (i = 0; i < mp_ncpus; i++)
238 free(sc->gic_redists.pcpu[i], M_GIC_V3);
240 free(sc->gic_res, M_GIC_V3);
241 free(sc->gic_redists.regions, M_GIC_V3);
251 gic_v3_bind(device_t dev, u_int irq, u_int cpuid)
254 struct gic_v3_softc *sc;
256 sc = device_get_softc(dev);
258 if (irq <= GIC_LAST_PPI) {
259 /* Can't bind PPI to another CPU but it's not an error */
261 } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) {
262 aff = CPU_AFFINITY(cpuid);
263 gic_d_write(sc, 4, GICD_IROUTER(irq), aff);
265 } else if (irq >= GIC_FIRST_LPI)
266 return (lpi_migrate(dev, irq, cpuid));
272 gic_v3_dispatch(device_t dev, struct trapframe *frame)
277 if (CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1) {
279 * Hardware: Cavium ThunderX
280 * Chip revision: Pass 1.0 (early version)
281 * Pass 1.1 (production)
282 * ERRATUM: 22978, 23154
285 "nop;nop;nop;nop;nop;nop;nop;nop; \n"
286 "mrs %0, ICC_IAR1_EL1 \n"
287 "nop;nop;nop;nop; \n"
289 : "=&r" (active_irq));
291 active_irq = gic_icc_read(IAR1);
294 if (__predict_false(active_irq == ICC_IAR1_EL1_SPUR))
297 if (__predict_true((active_irq >= GIC_FIRST_PPI &&
298 active_irq <= GIC_LAST_SPI) || active_irq >= GIC_FIRST_LPI)) {
299 arm_dispatch_intr(active_irq, frame);
303 if (active_irq <= GIC_LAST_SGI) {
304 gic_icc_write(EOIR1, (uint64_t)active_irq);
305 arm_dispatch_intr(active_irq, frame);
312 gic_v3_eoi(device_t dev, u_int irq)
315 gic_icc_write(EOIR1, (uint64_t)irq);
319 gic_v3_mask_irq(device_t dev, u_int irq)
321 struct gic_v3_softc *sc;
323 sc = device_get_softc(dev);
325 if (irq <= GIC_LAST_PPI) { /* SGIs and PPIs in corresponding Re-Distributor */
327 GICR_SGI_BASE_SIZE + GICD_ICENABLER(irq), GICD_I_MASK(irq));
328 gic_v3_wait_for_rwp(sc, REDIST);
329 } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
330 gic_r_write(sc, 4, GICD_ICENABLER(irq), GICD_I_MASK(irq));
331 gic_v3_wait_for_rwp(sc, DIST);
332 } else if (irq >= GIC_FIRST_LPI) { /* LPIs */
333 lpi_mask_irq(dev, irq);
335 panic("%s: Unsupported IRQ number %u", __func__, irq);
339 gic_v3_unmask_irq(device_t dev, u_int irq)
341 struct gic_v3_softc *sc;
343 sc = device_get_softc(dev);
345 if (irq <= GIC_LAST_PPI) { /* SGIs and PPIs in corresponding Re-Distributor */
347 GICR_SGI_BASE_SIZE + GICD_ISENABLER(irq), GICD_I_MASK(irq));
348 gic_v3_wait_for_rwp(sc, REDIST);
349 } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
350 gic_d_write(sc, 4, GICD_ISENABLER(irq), GICD_I_MASK(irq));
351 gic_v3_wait_for_rwp(sc, DIST);
352 } else if (irq >= GIC_FIRST_LPI) { /* LPIs */
353 lpi_unmask_irq(dev, irq);
355 panic("%s: Unsupported IRQ number %u", __func__, irq);
360 gic_v3_init_secondary(device_t dev)
362 struct gic_v3_softc *sc;
363 gic_v3_initseq_t *init_func;
366 sc = device_get_softc(dev);
368 /* Train init sequence for boot CPU */
369 for (init_func = gic_v3_secondary_init; *init_func != NULL; init_func++) {
370 err = (*init_func)(sc);
373 "Could not initialize GIC for CPU%u\n",
380 * Try to initialize ITS.
381 * If there is no driver attached this routine will fail but that
382 * does not mean failure here as only LPIs will not be functional
383 * on the current CPU.
385 if (its_init_cpu(NULL) != 0) {
387 "Could not initialize ITS for CPU%u. "
388 "No LPIs will arrive on this CPU\n",
393 * ARM64TODO: Unmask timer PPIs. To be removed when appropriate
394 * mechanism is implemented.
395 * Activate the timer interrupts: virtual (27), secure (29),
396 * and non-secure (30). Use hardcoded values here as there
397 * should be no defines for them.
399 gic_v3_unmask_irq(dev, 27);
400 gic_v3_unmask_irq(dev, 29);
401 gic_v3_unmask_irq(dev, 30);
405 gic_v3_ipi_send(device_t dev, cpuset_t cpuset, u_int ipi)
412 /* Set affinity mask to match level 3, 2 and 1 */
413 aff_mask = CPU_AFF1_MASK | CPU_AFF2_MASK | CPU_AFF3_MASK;
415 /* Iterate through all CPUs in set */
416 while (!CPU_EMPTY(&cpuset)) {
418 for (cpu = 0; cpu < mp_ncpus; cpu++) {
419 /* Compose target list for single AFF3:AFF2:AFF1 set */
420 if (CPU_ISSET(cpu, &cpuset)) {
423 * Save affinity of the first CPU to
424 * send IPI to for later comparison.
426 aff = CPU_AFFINITY(cpu);
427 tlist |= (1UL << CPU_AFF0(aff));
428 CPU_CLR(cpu, &cpuset);
430 /* Check for same Affinity level 3, 2 and 1 */
431 if ((aff & aff_mask) == (CPU_AFFINITY(cpu) & aff_mask)) {
432 tlist |= (1UL << CPU_AFF0(CPU_AFFINITY(cpu)));
433 /* Clear CPU in cpuset from target list */
434 CPU_CLR(cpu, &cpuset);
439 KASSERT((tlist & ~ICC_SGI1R_EL1_TL_MASK) == 0,
440 ("Target list too long for GICv3 IPI"));
441 /* Send SGI to CPUs in target list */
443 val |= (uint64_t)CPU_AFF3(aff) << ICC_SGI1R_EL1_AFF3_SHIFT;
444 val |= (uint64_t)CPU_AFF2(aff) << ICC_SGI1R_EL1_AFF2_SHIFT;
445 val |= (uint64_t)CPU_AFF1(aff) << ICC_SGI1R_EL1_AFF1_SHIFT;
446 val |= (uint64_t)(ipi & ICC_SGI1R_EL1_SGIID_MASK) <<
447 ICC_SGI1R_EL1_SGIID_SHIFT;
448 gic_icc_write(SGI1R, val);
458 gic_v3_wait_for_rwp(struct gic_v3_softc *sc, enum gic_v3_xdist xdist)
460 struct resource *res;
462 size_t us_left = 1000000;
464 cpuid = PCPU_GET(cpuid);
471 res = sc->gic_redists.pcpu[cpuid];
474 KASSERT(0, ("%s: Attempt to wait for unknown RWP", __func__));
478 while ((bus_read_4(res, GICD_CTLR) & GICD_CTLR_RWP) != 0) {
481 panic("GICD Register write pending for too long");
487 gic_v3_cpu_priority(uint64_t mask)
490 /* Set prority mask */
491 gic_icc_write(PMR, mask & ICC_PMR_EL1_PRIO_MASK);
495 gic_v3_cpu_enable_sre(struct gic_v3_softc *sc)
500 cpuid = PCPU_GET(cpuid);
502 * Set the SRE bit to enable access to GIC CPU interface
503 * via system registers.
505 sre = READ_SPECIALREG(icc_sre_el1);
506 sre |= ICC_SRE_EL1_SRE;
507 WRITE_SPECIALREG(icc_sre_el1, sre);
510 * Now ensure that the bit is set.
512 sre = READ_SPECIALREG(icc_sre_el1);
513 if ((sre & ICC_SRE_EL1_SRE) == 0) {
514 /* We are done. This was disabled in EL2 */
515 device_printf(sc->dev, "ERROR: CPU%u cannot enable CPU interface "
516 "via system registers\n", cpuid);
518 } else if (bootverbose) {
519 device_printf(sc->dev,
520 "CPU%u enabled CPU interface via system registers\n",
528 gic_v3_cpu_init(struct gic_v3_softc *sc)
532 /* Enable access to CPU interface via system registers */
533 err = gic_v3_cpu_enable_sre(sc);
536 /* Priority mask to minimum - accept all interrupts */
537 gic_v3_cpu_priority(GIC_PRIORITY_MIN);
538 /* Disable EOI mode */
539 gic_icc_clear(CTLR, ICC_CTLR_EL1_EOIMODE);
540 /* Enable group 1 (insecure) interrups */
541 gic_icc_set(IGRPEN1, ICC_IGRPEN0_EL1_EN);
548 gic_v3_dist_init(struct gic_v3_softc *sc)
554 * 1. Disable the Distributor
556 gic_d_write(sc, 4, GICD_CTLR, 0);
557 gic_v3_wait_for_rwp(sc, DIST);
560 * 2. Configure the Distributor
562 /* Set all global interrupts to be level triggered, active low. */
563 for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ICFGRn)
564 gic_d_write(sc, 4, GICD_ICFGR(i), 0x00000000);
566 /* Set priority to all shared interrupts */
567 for (i = GIC_FIRST_SPI;
568 i < sc->gic_nirqs; i += GICD_I_PER_IPRIORITYn) {
569 /* Set highest priority */
570 gic_d_write(sc, 4, GICD_IPRIORITYR(i), GIC_PRIORITY_MAX);
574 * Disable all interrupts. Leave PPI and SGIs as they are enabled in
575 * Re-Distributor registers.
577 for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ISENABLERn)
578 gic_d_write(sc, 4, GICD_ICENABLER(i), 0xFFFFFFFF);
580 gic_v3_wait_for_rwp(sc, DIST);
583 * 3. Enable Distributor
585 /* Enable Distributor with ARE, Group 1 */
586 gic_d_write(sc, 4, GICD_CTLR, GICD_CTLR_ARE_NS | GICD_CTLR_G1A |
590 * 4. Route all interrupts to boot CPU.
592 aff = CPU_AFFINITY(0);
593 for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i++)
594 gic_d_write(sc, 4, GICD_IROUTER(i), aff);
601 gic_v3_redist_alloc(struct gic_v3_softc *sc)
605 /* Allocate struct resource for all CPU's Re-Distributor registers */
606 for (cpuid = 0; cpuid < mp_ncpus; cpuid++)
607 if (CPU_ISSET(cpuid, &all_cpus) != 0)
608 sc->gic_redists.pcpu[cpuid] =
609 malloc(sizeof(*sc->gic_redists.pcpu[0]),
612 sc->gic_redists.pcpu[cpuid] = NULL;
617 gic_v3_redist_find(struct gic_v3_softc *sc)
619 struct resource r_res;
620 bus_space_handle_t r_bsh;
627 cpuid = PCPU_GET(cpuid);
629 aff = CPU_AFFINITY(cpuid);
630 /* Affinity in format for comparison with typer */
631 aff = (CPU_AFF3(aff) << 24) | (CPU_AFF2(aff) << 16) |
632 (CPU_AFF1(aff) << 8) | CPU_AFF0(aff);
635 device_printf(sc->dev,
636 "Start searching for Re-Distributor\n");
638 /* Iterate through Re-Distributor regions */
639 for (i = 0; i < sc->gic_redists.nregions; i++) {
640 /* Take a copy of the region's resource */
641 r_res = *sc->gic_redists.regions[i];
642 r_bsh = rman_get_bushandle(&r_res);
644 pidr2 = bus_read_4(&r_res, GICR_PIDR2);
645 switch (pidr2 & GICR_PIDR2_ARCH_MASK) {
646 case GICR_PIDR2_ARCH_GICv3: /* fall through */
647 case GICR_PIDR2_ARCH_GICv4:
650 device_printf(sc->dev,
651 "No Re-Distributor found for CPU%u\n", cpuid);
656 typer = bus_read_8(&r_res, GICR_TYPER);
657 if ((typer >> GICR_TYPER_AFF_SHIFT) == aff) {
658 KASSERT(sc->gic_redists.pcpu[cpuid] != NULL,
659 ("Invalid pointer to per-CPU redistributor"));
660 /* Copy res contents to its final destination */
661 *sc->gic_redists.pcpu[cpuid] = r_res;
663 device_printf(sc->dev,
664 "CPU%u Re-Distributor has been found\n",
670 r_bsh += (GICR_RD_BASE_SIZE + GICR_SGI_BASE_SIZE);
671 if ((typer & GICR_TYPER_VLPIS) != 0) {
673 (GICR_VLPI_BASE_SIZE + GICR_RESERVED_SIZE);
676 rman_set_bushandle(&r_res, r_bsh);
677 } while ((typer & GICR_TYPER_LAST) == 0);
680 device_printf(sc->dev, "No Re-Distributor found for CPU%u\n", cpuid);
685 gic_v3_redist_wake(struct gic_v3_softc *sc)
688 size_t us_left = 1000000;
690 waker = gic_r_read(sc, 4, GICR_WAKER);
691 /* Wake up Re-Distributor for this CPU */
692 waker &= ~GICR_WAKER_PS;
693 gic_r_write(sc, 4, GICR_WAKER, waker);
695 * When clearing ProcessorSleep bit it is required to wait for
696 * ChildrenAsleep to become zero following the processor power-on.
698 while ((gic_r_read(sc, 4, GICR_WAKER) & GICR_WAKER_CA) != 0) {
700 if (us_left-- == 0) {
701 panic("Could not wake Re-Distributor for CPU%u",
707 device_printf(sc->dev, "CPU%u Re-Distributor woke up\n",
715 gic_v3_redist_init(struct gic_v3_softc *sc)
720 err = gic_v3_redist_find(sc);
724 err = gic_v3_redist_wake(sc);
729 gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ICENABLER0,
730 GICR_I_ENABLER_PPI_MASK);
732 gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ISENABLER0,
733 GICR_I_ENABLER_SGI_MASK);
735 /* Set priority for SGIs and PPIs */
736 for (i = 0; i <= GIC_LAST_PPI; i += GICR_I_PER_IPRIORITYn) {
737 gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICD_IPRIORITYR(i),
741 gic_v3_wait_for_rwp(sc, REDIST);