]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/gic_v3.c
MFhead @ r286584
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / gic_v3.c
1 /*-
2  * Copyright (c) 2015 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Semihalf under
6  * the sponsorship of the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
16  *
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
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/ktr.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
40 #include <sys/rman.h>
41 #include <sys/pcpu.h>
42 #include <sys/proc.h>
43 #include <sys/cpuset.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46
47 #include <vm/vm.h>
48 #include <vm/pmap.h>
49
50 #include <machine/bus.h>
51 #include <machine/cpu.h>
52 #include <machine/intr.h>
53
54 #include "pic_if.h"
55
56 #include "gic_v3_reg.h"
57 #include "gic_v3_var.h"
58
59 /* Device and PIC methods */
60 static void gic_v3_dispatch(device_t, struct trapframe *);
61 static void gic_v3_eoi(device_t, u_int);
62 static void gic_v3_mask_irq(device_t, u_int);
63 static void gic_v3_unmask_irq(device_t, u_int);
64
65 static device_method_t gic_v3_methods[] = {
66         /* Device interface */
67         DEVMETHOD(device_detach,        gic_v3_detach),
68
69         /* PIC interface */
70         DEVMETHOD(pic_dispatch,         gic_v3_dispatch),
71         DEVMETHOD(pic_eoi,              gic_v3_eoi),
72         DEVMETHOD(pic_mask,             gic_v3_mask_irq),
73         DEVMETHOD(pic_unmask,           gic_v3_unmask_irq),
74
75         /* End */
76         DEVMETHOD_END
77 };
78
79 DEFINE_CLASS_0(gic_v3, gic_v3_driver, gic_v3_methods,
80     sizeof(struct gic_v3_softc));
81
82 /*
83  * Driver-specific definitions.
84  */
85 MALLOC_DEFINE(M_GIC_V3, "GICv3", GIC_V3_DEVSTR);
86
87 /*
88  * Helper functions and definitions.
89  */
90 /* Destination registers, either Distributor or Re-Distributor */
91 enum gic_v3_xdist {
92         DIST = 0,
93         REDIST,
94 };
95
96 /* Helper routines starting with gic_v3_ */
97 static int gic_v3_dist_init(struct gic_v3_softc *);
98 static int gic_v3_redist_find(struct gic_v3_softc *);
99 static int gic_v3_redist_init(struct gic_v3_softc *);
100 static int gic_v3_cpu_init(struct gic_v3_softc *);
101 static void gic_v3_wait_for_rwp(struct gic_v3_softc *, enum gic_v3_xdist);
102
103 /* A sequence of init functions for primary (boot) CPU */
104 typedef int (*gic_v3_initseq_t) (struct gic_v3_softc *);
105 /* Primary CPU initialization sequence */
106 static gic_v3_initseq_t gic_v3_primary_init[] = {
107         gic_v3_dist_init,
108         gic_v3_redist_init,
109         gic_v3_cpu_init,
110         NULL
111 };
112
113 /*
114  * Device interface.
115  */
116 int
117 gic_v3_attach(device_t dev)
118 {
119         struct gic_v3_softc *sc;
120         gic_v3_initseq_t *init_func;
121         uint32_t typer;
122         int rid;
123         int err;
124         size_t i;
125
126         sc = device_get_softc(dev);
127         sc->gic_registered = FALSE;
128         sc->dev = dev;
129         err = 0;
130
131         /* Initialize mutex */
132         mtx_init(&sc->gic_mtx, "GICv3 lock", NULL, MTX_SPIN);
133
134         /*
135          * Allocate array of struct resource.
136          * One entry for Distributor and all remaining for Re-Distributor.
137          */
138         sc->gic_res = malloc(
139             sizeof(sc->gic_res) * (sc->gic_redists.nregions + 1),
140             M_GIC_V3, M_WAITOK);
141
142         /* Now allocate corresponding resources */
143         for (i = 0, rid = 0; i < (sc->gic_redists.nregions + 1); i++, rid++) {
144                 sc->gic_res[rid] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
145                     &rid, RF_ACTIVE);
146                 if (sc->gic_res[rid] == NULL)
147                         return (ENXIO);
148         }
149
150         /*
151          * Distributor interface
152          */
153         sc->gic_dist = sc->gic_res[0];
154
155         /*
156          * Re-Dristributor interface
157          */
158         /* Allocate space under region descriptions */
159         sc->gic_redists.regions = malloc(
160             sizeof(*sc->gic_redists.regions) * sc->gic_redists.nregions,
161             M_GIC_V3, M_WAITOK);
162
163         /* Fill-up bus_space information for each region. */
164         for (i = 0, rid = 1; i < sc->gic_redists.nregions; i++, rid++)
165                 sc->gic_redists.regions[i] = sc->gic_res[rid];
166
167         /* Get the number of supported SPI interrupts */
168         typer = gic_d_read(sc, 4, GICD_TYPER);
169         sc->gic_nirqs = GICD_TYPER_I_NUM(typer);
170         if (sc->gic_nirqs > GIC_I_NUM_MAX)
171                 sc->gic_nirqs = GIC_I_NUM_MAX;
172
173         /* Get the number of supported interrupt identifier bits */
174         sc->gic_idbits = GICD_TYPER_IDBITS(typer);
175
176         if (bootverbose) {
177                 device_printf(dev, "SPIs: %u, IDs: %u\n",
178                     sc->gic_nirqs, (1 << sc->gic_idbits) - 1);
179         }
180
181         /* Train init sequence for boot CPU */
182         for (init_func = gic_v3_primary_init; *init_func != NULL; init_func++) {
183                 err = (*init_func)(sc);
184                 if (err != 0)
185                         return (err);
186         }
187         /*
188          * Full success.
189          * Now register PIC to the interrupts handling layer.
190          */
191         arm_register_root_pic(dev, sc->gic_nirqs);
192         sc->gic_registered = TRUE;
193
194         return (0);
195 }
196
197 int
198 gic_v3_detach(device_t dev)
199 {
200         struct gic_v3_softc *sc;
201         size_t i;
202         int rid;
203
204         sc = device_get_softc(dev);
205
206         if (device_is_attached(dev)) {
207                 /*
208                  * XXX: We should probably deregister PIC
209                  */
210                 if (sc->gic_registered)
211                         panic("Trying to detach registered PIC");
212         }
213         for (rid = 0; rid < (sc->gic_redists.nregions + 1); rid++)
214                 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->gic_res[rid]);
215
216         for (i = 0; i < MAXCPU; i++)
217                 free(sc->gic_redists.pcpu[i], M_GIC_V3);
218
219         free(sc->gic_res, M_GIC_V3);
220         free(sc->gic_redists.regions, M_GIC_V3);
221
222         return (0);
223 }
224
225 /*
226  * PIC interface.
227  */
228 static void
229 gic_v3_dispatch(device_t dev, struct trapframe *frame)
230 {
231         uint64_t active_irq;
232
233         while (1) {
234                 if (CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1) {
235                         /*
236                          * Hardware:            Cavium ThunderX
237                          * Chip revision:       Pass 1.0 (early version)
238                          *                      Pass 1.1 (production)
239                          * ERRATUM:             22978, 23154
240                          */
241                         __asm __volatile(
242                             "nop;nop;nop;nop;nop;nop;nop;nop;   \n"
243                             "mrs %0, ICC_IAR1_EL1               \n"
244                             "nop;nop;nop;nop;                   \n"
245                             "dsb sy                             \n"
246                             : "=&r" (active_irq));
247                 } else {
248                         active_irq = gic_icc_read(IAR1);
249                 }
250
251                 if (__predict_false(active_irq == ICC_IAR1_EL1_SPUR))
252                         break;
253
254                 if (__predict_true((active_irq >= GIC_FIRST_PPI &&
255                     active_irq <= GIC_LAST_SPI) || active_irq >= GIC_FIRST_LPI)) {
256                         arm_dispatch_intr(active_irq, frame);
257                         continue;
258                 }
259
260                 if (active_irq <= GIC_LAST_SGI) {
261                         /*
262                          * TODO: Implement proper SGI handling.
263                          *       Mask it if such is received for some reason.
264                          */
265                         device_printf(dev,
266                             "Received unsupported interrupt type: SGI\n");
267                         PIC_MASK(dev, active_irq);
268                 }
269         }
270 }
271
272 static void
273 gic_v3_eoi(device_t dev, u_int irq)
274 {
275
276         gic_icc_write(EOIR1, (uint64_t)irq);
277 }
278
279 static void
280 gic_v3_mask_irq(device_t dev, u_int irq)
281 {
282         struct gic_v3_softc *sc;
283
284         sc = device_get_softc(dev);
285
286         if (irq >= GIC_FIRST_PPI && irq <= GIC_LAST_PPI) { /* PPIs in corresponding Re-Distributor */
287                 gic_r_write(sc, 4,
288                     GICR_SGI_BASE_SIZE + GICD_ICENABLER(irq), GICD_I_MASK(irq));
289                 gic_v3_wait_for_rwp(sc, REDIST);
290         } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
291                 gic_r_write(sc, 4, GICD_ICENABLER(irq), GICD_I_MASK(irq));
292                 gic_v3_wait_for_rwp(sc, DIST);
293         } else if (irq >= GIC_FIRST_LPI) { /* LPIs */
294                 lpi_mask_irq(dev, irq);
295         } else
296                 panic("%s: Unsupported IRQ number %u", __func__, irq);
297 }
298
299 static void
300 gic_v3_unmask_irq(device_t dev, u_int irq)
301 {
302         struct gic_v3_softc *sc;
303
304         sc = device_get_softc(dev);
305
306         if (irq >= GIC_FIRST_PPI && irq <= GIC_LAST_PPI) { /* PPIs in corresponding Re-Distributor */
307                 gic_r_write(sc, 4,
308                     GICR_SGI_BASE_SIZE + GICD_ISENABLER(irq), GICD_I_MASK(irq));
309                 gic_v3_wait_for_rwp(sc, REDIST);
310         } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
311                 gic_d_write(sc, 4, GICD_ISENABLER(irq), GICD_I_MASK(irq));
312                 gic_v3_wait_for_rwp(sc, DIST);
313         } else if (irq >= GIC_FIRST_LPI) { /* LPIs */
314                 lpi_unmask_irq(dev, irq);
315         } else
316                 panic("%s: Unsupported IRQ number %u", __func__, irq);
317 }
318
319 /*
320  * Helper routines
321  */
322 static void
323 gic_v3_wait_for_rwp(struct gic_v3_softc *sc, enum gic_v3_xdist xdist)
324 {
325         struct resource *res;
326         u_int cpuid;
327         size_t us_left = 1000000;
328
329         cpuid = PCPU_GET(cpuid);
330
331         switch (xdist) {
332         case DIST:
333                 res = sc->gic_dist;
334                 break;
335         case REDIST:
336                 res = sc->gic_redists.pcpu[cpuid];
337                 break;
338         default:
339                 KASSERT(0, ("%s: Attempt to wait for unknown RWP", __func__));
340                 return;
341         }
342
343         while ((bus_read_4(res, GICD_CTLR) & GICD_CTLR_RWP) != 0) {
344                 DELAY(1);
345                 if (us_left-- == 0)
346                         panic("GICD Register write pending for too long");
347         }
348 }
349
350 /* CPU interface. */
351 static __inline void
352 gic_v3_cpu_priority(uint64_t mask)
353 {
354
355         /* Set prority mask */
356         gic_icc_write(PMR, mask & ICC_PMR_EL1_PRIO_MASK);
357 }
358
359 static int
360 gic_v3_cpu_enable_sre(struct gic_v3_softc *sc)
361 {
362         uint64_t sre;
363         u_int cpuid;
364
365         cpuid = PCPU_GET(cpuid);
366         /*
367          * Set the SRE bit to enable access to GIC CPU interface
368          * via system registers.
369          */
370         sre = READ_SPECIALREG(icc_sre_el1);
371         sre |= ICC_SRE_EL1_SRE;
372         WRITE_SPECIALREG(icc_sre_el1, sre);
373         isb();
374         /*
375          * Now ensure that the bit is set.
376          */
377         sre = READ_SPECIALREG(icc_sre_el1);
378         if ((sre & ICC_SRE_EL1_SRE) == 0) {
379                 /* We are done. This was disabled in EL2 */
380                 device_printf(sc->dev, "ERROR: CPU%u cannot enable CPU interface "
381                     "via system registers\n", cpuid);
382                 return (ENXIO);
383         } else if (bootverbose) {
384                 device_printf(sc->dev,
385                     "CPU%u enabled CPU interface via system registers\n",
386                     cpuid);
387         }
388
389         return (0);
390 }
391
392 static int
393 gic_v3_cpu_init(struct gic_v3_softc *sc)
394 {
395         int err;
396
397         /* Enable access to CPU interface via system registers */
398         err = gic_v3_cpu_enable_sre(sc);
399         if (err != 0)
400                 return (err);
401         /* Priority mask to minimum - accept all interrupts */
402         gic_v3_cpu_priority(GIC_PRIORITY_MIN);
403         /* Disable EOI mode */
404         gic_icc_clear(CTLR, ICC_CTLR_EL1_EOIMODE);
405         /* Enable group 1 (insecure) interrups */
406         gic_icc_set(IGRPEN1, ICC_IGRPEN0_EL1_EN);
407
408         return (0);
409 }
410
411 /* Distributor */
412 static int
413 gic_v3_dist_init(struct gic_v3_softc *sc)
414 {
415         uint64_t aff;
416         u_int i;
417
418         /*
419          * 1. Disable the Distributor
420          */
421         gic_d_write(sc, 4, GICD_CTLR, 0);
422         gic_v3_wait_for_rwp(sc, DIST);
423
424         /*
425          * 2. Configure the Distributor
426          */
427         /* Set all global interrupts to be level triggered, active low. */
428         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ICFGRn)
429                 gic_d_write(sc, 4, GICD_ICFGR(i), 0x00000000);
430
431         /* Set priority to all shared interrupts */
432         for (i = GIC_FIRST_SPI;
433             i < sc->gic_nirqs; i += GICD_I_PER_IPRIORITYn) {
434                 /* Set highest priority */
435                 gic_d_write(sc, 4, GICD_IPRIORITYR(i), GIC_PRIORITY_MAX);
436         }
437
438         /*
439          * Disable all interrupts. Leave PPI and SGIs as they are enabled in
440          * Re-Distributor registers.
441          */
442         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ISENABLERn)
443                 gic_d_write(sc, 4, GICD_ICENABLER(i), 0xFFFFFFFF);
444
445         gic_v3_wait_for_rwp(sc, DIST);
446
447         /*
448          * 3. Enable Distributor
449          */
450         /* Enable Distributor with ARE, Group 1 */
451         gic_d_write(sc, 4, GICD_CTLR, GICD_CTLR_ARE_NS | GICD_CTLR_G1A |
452             GICD_CTLR_G1);
453
454         /*
455          * 4. Route all interrupts to boot CPU.
456          */
457         aff = CPU_AFFINITY(PCPU_GET(cpuid));
458         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i++)
459                 gic_d_write(sc, 4, GICD_IROUTER(i), aff);
460
461         return (0);
462 }
463
464 /* Re-Distributor */
465 static int
466 gic_v3_redist_find(struct gic_v3_softc *sc)
467 {
468         struct resource r_res;
469         bus_space_handle_t r_bsh;
470         uint64_t aff;
471         uint64_t typer;
472         uint32_t pidr2;
473         u_int cpuid;
474         size_t i;
475
476         cpuid = PCPU_GET(cpuid);
477
478         /* Allocate struct resource for this CPU's Re-Distributor registers */
479         sc->gic_redists.pcpu[cpuid] =
480             malloc(sizeof(*sc->gic_redists.pcpu[0]), M_GIC_V3, M_WAITOK);
481
482         aff = CPU_AFFINITY(cpuid);
483         /* Affinity in format for comparison with typer */
484         aff = (CPU_AFF3(aff) << 24) | (CPU_AFF2(aff) << 16) |
485             (CPU_AFF1(aff) << 8) | CPU_AFF0(aff);
486
487         if (bootverbose) {
488                 device_printf(sc->dev,
489                     "Start searching for Re-Distributor\n");
490         }
491         /* Iterate through Re-Distributor regions */
492         for (i = 0; i < sc->gic_redists.nregions; i++) {
493                 /* Take a copy of the region's resource */
494                 r_res = *sc->gic_redists.regions[i];
495                 r_bsh = rman_get_bushandle(&r_res);
496
497                 pidr2 = bus_read_4(&r_res, GICR_PIDR2);
498                 switch (pidr2 & GICR_PIDR2_ARCH_MASK) {
499                 case GICR_PIDR2_ARCH_GICv3: /* fall through */
500                 case GICR_PIDR2_ARCH_GICv4:
501                         break;
502                 default:
503                         device_printf(sc->dev,
504                             "No Re-Distributor found for CPU%u\n", cpuid);
505                         free(sc->gic_redists.pcpu[cpuid], M_GIC_V3);
506                         return (ENODEV);
507                 }
508
509                 do {
510                         typer = bus_read_8(&r_res, GICR_TYPER);
511                         if ((typer >> GICR_TYPER_AFF_SHIFT) == aff) {
512                                 KASSERT(sc->gic_redists.pcpu[cpuid] != NULL,
513                                     ("Invalid pointer to per-CPU redistributor"));
514                                 /* Copy res contents to its final destination */
515                                 *sc->gic_redists.pcpu[cpuid] = r_res;
516                                 if (bootverbose) {
517                                         device_printf(sc->dev,
518                                             "CPU%u Re-Distributor has been found\n",
519                                             cpuid);
520                                 }
521                                 return (0);
522                         }
523
524                         r_bsh += (GICR_RD_BASE_SIZE + GICR_SGI_BASE_SIZE);
525                         if ((typer & GICR_TYPER_VLPIS) != 0) {
526                                 r_bsh +=
527                                     (GICR_VLPI_BASE_SIZE + GICR_RESERVED_SIZE);
528                         }
529
530                         rman_set_bushandle(&r_res, r_bsh);
531                 } while ((typer & GICR_TYPER_LAST) == 0);
532         }
533
534         free(sc->gic_redists.pcpu[cpuid], M_GIC_V3);
535         device_printf(sc->dev, "No Re-Distributor found for CPU%u\n", cpuid);
536         return (ENXIO);
537 }
538
539 static int
540 gic_v3_redist_wake(struct gic_v3_softc *sc)
541 {
542         uint32_t waker;
543         size_t us_left = 1000000;
544
545         waker = gic_r_read(sc, 4, GICR_WAKER);
546         /* Wake up Re-Distributor for this CPU */
547         waker &= ~GICR_WAKER_PS;
548         gic_r_write(sc, 4, GICR_WAKER, waker);
549         /*
550          * When clearing ProcessorSleep bit it is required to wait for
551          * ChildrenAsleep to become zero following the processor power-on.
552          */
553         while ((gic_r_read(sc, 4, GICR_WAKER) & GICR_WAKER_CA) != 0) {
554                 DELAY(1);
555                 if (us_left-- == 0) {
556                         panic("Could not wake Re-Distributor for CPU%u",
557                             PCPU_GET(cpuid));
558                 }
559         }
560
561         if (bootverbose) {
562                 device_printf(sc->dev, "CPU%u Re-Distributor woke up\n",
563                     PCPU_GET(cpuid));
564         }
565
566         return (0);
567 }
568
569 static int
570 gic_v3_redist_init(struct gic_v3_softc *sc)
571 {
572         int err;
573         size_t i;
574
575         err = gic_v3_redist_find(sc);
576         if (err != 0)
577                 return (err);
578
579         err = gic_v3_redist_wake(sc);
580         if (err != 0)
581                 return (err);
582
583         /* Disable SPIs */
584         gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ICENABLER0,
585             GICR_I_ENABLER_PPI_MASK);
586         /* Enable SGIs */
587         gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ISENABLER0,
588             GICR_I_ENABLER_SGI_MASK);
589
590         /* Set priority for SGIs and PPIs */
591         for (i = 0; i <= GIC_LAST_PPI; i += GICR_I_PER_IPRIORITYn) {
592                 gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICD_IPRIORITYR(i),
593                     GIC_PRIORITY_MAX);
594         }
595
596         gic_v3_wait_for_rwp(sc, REDIST);
597
598         return (0);
599 }