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