Merge branch 'master' into isa/arm64
[lunaix-os.git] / lunaix-os / arch / aarch64 / soc / gic.c
1 #include <lunaix/types.h>
2 #include <lunaix/device.h>
3 #include <lunaix/spike.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/mm/page.h>
6 #include <lunaix/mm/mmio.h>
7 #include <lunaix/syslog.h>
8
9 #include <hal/devtree.h>
10
11 #include <asm/aa64_isrm.h>
12 #include <asm/soc/gic.h>
13
14 static struct arm_gic gic;
15
16 LOG_MODULE("gic")
17
18 DEFINE_BMP_INIT_OP(gic_bmp, valloc);
19
20 DEFINE_BMP_QUERY_OP(gic_bmp);
21
22 DEFINE_BMP_SET_OP(gic_bmp);
23
24 DEFINE_BMP_ALLOCFROM_OP(gic_bmp);
25
26
27 /* ++++++ GIC device-tree retrieval ++++++ */
28
29 static void
30 __setup_pe_rdist(struct dt_prop_iter* prop)
31 {
32     ptr_t base;
33     size_t len, off;
34     int i;
35
36     base = dtprop_reg_nextaddr(prop);
37     len  = dtprop_reg_nextlen(prop);
38
39     assert(len >= NR_CPU * FRAME_SIZE * 2);
40
41     i = 0;
42     base = ioremap(base, len);
43     off = base;
44
45     for (; i < NR_CPU; i++) {
46         gic.pes[i]._rd = (struct gic_rd*) (base + off);
47         off += sizeof(struct gic_rd);
48     }
49 }
50
51 static void
52 __create_its(struct dt_node* gic_node)
53 {
54     struct dt_node* its_node;
55     struct dt_node_iter iter;
56     struct dt_prop_iter prop;
57     ptr_t its_base;
58     size_t its_size;
59
60     dt_begin_find(&iter, gic_node, "its");
61
62     if (!dt_find_next(&iter, (struct dt_node_base**)&its_node)) {
63         return;
64     }
65
66     dt_decode_reg(&prop, its_node, reg);
67
68     its_base = dtprop_reg_nextaddr(&prop);
69     its_size = dtprop_reg_nextlen(&prop);
70
71     assert(its_size >= sizeof(struct gic_its));
72
73     gic.mmrs.its = (struct gic_its*)ioremap(its_base, its_size);
74 }
75
76 static void
77 gic_create_from_dt()
78 {
79     struct dt_node* gic_node;
80     struct dt_node_iter iter;
81     struct dt_prop_iter prop;
82     ptr_t ptr;
83     size_t sz;
84
85     dt_begin_find(&iter, NULL, "interrupt-controller");
86
87     if (!dt_find_next(&iter, (struct dt_node_base**)&gic_node)) {
88         fail("expected /interrupt-controller node, but found none");
89     }
90
91     dt_decode_reg(&prop, gic_node, reg);
92
93     ptr = dtprop_reg_nextaddr(&prop);
94     sz  = dtprop_reg_nextlen(&prop);
95     gic.mmrs.dist_base = (gicreg_t*)ioremap(ptr, sz);
96
97     __setup_pe_rdist(&prop);
98     
99     // ignore cpu_if, as we use sysreg to access them
100     dtprop_next_n(&prop, 2);
101     
102     // ignore vcpu_if, as we dont do any EL2 stuff
103
104     __create_its(gic_node);
105 }
106
107
108 /* ++++++ GIC dirver ++++++ */
109
110 static void
111 __config_interrupt(struct arm_gic* gic, struct gic_distributor* dist, 
112                     struct gic_interrupt* ent)
113 {
114     unsigned int intid_rel;
115     unsigned long trig_index;
116
117     intid_rel = ent->intid - ent->domain->base;
118
119     if (ent->config.class == GIC_LPI) {
120         lpi_entry_t entry = 0;
121
122         entry |= LPI_EN;
123         
124         gic->lpi_tables.property[intid_rel] = entry;
125
126         // clear any pending when we (re-)configuring
127         bitmap_set(gic_bmp, &gic->lpi_tables.pendings, intid_rel, false);
128
129         return;
130     }
131
132
133     bitmap_set(gic_bmp, &dist->group, intid_rel, 0);
134     bitmap_set(gic_bmp, &dist->grpmod, intid_rel, 1);
135
136     trig_index = intid_rel * 2;
137     bitmap_set(gic_bmp, &dist->icfg, trig_index, 0);
138     if (ent->config.trigger == GIC_TRIG_EDGE) {
139         bitmap_set(gic_bmp, &dist->icfg, trig_index + 1, 1);
140     } else {
141         bitmap_set(gic_bmp, &dist->icfg, trig_index + 1, 0);
142     }
143
144     if (gic->nmi_ready) {
145         bitmap_set(gic_bmp, &dist->nmi, intid_rel, ent->config.as_nmi);
146     }
147
148     bitmap_set(gic_bmp, &dist->enable, intid_rel, true);
149 }
150
151 static void
152 __undone_interrupt(struct arm_gic* gic, struct gic_distributor* dist, 
153                     struct gic_interrupt* ent)
154 {
155     unsigned int intid_rel;
156
157     intid_rel = ent->intid - ent->domain->base;
158     
159     if (ent->config.class == GIC_LPI) {
160         gic->lpi_tables.property[intid_rel] = 0;
161
162         // clear any pending when we (re-)configuring
163         bitmap_set(gic_bmp, &gic->lpi_tables.pendings, intid_rel, false);
164
165         return;
166     }
167
168     bitmap_set(gic_bmp, &dist->disable, intid_rel, true);
169     
170     if (gic->nmi_ready) {
171         bitmap_set(gic_bmp, &dist->nmi, intid_rel, false);
172     }
173 }
174
175 static struct gic_idomain*
176 __idomain(int nr_ints, unsigned int base, bool extended)
177 {
178     struct gic_idomain* rec;
179
180     rec = valloc(sizeof(*rec));
181     
182     bitmap_init(gic_bmp, &rec->ivmap, nr_ints);
183     hashtable_init(rec->recs);
184
185     rec->base = base;
186     rec->extended = extended;
187
188     return rec;
189 }
190
191 static inline void
192 __init_distributor(struct gic_distributor* d, 
193                    gicreg_t* base, unsigned int nr_ints)
194 {
195     bitmap_init_ptr(gic_bmp,
196         &d->group, nr_ints, gic_regptr(base, GICD_IGROUPRn));
197
198     bitmap_init_ptr(gic_bmp,
199         &d->grpmod, nr_ints, gic_regptr(base, GICD_IGRPMODRn));
200
201     bitmap_init_ptr(gic_bmp,
202         &d->enable, nr_ints, gic_regptr(base, GICD_ISENABLER));
203     
204     bitmap_init_ptr(gic_bmp,
205         &d->disable, nr_ints, gic_regptr(base, GICD_ICENABLER));
206
207     bitmap_init_ptr(gic_bmp,
208         &d->icfg, nr_ints * 2, gic_regptr(base, GICD_ICFGR));
209     
210     bitmap_init_ptr(gic_bmp,
211         &d->nmi, nr_ints, gic_regptr(base, GICD_INMIR));
212 }
213
214 static inline struct leaflet*
215 __alloc_lpi_table(size_t table_sz)
216 {
217     unsigned int val;
218     struct leaflet* tab;
219
220     val = page_aligned(table_sz);
221     tab = alloc_leaflet(count_order(leaf_count(val)));
222     leaflet_wipe(tab);
223
224     return leaflet_addr(tab);
225 }
226
227 static struct gic_idomain*
228 __deduce_domain(unsigned int intid)
229 {
230     if (intid <= INITID_SGI_END) {
231         return gic.pes[0].idomain.local_ints;
232     }
233
234     if (intid <= INITID_PPI_END) {
235         return gic.pes[0].idomain.local_ints;
236     }
237
238     if (intid <= INITID_SPI_END) {
239         return gic.idomain.spi;
240     }
241
242     if (INITID_ePPI_BASE <= intid && intid <= INITID_ePPI_END) {
243         return gic.pes[0].idomain.eppi;
244     }
245
246     if (INITID_eSPI_BASE <= intid && intid <= INITID_eSPI_END) {
247         return gic.idomain.espi;
248     }
249
250     if (intid >= INITID_LPI_BASE) {
251         return gic.idomain.lpi;
252     }
253
254     return NULL;
255 }
256
257 static struct gic_interrupt*
258 __find_interrupt_record(unsigned int intid)
259 {
260     struct gic_idomain* domain;
261
262     domain = __deduce_domain(intid);
263     
264     if (!domain) {
265         return NULL;
266     }
267
268     struct gic_interrupt *pos, *n;
269
270     hashtable_hash_foreach(domain->recs, intid, pos, n, node)
271     {
272         if (pos->intid == intid) {
273             return pos;
274         }
275     }
276
277     return NULL;
278 }
279
280 static inline struct gic_interrupt*
281 __register_interrupt(struct gic_idomain* domain, 
282                             unsigned int intid, struct gic_int_param* param)
283 {
284     struct gic_interrupt* interrupt;
285
286     interrupt = valloc(sizeof(*interrupt));
287     interrupt->config = (struct gic_intcfg) {
288         .class   = param->class,
289         .trigger = param->trigger,
290         .group   = param->group,
291         .as_nmi  = param->as_nmi
292     };
293
294     interrupt->intid = intid;
295     interrupt->domain = domain;
296
297     hashtable_hash_in(domain->recs, &interrupt->node, intid);
298
299     return interrupt;
300 }
301
302 static struct gic_distributor*
303 __attached_distributor(int cpu, struct gic_interrupt* ent)
304 {
305     enum gic_int_type iclass;
306
307     iclass = ent->config.class;
308
309     if (iclass == GIC_PPI || iclass == GIC_SGI) {
310         return &gic.pes[cpu].rdist;
311     }
312     
313     if (ent->domain->extended) {
314         return &gic.dist_e;
315     }
316     
317     return &gic.dist;
318 }
319
320 static void
321 gic_configure_icc()
322 {
323     reg_t v;
324
325     v =
326     sysreg_flagging(ICC_SRE_EL1, 
327                     ICC_SRE_SRE | ICC_SRE_DFB | ICC_SRE_DIB, 
328                     0);
329     
330
331     v = 
332     sysreg_flagging(ICC_CTLR_EL1,
333                     ICC_CTRL_CBPR,
334                     ICC_CTRL_EOImode | ICC_CTRL_PMHE);
335
336     // disable all group 0 interrupts as those are meant for EL3
337     v=
338     sysreg_flagging(ICC_IGRPEN0_EL1, 0, ICC_IGRPEN_ENABLE);
339
340     // enable all group 1 interrupts, we'll stick with EL1_NS
341     v=
342     sysreg_flagging(ICC_IGRPEN1_EL1, ICC_IGRPEN_ENABLE, 0);
343 }
344
345 static void
346 gic_configure_global(struct arm_gic* gic)
347 {
348     gicreg64_t reg;
349     unsigned int val, max_nr_spi;
350
351     reg = gic->mmrs.dist_base[GICD_TYPER];
352     
353     // check if eSPI supported
354     gic->has_espi = (reg & GICD_TYPER_ESPI);
355     if (gic->has_espi) {
356         val = BITS_GET(reg, GICD_TYPER_nESPI);
357         gic->espi_nr = 32 * (val + 1);
358     }
359
360     // Parse IDbits
361     val = BITS_GET(reg, GICD_TYPER_IDbits);
362     gic->max_intid = 1 << (val + 1) - 1;
363
364     // LPI is supported
365     if (val + 1 >= 14) {
366         val = BITS_GET(reg, GICD_TYPER_nLPI);
367         if (val) {
368             gic->lpi_nr = 1 << (val + 1);
369         }
370         else {
371             gic->lpi_nr = gic->max_intid - INITID_LPI_BASE + 1;
372         }
373     }
374
375     // check if SPI supported
376     val = BITS_GET(reg, GICD_TYPER_nSPI);
377     if (val) {
378         max_nr_spi = 32 * (val + 1);
379         gic->spi_nr = MIN(max_nr_spi, INITID_SPEC_BASE);
380         gic->spi_nr -= INITID_SPI_BASE;
381     } else {
382         gic->spi_nr = 0;
383     }
384
385     gic->nmi_ready = (reg & GICD_TYPER_NMI);
386     gic->msi_via_spi = (reg & GICD_TYPER_MBIS);
387
388     __init_distributor(&gic->dist, gic->mmrs.dist_base, gic->spi_nr);
389     __init_distributor(&gic->dist_e, gic->mmrs.dist_base, gic->espi_nr);
390
391
392     if (gic->spi_nr) {
393         gic->idomain.spi  = __idomain(gic->spi_nr, INITID_SPI_BASE, false);
394     }
395     if (gic->espi_nr) {
396         gic->idomain.espi = __idomain(gic->espi_nr, INITID_eSPI_BASE, true);
397     }
398     if (gic->lpi_nr) {
399         gic->idomain.lpi  = __idomain(gic->lpi_nr, INITID_LPI_BASE, false);
400     }
401
402     gic->lpi_tables.prop = __alloc_lpi_table(gic->lpi_nr);
403     gic->lpi_tables.pend = __alloc_lpi_table(gic->lpi_nr / 8);
404
405     bitmap_init_ptr(gic_bmp, 
406         &gic->lpi_tables.pendings, gic->lpi_nr, gic->lpi_tables.pend);
407 }
408
409 static void
410 gic_configure_pe(struct arm_gic* gic, struct gic_pe* pe)
411 {
412     unsigned int nr_local_ints;
413     gicreg64_t reg;
414
415     reg = gic_reg64(pe->_rd, GICR_TYPER);
416
417     pe->affinity = BITS_GET(reg, GICR_TYPER_AffVal);
418     pe->ppi_nr   = INITID_PPI_BASE;
419     switch (BITS_GET(reg, GICR_TYPER_PPInum))
420     {
421         case 1:
422             pe->ppi_nr += 1088 - INITID_ePPI_BASE;
423             pe->eppi_ready = true;
424             break;
425         case 2:
426             pe->ppi_nr += 1120 - INITID_ePPI_BASE;
427             pe->eppi_ready = true;
428             break;
429     }
430
431     nr_local_ints = pe->ppi_nr + INITID_PPI_BASE;
432     
433     pe->idomain.local_ints = __idomain(32, 0, false);
434     pe->idomain.eppi = __idomain(nr_local_ints - 32, INITID_ePPI_BASE, true);
435
436     __init_distributor(&pe->rdist, pe->_rd->sgi_base, nr_local_ints);
437
438     reg = 0;
439     BITS_SET(reg, GICR_BASER_PAddr, gic->lpi_tables.prop);
440     BITS_SET(reg, GICR_BASER_Share, 0b01);
441     BITS_SET(reg, GICR_PROPBASER_IDbits, ilog2(gic->max_intid));
442     pe->_rd->sgi_base[GICR_PROPBASER] = reg;
443
444     reg  = 0;
445     reg |= GICR_PENDBASER_PTZ;
446     BITS_SET(reg, GICR_BASER_PAddr, gic->lpi_tables.pend);
447     BITS_SET(reg, GICR_BASER_Share, 0b01);
448     pe->_rd->sgi_base[GICR_PENDBASER] = reg;
449 }
450
451 struct gic_interrupt*
452 aa64_isrm_ivalloc(struct gic_int_param* param, isr_cb handler)
453 {
454     unsigned int iv;
455     struct gic_idomain* domain;
456     int cpu;
457
458     cpu = param->cpu_id;
459
460     assert(cpu == 0);
461
462     switch (param->class)
463     {
464     case GIC_PPI:
465         if (!param->ext_range) {
466             domain = gic.pes[cpu].idomain.local_ints;
467         }
468         else {
469             domain = gic.pes[cpu].idomain.eppi;
470         }
471         break;
472
473     case GIC_SGI:
474         domain = gic.pes[cpu].idomain.local_ints;
475         break;
476
477     case GIC_SPI:
478         if (!param->ext_range) {
479             assert(gic.spi_nr > 0);
480             domain = gic.idomain.spi;
481         } 
482         else {
483             assert(gic.has_espi);
484             domain = gic.idomain.espi;
485         }
486         break;
487
488     case GIC_LPI:
489         assert(gic.lpi_ready);
490         domain = gic.idomain.lpi;
491         break;
492         
493     default:
494         fail("unknown interrupt class");
495         break;
496     }
497
498     if (!bitmap_alloc(gic_bmp, &domain->ivmap, 0, &iv)) {
499         FATAL("out of usable iv for class=%d", param->class);
500     }
501
502     iv += domain->base;
503
504     if (param->class == GIC_SPI && !param->ext_range && iv >= INITID_ePPI_BASE) 
505     {
506         WARN("PPI vector=%d falls in extended range, while not requested.", iv);
507         param->ext_range = true;
508     }
509
510     struct gic_interrupt* ent;
511     struct gic_distributor* dist;
512
513     ent  = __register_interrupt(domain, iv, param);
514     dist = __attached_distributor(cpu, ent);
515     
516     __config_interrupt(&gic, dist, ent);
517
518     ent->handler = handler;
519
520     return iv;
521 }
522
523 static void
524 gic_update_active()
525 {
526     reg_t val;
527     unsigned int intid;
528     struct gic_interrupt* intr;
529     struct gic_pe* pe;
530
531     pe  = &gic.pes[0];
532     val = read_sysreg(ICC_IAR1_EL1);
533     intid = (unsigned int)val & ((1 << 24) - 1);
534
535     if (check_special_intid(intid)) {
536         return;
537     }
538
539     intr = __find_interrupt_record(intid);
540     pe->active = intr;
541     pe->iar_val = val;
542 }
543
544 static void
545 gic_signal_eoi()
546 {
547     struct gic_pe* pe;
548
549     pe  = &gic.pes[0];
550     if (!pe->active) {
551         return;
552     }
553
554     pe->active = NULL;
555     set_sysreg(ICC_EOIR1_EL1, pe->iar_val);
556 }
557
558 void
559 isrm_init()
560 {
561     // nothing to do
562 }
563
564 void
565 isrm_ivfree(int iv)
566 {
567     struct gic_interrupt* ent;
568     struct gic_distributor* dist;
569     
570     ent  = __find_interrupt_record(iv);
571     if (!ent) {
572         return;
573     }
574
575     dist = __attached_distributor(0, ent);
576     __undone_interrupt(&gic, dist, ent);
577
578     hlist_delete(&ent->node);
579     vfree(ent);
580 }
581
582 int
583 isrm_ivosalloc(isr_cb handler)
584 {
585     return isrm_ivexalloc(handler);
586 }
587
588 int
589 isrm_ivexalloc(isr_cb handler)
590 {
591     struct gic_int_param param;
592     struct gic_interrupt* intr;
593
594     param = (struct gic_int_param) {
595         .class = GIC_SPI,
596         .group = GIC_G1NS,
597         .trigger = GIC_TRIG_EDGE,
598     };
599
600     intr = aa64_isrm_ivalloc(&param, handler);
601     
602     return intr->intid;
603 }
604
605 int
606 isrm_bindirq(int irq, isr_cb irq_handler)
607 {
608     // Not supported
609 }
610
611 void
612 isrm_bindiv(int iv, isr_cb handler)
613 {
614     // Not supported
615 }
616
617 isr_cb
618 isrm_get(int iv)
619 {
620     struct gic_interrupt* intr;
621
622     intr = __find_interrupt_record(iv);
623     if (!intr) {
624         return NULL;
625     }
626
627     return intr->handler;
628 }
629
630 ptr_t
631 isrm_get_payload(const struct hart_state* state)
632 {
633     struct gic_interrupt* active;
634
635     active = gic.pes[0].active;
636     assert(active);
637
638     return active->handler;
639 }
640
641 void
642 isrm_set_payload(int iv, ptr_t payload)
643 {
644     struct gic_interrupt* intr;
645
646     intr = __find_interrupt_record(iv);
647     if (!intr) {
648         return NULL;
649     }
650
651     intr->payload = payload;
652 }
653
654 void
655 isrm_irq_attach(int irq, int iv, cpu_t dest, u32_t flags)
656 {
657     // Not supported
658 }
659
660 void
661 isrm_notify_eoi(cpu_t id, int iv)
662 {
663     struct gic_interrupt* active;
664
665     active = gic.pes[0].active;
666     assert(active);
667 }
668
669 void
670 isrm_notify_eos(cpu_t id)
671 {
672     isrm_notify_eoi(id, 0);
673 }
674
675
676 static void
677 gic_init()
678 {
679     memset(&gic, 0, sizeof(gic));
680
681     gic_create_from_dt();
682
683     // configure the system interfaces
684     gic_configure_icc();
685
686     // configure global distributor
687     gic_configure_global(&gic);
688     
689     // configure per-PE local distributor (redistributor)
690     for (int i = 0; i < NR_CPU; i++)
691     {
692         gic_configure_pe(&gic, &gic.pes[i]);
693     }
694 }
695
696 static struct device_def dev_arm_gic = {
697     .name = "ARM Generic Interrupt Controller",
698     .class = DEVCLASS(DEVIF_SOC, DEVFN_CFG, DEV_INTC),
699     .init = gic_init
700 };
701 EXPORT_DEVICE(arm_gic, &dev_arm_gic, load_sysconf);