]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/gic_v3.c
Update llvm/clang to r241361.
[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))) {
240                         arm_dispatch_intr(active_irq, frame);
241                         continue;
242                 }
243
244                 if (active_irq <= GIC_LAST_SGI || active_irq >= GIC_FIRST_LPI) {
245                         /*
246                          * TODO: Implement proper SGI/LPI handling.
247                          *       Mask it if such is received for some reason.
248                          */
249                         device_printf(dev,
250                             "Received unsupported interrupt type: %s\n",
251                             active_irq >= GIC_FIRST_LPI ? "LPI" : "SGI");
252                         PIC_MASK(dev, active_irq);
253                 }
254         }
255 }
256
257 static void
258 gic_v3_eoi(device_t dev, u_int irq)
259 {
260
261         gic_icc_write(EOIR1, (uint64_t)irq);
262 }
263
264 static void
265 gic_v3_mask_irq(device_t dev, u_int irq)
266 {
267         struct gic_v3_softc *sc;
268
269         sc = device_get_softc(dev);
270
271         if (irq >= GIC_FIRST_PPI && irq <= GIC_LAST_PPI) { /* PPIs in corresponding Re-Distributor */
272                 gic_r_write(sc, 4,
273                     GICR_SGI_BASE_SIZE + GICD_ICENABLER(irq), GICD_I_MASK(irq));
274                 gic_v3_wait_for_rwp(sc, REDIST);
275         } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
276                 gic_r_write(sc, 4, GICD_ICENABLER(irq), GICD_I_MASK(irq));
277                 gic_v3_wait_for_rwp(sc, DIST);
278         } else
279                 panic("%s: Unsupported IRQ number %u", __func__, irq);
280 }
281
282 static void
283 gic_v3_unmask_irq(device_t dev, u_int irq)
284 {
285         struct gic_v3_softc *sc;
286
287         sc = device_get_softc(dev);
288
289         if (irq >= GIC_FIRST_PPI && irq <= GIC_LAST_PPI) { /* PPIs in corresponding Re-Distributor */
290                 gic_r_write(sc, 4,
291                     GICR_SGI_BASE_SIZE + GICD_ISENABLER(irq), GICD_I_MASK(irq));
292                 gic_v3_wait_for_rwp(sc, REDIST);
293         } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) { /* SPIs in distributor */
294                 gic_d_write(sc, 4, GICD_ISENABLER(irq), GICD_I_MASK(irq));
295                 gic_v3_wait_for_rwp(sc, DIST);
296         } else
297                 panic("%s: Unsupported IRQ number %u", __func__, irq);
298 }
299
300 /*
301  * Helper routines
302  */
303 static void
304 gic_v3_wait_for_rwp(struct gic_v3_softc *sc, enum gic_v3_xdist xdist)
305 {
306         struct resource *res;
307         u_int cpuid;
308         size_t us_left = 1000000;
309
310         cpuid = PCPU_GET(cpuid);
311
312         switch (xdist) {
313         case DIST:
314                 res = sc->gic_dist;
315                 break;
316         case REDIST:
317                 res = sc->gic_redists.pcpu[cpuid];
318                 break;
319         default:
320                 KASSERT(0, ("%s: Attempt to wait for unknown RWP", __func__));
321                 return;
322         }
323
324         while ((bus_read_4(res, GICD_CTLR) & GICD_CTLR_RWP) != 0) {
325                 DELAY(1);
326                 if (us_left-- == 0)
327                         panic("GICD Register write pending for too long");
328         }
329 }
330
331 /* CPU interface. */
332 static __inline void
333 gic_v3_cpu_priority(uint64_t mask)
334 {
335
336         /* Set prority mask */
337         gic_icc_write(PMR, mask & ICC_PMR_EL1_PRIO_MASK);
338 }
339
340 static int
341 gic_v3_cpu_enable_sre(struct gic_v3_softc *sc)
342 {
343         uint64_t sre;
344         u_int cpuid;
345
346         cpuid = PCPU_GET(cpuid);
347         /*
348          * Set the SRE bit to enable access to GIC CPU interface
349          * via system registers.
350          */
351         sre = READ_SPECIALREG(icc_sre_el1);
352         sre |= ICC_SRE_EL1_SRE;
353         WRITE_SPECIALREG(icc_sre_el1, sre);
354         isb();
355         /*
356          * Now ensure that the bit is set.
357          */
358         sre = READ_SPECIALREG(icc_sre_el1);
359         if ((sre & ICC_SRE_EL1_SRE) == 0) {
360                 /* We are done. This was disabled in EL2 */
361                 device_printf(sc->dev, "ERROR: CPU%u cannot enable CPU interface "
362                     "via system registers\n", cpuid);
363                 return (ENXIO);
364         } else if (bootverbose) {
365                 device_printf(sc->dev,
366                     "CPU%u enabled CPU interface via system registers\n",
367                     cpuid);
368         }
369
370         return (0);
371 }
372
373 static int
374 gic_v3_cpu_init(struct gic_v3_softc *sc)
375 {
376         int err;
377
378         /* Enable access to CPU interface via system registers */
379         err = gic_v3_cpu_enable_sre(sc);
380         if (err != 0)
381                 return (err);
382         /* Priority mask to minimum - accept all interrupts */
383         gic_v3_cpu_priority(GIC_PRIORITY_MIN);
384         /* Disable EOI mode */
385         gic_icc_clear(CTLR, ICC_CTLR_EL1_EOIMODE);
386         /* Enable group 1 (insecure) interrups */
387         gic_icc_set(IGRPEN1, ICC_IGRPEN0_EL1_EN);
388
389         return (0);
390 }
391
392 /* Distributor */
393 static int
394 gic_v3_dist_init(struct gic_v3_softc *sc)
395 {
396         uint64_t aff;
397         u_int i;
398
399         /*
400          * 1. Disable the Distributor
401          */
402         gic_d_write(sc, 4, GICD_CTLR, 0);
403         gic_v3_wait_for_rwp(sc, DIST);
404
405         /*
406          * 2. Configure the Distributor
407          */
408         /* Set all global interrupts to be level triggered, active low. */
409         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ICFGRn)
410                 gic_d_write(sc, 4, GICD_ICFGR(i), 0x00000000);
411
412         /* Set priority to all shared interrupts */
413         for (i = GIC_FIRST_SPI;
414             i < sc->gic_nirqs; i += GICD_I_PER_IPRIORITYn) {
415                 /* Set highest priority */
416                 gic_d_write(sc, 4, GICD_IPRIORITYR(i), GIC_PRIORITY_MAX);
417         }
418
419         /*
420          * Disable all interrupts. Leave PPI and SGIs as they are enabled in
421          * Re-Distributor registers.
422          */
423         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i += GICD_I_PER_ISENABLERn)
424                 gic_d_write(sc, 4, GICD_ICENABLER(i), 0xFFFFFFFF);
425
426         gic_v3_wait_for_rwp(sc, DIST);
427
428         /*
429          * 3. Enable Distributor
430          */
431         /* Enable Distributor with ARE, Group 1 */
432         gic_d_write(sc, 4, GICD_CTLR, GICD_CTLR_ARE_NS | GICD_CTLR_G1A |
433             GICD_CTLR_G1);
434
435         /*
436          * 4. Route all interrupts to boot CPU.
437          */
438         aff = CPU_AFFINITY(PCPU_GET(cpuid));
439         for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i++)
440                 gic_d_write(sc, 4, GICD_IROUTER(i), aff);
441
442         return (0);
443 }
444
445 /* Re-Distributor */
446 static int
447 gic_v3_redist_find(struct gic_v3_softc *sc)
448 {
449         struct resource r_res;
450         bus_space_handle_t r_bsh;
451         uint64_t aff;
452         uint64_t typer;
453         uint32_t pidr2;
454         u_int cpuid;
455         size_t i;
456
457         cpuid = PCPU_GET(cpuid);
458
459         /* Allocate struct resource for this CPU's Re-Distributor registers */
460         sc->gic_redists.pcpu[cpuid] =
461             malloc(sizeof(*sc->gic_redists.pcpu[0]), M_GIC_V3, M_WAITOK);
462
463         aff = CPU_AFFINITY(cpuid);
464         /* Affinity in format for comparison with typer */
465         aff = (CPU_AFF3(aff) << 24) | (CPU_AFF2(aff) << 16) |
466             (CPU_AFF1(aff) << 8) | CPU_AFF0(aff);
467
468         if (bootverbose) {
469                 device_printf(sc->dev,
470                     "Start searching for Re-Distributor\n");
471         }
472         /* Iterate through Re-Distributor regions */
473         for (i = 0; i < sc->gic_redists.nregions; i++) {
474                 /* Take a copy of the region's resource */
475                 r_res = *sc->gic_redists.regions[i];
476                 r_bsh = rman_get_bushandle(&r_res);
477
478                 pidr2 = bus_read_4(&r_res, GICR_PIDR2);
479                 switch (pidr2 & GICR_PIDR2_ARCH_MASK) {
480                 case GICR_PIDR2_ARCH_GICv3: /* fall through */
481                 case GICR_PIDR2_ARCH_GICv4:
482                         break;
483                 default:
484                         device_printf(sc->dev,
485                             "No Re-Distributor found for CPU%u\n", cpuid);
486                         free(sc->gic_redists.pcpu[cpuid], M_GIC_V3);
487                         return (ENODEV);
488                 }
489
490                 do {
491                         typer = bus_read_8(&r_res, GICR_TYPER);
492                         if ((typer >> GICR_TYPER_AFF_SHIFT) == aff) {
493                                 KASSERT(sc->gic_redists.pcpu[cpuid] != NULL,
494                                     ("Invalid pointer to per-CPU redistributor"));
495                                 /* Copy res contents to its final destination */
496                                 *sc->gic_redists.pcpu[cpuid] = r_res;
497                                 if (bootverbose) {
498                                         device_printf(sc->dev,
499                                             "CPU%u Re-Distributor has been found\n",
500                                             cpuid);
501                                 }
502                                 return (0);
503                         }
504
505                         r_bsh += (GICR_RD_BASE_SIZE + GICR_SGI_BASE_SIZE);
506                         if ((typer & GICR_TYPER_VLPIS) != 0) {
507                                 r_bsh +=
508                                     (GICR_VLPI_BASE_SIZE + GICR_RESERVED_SIZE);
509                         }
510
511                         rman_set_bushandle(&r_res, r_bsh);
512                 } while ((typer & GICR_TYPER_LAST) == 0);
513         }
514
515         free(sc->gic_redists.pcpu[cpuid], M_GIC_V3);
516         device_printf(sc->dev, "No Re-Distributor found for CPU%u\n", cpuid);
517         return (ENXIO);
518 }
519
520 static int
521 gic_v3_redist_wake(struct gic_v3_softc *sc)
522 {
523         uint32_t waker;
524         size_t us_left = 1000000;
525
526         waker = gic_r_read(sc, 4, GICR_WAKER);
527         /* Wake up Re-Distributor for this CPU */
528         waker &= ~GICR_WAKER_PS;
529         gic_r_write(sc, 4, GICR_WAKER, waker);
530         /*
531          * When clearing ProcessorSleep bit it is required to wait for
532          * ChildrenAsleep to become zero following the processor power-on.
533          */
534         while ((gic_r_read(sc, 4, GICR_WAKER) & GICR_WAKER_CA) != 0) {
535                 DELAY(1);
536                 if (us_left-- == 0) {
537                         panic("Could not wake Re-Distributor for CPU%u",
538                             PCPU_GET(cpuid));
539                 }
540         }
541
542         if (bootverbose) {
543                 device_printf(sc->dev, "CPU%u Re-Distributor woke up\n",
544                     PCPU_GET(cpuid));
545         }
546
547         return (0);
548 }
549
550 static int
551 gic_v3_redist_init(struct gic_v3_softc *sc)
552 {
553         int err;
554         size_t i;
555
556         err = gic_v3_redist_find(sc);
557         if (err != 0)
558                 return (err);
559
560         err = gic_v3_redist_wake(sc);
561         if (err != 0)
562                 return (err);
563
564         /* Disable SPIs */
565         gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ICENABLER0,
566             GICR_I_ENABLER_PPI_MASK);
567         /* Enable SGIs */
568         gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICR_ISENABLER0,
569             GICR_I_ENABLER_SGI_MASK);
570
571         /* Set priority for SGIs and PPIs */
572         for (i = 0; i <= GIC_LAST_PPI; i += GICR_I_PER_IPRIORITYn) {
573                 gic_r_write(sc, 4, GICR_SGI_BASE_SIZE + GICD_IPRIORITYR(i),
574                     GIC_PRIORITY_MAX);
575         }
576
577         gic_v3_wait_for_rwp(sc, REDIST);
578
579         return (0);
580 }