1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "hw/sysbus.h"
23#include "gic_internal.h"
24#include "qapi/error.h"
25#include "qom/cpu.h"
26#include "qemu/log.h"
27#include "trace.h"
28
29#include "hw/fdt_generic_util.h"
30
31#include "hw/guest/linux.h"
32
33
34
35#ifdef DEBUG_GIC
36#define DPRINTF(fmt, ...) \
37do { fprintf(stderr, "arm_gic: " fmt , ## __VA_ARGS__); } while (0)
38#else
39#define DPRINTF(fmt, ...) do {} while(0)
40#endif
41
42#define IDLE_PRIORITY 0xff
43
44static const uint8_t gic_id_11mpcore[] = {
45 0x00, 0x00, 0x00, 0x00, 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1
46};
47
48static const uint8_t gic_id_gicv1[] = {
49 0x04, 0x00, 0x00, 0x00, 0x90, 0xb3, 0x1b, 0x00, 0x0d, 0xf0, 0x05, 0xb1
50};
51
52static const uint8_t gic_id_gicv2[] = {
53 0x04, 0x00, 0x00, 0x00, 0x90, 0xb4, 0x2b, 0x00, 0x0d, 0xf0, 0x05, 0xb1
54};
55
56#define NUM_CPU(s) ((s)->num_cpu)
57
58#define GICH_LRN_STATE_INVALID 0
59#define GICH_LRN_STATE_PENDING 1
60#define GICH_LRN_STATE_ACTIVE 2
61
62static inline void gic_dump_lrs(GICState *s, const char *prefix)
63{
64 unsigned int i;
65 unsigned int lr;
66 unsigned int apr;
67 uint32_t lr_comb_state = 0;
68
69 for (i = 0; i < s->num_cpu; i++) {
70 qemu_log("%s: CPU%d HCR=%x ", prefix, i, s->gich.hcr[i]);
71 for (lr = 0; lr < GICV_NR_LR; lr++) {
72 int state = extract32(s->gich.lr[i][lr], 28, 2);
73 lr_comb_state |= s->gich.lr[i][lr];
74 qemu_log("LR[%d]=%x %c%c ", lr, s->gich.lr[i][lr],
75 state & GICH_LRN_STATE_PENDING ? 'P' : '.',
76 state & GICH_LRN_STATE_ACTIVE ? 'A' : '.');
77 }
78 for (apr = 0; apr < GIC_NR_APRS; apr++) {
79 qemu_log("APR[%d]=%x ", apr, s->apr[apr][i]);
80 }
81 qemu_log("GICH.APR=%x\n", s->gich.apr[i]);
82 if (extract32(lr_comb_state, 28, 2) == 0 && s->gich.apr[i]) {
83 qemu_log("BAD! no active LR but GICH.APR!\n");
84 }
85 }
86}
87
88static inline int gic_get_current_cpu(GICState *s)
89{
90 if (s->num_cpu > 1) {
91 return current_cpu->cpu_index % 4;
92 }
93 return 0;
94}
95
96static bool is_apr(GICState *s, unsigned int cpu, unsigned int prio)
97{
98 int regnum = prio / 32;
99 int regbit = prio % 32;
100
101 if (regnum >= ARRAY_SIZE(s->apr)) printf("prio=%d\n", prio);
102 assert(regnum < ARRAY_SIZE(s->apr));
103 return s->apr[regnum][cpu] & (1 << regbit);
104}
105
106static void set_apr(GICState *s, unsigned int cpu, unsigned int prio)
107{
108 int regnum = prio / 32;
109 int regbit = prio % 32;
110
111 if (regnum >= ARRAY_SIZE(s->apr)) printf("prio=%d\n", prio);
112 assert(regnum < ARRAY_SIZE(s->apr));
113 assert(!is_apr(s, cpu, prio));
114 s->apr[regnum][cpu] |= 1 << regbit;
115}
116
117static void clear_apr(GICState *s, unsigned int cpu, unsigned int prio)
118{
119 int regnum = prio / 32;
120 int regbit = prio % 32;
121
122 if (regnum >= ARRAY_SIZE(s->apr)) printf("prio=%d\n", prio);
123 assert(regnum < ARRAY_SIZE(s->apr));
124 assert(is_apr(s, cpu, prio));
125 if (s->apr[regnum][cpu] & ((1 << regbit) - 1)) {
126 qemu_log("cpu=%d completed APR not lowest! prio=%d\n", cpu, prio);
127 gic_dump_lrs(s, "BAD");
128 } else {
129 int i;
130 i = regnum;
131 while (--i > 0) {
132 if (s->apr[i][cpu]) {
133 qemu_log("cpu=%d completed APR not lowest! %d\n", cpu, prio);
134 gic_dump_lrs(s, "BAD");
135 }
136 }
137 }
138 s->apr[regnum][cpu] &= ~(1 << regbit);
139}
140
141#define GICH_LRN_STATE_INVALID 0
142#define GICH_LRN_STATE_PENDING 1
143#define GICH_LRN_STATE_ACTIVE 2
144static void gicv_update_cpu(GICState *s, int vcpu)
145{
146 int cpu = vcpu + GIC_N_REALCPU;
147 unsigned int i;
148 unsigned int best_prio = 0x100;
149 unsigned int best_irq = 1023;
150 unsigned int best_lrn = 0;
151 unsigned int allstate = 0;
152 int nr_valid = 0;
153 bool level = 0;
154 bool maint_irq = 0;
155
156 if (!(s->gich.hcr[vcpu] & 1)) {
157 goto done;
158 }
159
160 s->current_pending[cpu] = 1023;
161 s->gich.pending_prio[vcpu] = 0x100;
162 s->gich.misr[vcpu] = 0;
163 s->gich.eisr[vcpu] = 0;
164 s->gich.elrsr[vcpu] = 0;
165
166 for (i = 0; i < ARRAY_SIZE(s->gich.lr[vcpu]); i++) {
167 unsigned int state;
168 unsigned int prio;
169 unsigned int vid;
170 unsigned int hw;
171 unsigned int eoi;
172
173 state = extract32(s->gich.lr[vcpu][i], 28, 2);
174 vid = extract32(s->gich.lr[vcpu][i], 0, 10);
175 prio = extract32(s->gich.lr[vcpu][i], 23, 6);
176 hw = extract32(s->gich.lr[vcpu][i], 31, 1);
177 eoi = extract32(s->gich.lr[vcpu][i], 19, 1);
178
179 if (state == 0 && hw == 0 && eoi) {
180 s->gich.eisr[vcpu] |= 1ULL << i;
181 }
182
183 if (state == 0 && (hw || !eoi)) {
184 s->gich.elrsr[vcpu] |= 1ULL << i;
185 }
186
187 allstate |= state;
188
189 if (state) {
190 nr_valid++;
191 }
192
193 if (state != GICH_LRN_STATE_PENDING) {
194 continue;
195 }
196
197#if 0
198 if (s->gich.apr[vcpu] & (1 << (prio >> 3))) {
199 continue;
200 }
201#endif
202 if (prio < best_prio) {
203 best_prio = prio;
204 best_irq = vid;
205 best_lrn = i;
206 }
207 }
208
209 if (best_prio < s->priority_mask[cpu]) {
210
211 s->current_pending[cpu] = best_irq;
212 s->gich.pending_lrn[vcpu] = best_lrn;
213 s->gich.pending_prio[vcpu] = best_prio;
214 if (best_prio < s->running_priority[cpu]) {
215 level = 1;
216 }
217 }
218
219 s->gich.misr[vcpu] |= s->gich.eisr[vcpu] != 0;
220 s->gich.misr[vcpu] |= (nr_valid > 1 ? 0 : 1 << 1) & s->gich.hcr[vcpu];
221 s->gich.misr[vcpu] |= ((allstate & 1) << 3) & s->gich.hcr[vcpu];
222
223 level &= s->gich.hcr[vcpu] & 1;
224 assert(!(level && !(s->gicc_ctrl[cpu].enable_grp[1])));
225
226 maint_irq = s->gich.misr[vcpu] && (s->gich.hcr[vcpu] & 1);
227done:
228
229 qemu_set_irq(s->parent_irq[cpu], level);
230 qemu_set_irq(s->maint[vcpu], maint_irq);
231}
232
233static void gicv_update(GICState *s)
234{
235 unsigned int i;
236
237 for (i = 0; i < s->num_cpu; i++) {
238 gicv_update_cpu(s, i);
239 }
240}
241
242
243
244void gic_update(GICState *s)
245{
246 int best_irq;
247 int best_prio;
248 int irq;
249 int level;
250 int cpu;
251 int cm;
252
253 for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
254 bool cpu_irq = false;
255 bool cpu_fiq = false;
256 bool next_grp0;
257
258 cm = 1 << cpu;
259 s->current_pending[cpu] = 1023;
260 best_prio = 0x100;
261 best_irq = 1023;
262 for (irq = 0; irq < s->num_irq; irq++) {
263 if (GIC_TEST_ENABLED(irq, cm) && gic_test_pending(s, irq, cm) &&
264 (irq < GIC_INTERNAL || GIC_TARGET(irq) & cm)) {
265 if (GIC_GET_PRIORITY(irq, cpu) < best_prio &&
266 !is_apr(s, cpu, GIC_GET_PRIORITY(irq, cpu))) {
267 best_prio = GIC_GET_PRIORITY(irq, cpu);
268 best_irq = irq;
269 }
270 }
271 }
272 level = 0;
273 if (best_prio < s->priority_mask[cpu]) {
274 s->current_pending[cpu] = best_irq;
275 if (best_prio < s->running_priority[cpu]) {
276 DPRINTF("Raised pending IRQ %d (cpu %d)\n", best_irq, cpu);
277 level = 1;
278 }
279 }
280
281 next_grp0 = GIC_GROUP(best_irq) == 0;
282 if (level) {
283 if (next_grp0 && s->gicc_ctrl[cpu].fiq_en) {
284 if (s->gicc_ctrl[cpu].enable_grp[0]) {
285 cpu_fiq = true;
286 }
287 } else {
288 if ((next_grp0 && s->gicc_ctrl[cpu].enable_grp[0])
289 || (!next_grp0 && s->gicc_ctrl[cpu].enable_grp[1])) {
290 cpu_irq = true;
291 }
292 }
293 }
294 qemu_set_irq(s->parent_fiq[cpu], cpu_fiq);
295 qemu_set_irq(s->parent_irq[cpu], cpu_irq);
296 }
297 gicv_update(s);
298}
299
300void gic_set_pending_private(GICState *s, int cpu, int irq)
301{
302 int cm = 1 << cpu;
303
304 if (gic_test_pending(s, irq, cm)) {
305 return;
306 }
307
308 DPRINTF("Set %d pending cpu %d\n", irq, cpu);
309 GIC_SET_PENDING(irq, cm);
310 gic_update(s);
311}
312
313static void gic_set_irq_11mpcore(GICState *s, int irq, int level,
314 int cm, int target)
315{
316 if (level) {
317 GIC_SET_LEVEL(irq, cm);
318 if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
319 DPRINTF("Set %d pending mask %x\n", irq, target);
320 GIC_SET_PENDING(irq, target);
321 }
322 } else {
323 GIC_CLEAR_LEVEL(irq, cm);
324 }
325}
326
327static void gic_set_irq_nvic(GICState *s, int irq, int level,
328 int cm, int target)
329{
330 if (level) {
331 GIC_SET_LEVEL(irq, cm);
332 GIC_SET_PENDING(irq, target);
333 } else {
334 GIC_CLEAR_LEVEL(irq, cm);
335 }
336}
337
338static void gic_set_irq_generic(GICState *s, int irq, int level,
339 int cm, int target)
340{
341 if (level) {
342 GIC_SET_LEVEL(irq, cm);
343 DPRINTF("Set %d pending mask %x\n", irq, target);
344 if (GIC_TEST_EDGE_TRIGGER(irq)) {
345 GIC_SET_PENDING(irq, target);
346 }
347 } else {
348 GIC_CLEAR_LEVEL(irq, cm);
349 }
350}
351
352
353static void gic_set_irq(void *opaque, int irq, int level)
354{
355
356
357
358
359
360
361 GICState *s = (GICState *)opaque;
362 int cm, target;
363 if (irq < (s->num_irq - GIC_INTERNAL)) {
364
365 cm = ALL_CPU_MASK;
366 irq += GIC_INTERNAL;
367 target = GIC_TARGET(irq);
368 } else {
369 int cpu;
370 irq -= (s->num_irq - GIC_INTERNAL);
371 cpu = irq / GIC_INTERNAL;
372 irq %= GIC_INTERNAL;
373 cm = 1 << cpu;
374 target = cm;
375 }
376
377 assert(irq >= GIC_NR_SGIS);
378
379 if (level == GIC_TEST_LEVEL(irq, cm)) {
380 return;
381 }
382
383 if (s->revision == REV_11MPCORE) {
384 gic_set_irq_11mpcore(s, irq, level, cm, target);
385 } else if (s->revision == REV_NVIC) {
386 gic_set_irq_nvic(s, irq, level, cm, target);
387 } else {
388 gic_set_irq_generic(s, irq, level, cm, target);
389 }
390
391 gic_update(s);
392}
393
394static void gic_set_irq_cb(void *opaque, int irq, int level)
395{
396 ARMGICClass *agc = ARM_GIC_GET_CLASS((Object *)opaque);
397
398 agc->irq_handler(opaque, irq, level);
399}
400
401static void gic_set_running_irq(GICState *s, int cpu, int irq)
402{
403 s->running_irq[cpu] = irq;
404 if (irq == 1023) {
405 s->running_priority[cpu] = 0x100;
406 } else {
407 s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
408 }
409 gic_update(s);
410}
411
412static uint32_t gic_acknowledge_virq(GICState *s, int cpu)
413{
414 uint32_t t, cpuid = 0;
415 int vcpu = cpu - GIC_N_REALCPU;
416 bool hw;
417
418 if (s->gich.pending_prio[vcpu] == 0x100) {
419 return 1023;
420 }
421 s->running_priority[cpu] = s->gich.pending_prio[vcpu];
422 s->running_irq[cpu] = s->current_pending[cpu];
423
424 t = s->gich.lr[vcpu][s->gich.pending_lrn[vcpu]];
425 s->gich.lr[vcpu][s->gich.pending_lrn[vcpu]] = deposit32(t, 28, 2, 2);
426
427 hw = extract32(t, 31, 1);
428 if (!hw) {
429 cpuid = extract32(t, 10, 3);
430 }
431
432 gicv_update(s);
433
434 s->gich.apr[vcpu] |= 1 << (s->running_priority[cpu] >> 3);
435#if 0
436 if (s->running_irq[cpu] == 27) {
437 qemu_log("Vack CPU%d %d\n", cpu, s->running_irq[cpu]);
438 gic_dump_lrs(s, "Vack");
439 }
440#endif
441 return s->running_irq[cpu] | (cpuid << 10);
442}
443
444uint32_t gic_acknowledge_irq(GICState *s, int cpu, bool secure)
445{
446 int ret, irq, src;
447 int cm = 1 << cpu;
448 bool is_grp0;
449
450 irq = s->current_pending[cpu];
451 is_grp0 = GIC_GROUP(irq) == 0;
452
453 if (irq == 1023
454 || GIC_GET_PRIORITY(irq, cpu) >= s->running_priority[cpu]) {
455 DPRINTF("ACK no pending IRQ\n");
456 return 1023;
457 }
458
459 if ((is_grp0 && !s->gicc_ctrl[cpu].enable_grp[0])
460 || (!is_grp0 && !s->gicc_ctrl[cpu].enable_grp[1])
461 || (is_grp0 && !secure)) {
462 return 1023;
463 }
464
465 if (!is_grp0 && secure && !s->gicc_ctrl[cpu].ack_ctl) {
466 return 1022;
467 }
468
469 s->last_active[irq][cpu] = s->running_irq[cpu];
470
471 if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
472
473
474
475 GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm);
476 ret = irq;
477 } else {
478 if (irq < GIC_NR_SGIS) {
479
480
481
482
483 assert(s->sgi_pending[irq][cpu] != 0);
484 src = ctz32(s->sgi_pending[irq][cpu]);
485 s->sgi_pending[irq][cpu] &= ~(1 << src);
486 if (s->sgi_pending[irq][cpu] == 0) {
487 GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm);
488 }
489 ret = irq | ((src & 0x7) << 10);
490 } else {
491
492
493
494
495 GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm);
496 ret = irq;
497 }
498 }
499
500 gic_set_running_irq(s, cpu, irq);
501 set_apr(s, cpu, s->running_priority[cpu]);
502#if 0
503 if (irq == 27) {
504 qemu_log("ack CPU%d %d\n", cpu, irq);
505
506 }
507 DPRINTF("ACK %d\n", irq);
508#endif
509 return ret;
510}
511
512void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val)
513{
514 if (irq < GIC_INTERNAL) {
515 s->priority1[irq][cpu] = val;
516 } else {
517 s->priority2[(irq) - GIC_INTERNAL] = val;
518 }
519}
520
521static void gic_complete_irq_force(GICState *s, int cpu, int irq, bool force, bool sec)
522{
523 int update = 0;
524 int cm = 1 << cpu;
525 bool eoirmode = s->gicc_ctrl[cpu].eoirmode_ns;
526
527 if (sec) {
528 eoirmode = s->gicc_ctrl[cpu].eoirmode;
529 }
530
531 if (force) {
532 eoirmode = false;
533 }
534
535 if (irq >= s->num_irq) {
536
537
538
539
540
541
542
543
544 return;
545 }
546 if (s->running_irq[cpu] == 1023) {
547 int i;
548 for (i = 0; i < GIC_NR_APRS; i++) {
549 assert(s->apr[i][cpu] == 0);
550 }
551 return;
552 }
553
554 if (eoirmode) {
555 gic_update(s);
556 return;
557 }
558
559 if (s->revision == REV_11MPCORE) {
560
561
562 if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
563 && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
564 DPRINTF("Set %d pending mask %x\n", irq, cm);
565 GIC_SET_PENDING(irq, cm);
566 update = 1;
567 }
568 } else if (s->revision == REV_NVIC) {
569 if (GIC_TEST_LEVEL(irq, cm)) {
570 DPRINTF("Set nvic %d pending mask %x\n", irq, cm);
571 GIC_SET_PENDING(irq, cm);
572 }
573 }
574
575#if 0
576 if (irq == 27) {
577 qemu_log("HW DIR irq=%d\n", irq);
578 }
579#endif
580
581 if (irq != s->running_irq[cpu]) {
582
583 int tmp = s->running_irq[cpu];
584 if (irq == 27)
585 qemu_log("compl not running irq=%d running=%d %x %x %x\n", irq, s->running_irq[cpu],
586 s->apr[0][cpu], s->apr[1][cpu], s->apr[2][cpu]);
587 while (s->last_active[tmp][cpu] != 1023) {
588 if (s->last_active[tmp][cpu] == irq) {
589 if (is_apr(s, cpu, GIC_GET_PRIORITY(s->last_active[tmp][cpu], cpu)))
590 clear_apr(s, cpu, GIC_GET_PRIORITY(s->last_active[tmp][cpu], cpu));
591 s->last_active[tmp][cpu] = s->last_active[irq][cpu];
592 break;
593 }
594 tmp = s->last_active[tmp][cpu];
595 }
596 if (update) {
597 gic_update(s);
598 }
599 } else {
600
601 clear_apr(s, cpu, s->running_priority[cpu]);
602 gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
603 }
604 if (irq == 27 && s->running_irq[cpu] == 27) {
605 qemu_log("BAD: DIR irq=%d running IRQ=%d\n", irq, s->running_irq[cpu]);
606 }
607}
608
609void gic_complete_irq(GICState *s, int cpu, int irq, bool secure)
610{
611 gic_complete_irq_force(s, cpu, irq, false, secure);
612#if 0
613 if (irq == 27) {
614 qemu_log("complete CPU%d %d\n", cpu, irq);
615
616 }
617#endif
618}
619
620static void gic_complete_virq(GICState *s, int cpu, int irq)
621{
622 int vcpu = cpu - GIC_N_REALCPU;
623 bool eoirmode = s->gicc_ctrl[cpu].eoirmode_ns;
624 unsigned int i;
625 unsigned int state;
626 unsigned int vid;
627 unsigned int pid;
628 bool hw;
629 bool eoi;
630
631 for (i = 0; i < ARRAY_SIZE(s->gich.lr[vcpu]); i++) {
632 state = extract32(s->gich.lr[vcpu][i], 28, 2);
633 if (state == GICH_LRN_STATE_INVALID) {
634 continue;
635 }
636
637 vid = extract32(s->gich.lr[vcpu][i], 0, 10);
638 pid = extract32(s->gich.lr[vcpu][i], 10, 10);
639 eoi = extract32(s->gich.lr[vcpu][i], 19, 1);
640 hw = extract32(s->gich.lr[vcpu][i], 31, 1);
641 if (vid == irq) {
642 break;
643 }
644 }
645
646 if (i == ARRAY_SIZE(s->gich.lr[vcpu])) {
647 qemu_log("%s:%d BAD?\n", __func__, __LINE__);
648 return;
649 }
650
651 if (!hw && eoi) {
652 qemu_log("EOI! maint! %d\n", irq);
653 s->gich.eisr[vcpu] |= 1ULL << irq;
654 }
655
656 if (eoirmode == 0) {
657
658 s->gich.lr[vcpu][i] = deposit32(s->gich.lr[vcpu][i], 29, 1, 0);
659 if (hw) {
660
661 gic_complete_irq_force(s, vcpu, pid, true, false);
662 }
663 } else {
664 qemu_log_mask(LOG_UNIMP, "gic: unimplemted CTLR.EOIRMODE = 1\n");
665 }
666 s->gich.apr[vcpu] &= ~(1 << (s->running_priority[cpu] >> 3));
667 s->running_priority[cpu] = 0x100;
668 s->running_irq[cpu] = 1023;
669#if 0
670 if (irq == 27) {
671 qemu_log("Vcomplete CPU%d %d\n", cpu, irq);
672 gic_dump_lrs(s, "Vcomplete");
673 }
674#endif
675}
676
677static uint32_t gic_dist_readb(void *opaque, hwaddr offset, bool secure)
678{
679 GICState *s = (GICState *)opaque;
680 uint32_t res;
681 int irq;
682 int i;
683 int cpu;
684 int cm;
685 int mask;
686
687 cpu = gic_get_current_cpu(s);
688 cm = 1 << cpu;
689 if (offset < 0x100) {
690 if (offset == 0) {
691 if (secure) {
692 return (s->enabled << 1) | s->enabled_grp0;
693 } else {
694 return s->enabled;
695 }
696 }
697 if (offset == 4)
698 return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
699 if (offset < 0x08)
700 return 0;
701 if (offset >= 0x80) {
702 if (secure && s->revision >= 2) {
703 unsigned int irq = (offset - 0x80) * 8;
704 res = 0;
705 for (i = 0; i < 8; i++) {
706 res |= s->irq_state[irq + i].group << i;
707 }
708 return res;
709 }
710
711 return 0;
712 }
713 goto bad_reg;
714 } else if (offset < 0x200) {
715
716 if (offset < 0x180)
717 irq = (offset - 0x100) * 8;
718 else
719 irq = (offset - 0x180) * 8;
720 irq += GIC_BASE_IRQ;
721 if (irq >= s->num_irq)
722 goto bad_reg;
723 res = 0;
724 for (i = 0; i < 8; i++) {
725 if (GIC_TEST_ENABLED(irq + i, cm)) {
726 res |= (1 << i);
727 }
728 }
729 } else if (offset < 0x300) {
730
731 if (offset < 0x280)
732 irq = (offset - 0x200) * 8;
733 else
734 irq = (offset - 0x280) * 8;
735 irq += GIC_BASE_IRQ;
736 if (irq >= s->num_irq)
737 goto bad_reg;
738 res = 0;
739 mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK;
740 for (i = 0; i < 8; i++) {
741 if (gic_test_pending(s, irq + i, mask)) {
742 res |= (1 << i);
743 }
744 }
745 } else if (offset < 0x400) {
746
747 irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
748 if (irq >= s->num_irq)
749 goto bad_reg;
750 res = 0;
751 mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK;
752 for (i = 0; i < 8; i++) {
753 if (GIC_TEST_ACTIVE(irq + i, mask)) {
754 res |= (1 << i);
755 }
756 }
757 } else if (offset < 0x800) {
758
759 irq = (offset - 0x400) + GIC_BASE_IRQ;
760 if (irq >= s->num_irq)
761 goto bad_reg;
762 res = GIC_GET_PRIORITY(irq, cpu);
763 } else if (offset < 0xc00) {
764
765 if (s->num_cpu == 1 && s->revision != REV_11MPCORE) {
766
767 res = 0;
768 } else {
769 irq = (offset - 0x800) + GIC_BASE_IRQ;
770 if (irq >= s->num_irq) {
771 goto bad_reg;
772 }
773 if (irq < GIC_INTERNAL) {
774 res = cm;
775 } else {
776 res = GIC_TARGET(irq);
777 }
778 }
779 } else if (offset < 0xf00) {
780
781 irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
782 if (irq >= s->num_irq)
783 goto bad_reg;
784 res = 0;
785 for (i = 0; i < 4; i++) {
786 if (GIC_TEST_MODEL(irq + i))
787 res |= (1 << (i * 2));
788 if (GIC_TEST_EDGE_TRIGGER(irq + i))
789 res |= (2 << (i * 2));
790 }
791 } else if (offset < 0xf10) {
792 goto bad_reg;
793 } else if (offset < 0xf30) {
794 if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
795 goto bad_reg;
796 }
797
798 if (offset < 0xf20) {
799
800 irq = (offset - 0xf10);
801 } else {
802 irq = (offset - 0xf20);
803
804 }
805
806 res = s->sgi_pending[irq][cpu];
807 } else if (offset < 0xfd0) {
808 goto bad_reg;
809 } else if (offset < 0x1000) {
810 if (offset & 3) {
811 res = 0;
812 } else {
813 switch (s->revision) {
814 case REV_11MPCORE:
815 res = gic_id_11mpcore[(offset - 0xfd0) >> 2];
816 break;
817 case 1:
818 res = gic_id_gicv1[(offset - 0xfd0) >> 2];
819 break;
820 case 2:
821 res = gic_id_gicv2[(offset - 0xfd0) >> 2];
822 break;
823 case REV_NVIC:
824
825 abort();
826 default:
827 res = 0;
828 }
829 }
830 } else {
831 g_assert_not_reached();
832 }
833 return res;
834bad_reg:
835 qemu_log_mask(LOG_GUEST_ERROR,
836 "gic_dist_readb: Bad offset %x\n", (int)offset);
837 return 0;
838}
839
840static uint32_t gic_dist_readw(void *opaque, hwaddr offset, bool secure)
841{
842 uint32_t val;
843 val = gic_dist_readb(opaque, offset, secure);
844 val |= gic_dist_readb(opaque, offset + 1, secure) << 8;
845 return val;
846}
847
848static uint32_t gic_dist_readl(void *opaque, hwaddr offset, bool secure)
849{
850 uint32_t val;
851 val = gic_dist_readw(opaque, offset, secure);
852 val |= gic_dist_readw(opaque, offset + 2, secure) << 16;
853 return val;
854}
855
856static void gic_dist_writeb(void *opaque, hwaddr offset,
857 uint32_t value, bool secure)
858{
859 GICState *s = (GICState *)opaque;
860 int irq;
861 int i;
862 int cpu;
863
864 cpu = gic_get_current_cpu(s);
865 if (offset < 0x100) {
866 if (offset == 0) {
867 if (!secure) {
868 s->enabled = (value & 1);
869 } else {
870 s->enabled = (value & 2);
871 s->enabled_grp0 = (value & 1);
872 }
873 DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
874 } else if (offset < 4) {
875
876 } else if (offset >= 0x80) {
877 if (secure && s->revision >= 2) {
878 unsigned int irq = (offset - 0x80) * 8;
879 for (i = 0; i < 8; i++) {
880 s->irq_state[irq + i].group = value & (1 << i);
881 }
882 }
883 } else {
884 goto bad_reg;
885 }
886 } else if (offset < 0x180) {
887
888 irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
889 if (irq >= s->num_irq)
890 goto bad_reg;
891 if (irq < GIC_NR_SGIS) {
892 value = 0xff;
893 }
894
895 for (i = 0; i < 8; i++) {
896 if (value & (1 << i)) {
897 int mask =
898 (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq + i);
899 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
900
901 if (!s->irq_state[irq + i].group && !secure) {
902 continue;
903 }
904
905 if (!GIC_TEST_ENABLED(irq + i, cm)) {
906 DPRINTF("Enabled IRQ %d\n", irq + i);
907 }
908 GIC_SET_ENABLED(irq + i, cm);
909
910
911 if (GIC_TEST_LEVEL(irq + i, mask)
912 && !GIC_TEST_EDGE_TRIGGER(irq + i)) {
913 DPRINTF("Set %d pending mask %x\n", irq + i, mask);
914 GIC_SET_PENDING(irq + i, mask);
915 }
916 }
917 }
918 } else if (offset < 0x200) {
919
920 irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
921 if (irq >= s->num_irq)
922 goto bad_reg;
923 if (irq < GIC_NR_SGIS) {
924 value = 0;
925 }
926
927 for (i = 0; i < 8; i++) {
928 if (value & (1 << i)) {
929 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
930
931 if (!s->irq_state[irq + i].group && !secure) {
932 continue;
933 }
934
935 if (GIC_TEST_ENABLED(irq + i, cm)) {
936 DPRINTF("Disabled IRQ %d\n", irq + i);
937 }
938 GIC_CLEAR_ENABLED(irq + i, cm);
939 }
940 }
941 } else if (offset < 0x280) {
942
943 irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
944 qemu_log("pend irq=%d\n", irq);
945 if (irq >= s->num_irq)
946 goto bad_reg;
947 if (irq < GIC_NR_SGIS) {
948 value = 0;
949 }
950
951 for (i = 0; i < 8; i++) {
952 if (value & (1 << i)) {
953 GIC_SET_PENDING(irq + i, GIC_TARGET(irq + i));
954 }
955 }
956 } else if (offset < 0x300) {
957
958 irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
959 if (irq >= s->num_irq)
960 goto bad_reg;
961 if (irq < GIC_NR_SGIS) {
962 value = 0;
963 }
964
965 for (i = 0; i < 8; i++) {
966
967
968
969 if (value & (1 << i)) {
970 GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
971 }
972 }
973 } else if (offset < 0x400) {
974
975 goto bad_reg;
976 } else if (offset < 0x800) {
977
978 irq = (offset - 0x400) + GIC_BASE_IRQ;
979 if (irq >= s->num_irq)
980 goto bad_reg;
981 if (s->irq_state[irq].group || secure) {
982 gic_set_priority(s, cpu, irq, value);
983 }
984 } else if (offset < 0xc00) {
985
986
987
988 if (s->num_cpu != 1 || s->revision == REV_11MPCORE) {
989 irq = (offset - 0x800) + GIC_BASE_IRQ;
990 if (irq >= s->num_irq) {
991 goto bad_reg;
992 }
993 if (irq < 29) {
994 value = 0;
995 } else if (irq < GIC_INTERNAL) {
996 value = ALL_CPU_MASK;
997 }
998 if (s->irq_state[irq].group || secure) {
999 s->irq_target[irq] = value & ALL_CPU_MASK;
1000 }
1001 }
1002 } else if (offset < 0xf00) {
1003
1004 irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
1005 if (irq >= s->num_irq)
1006 goto bad_reg;
1007 if (irq < GIC_NR_SGIS)
1008 value |= 0xaa;
1009 for (i = 0; i < 4; i++) {
1010 if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
1011 if (value & (1 << (i * 2))) {
1012 GIC_SET_MODEL(irq + i);
1013 } else {
1014 GIC_CLEAR_MODEL(irq + i);
1015 }
1016 }
1017 if (value & (2 << (i * 2))) {
1018 GIC_SET_EDGE_TRIGGER(irq + i);
1019 } else {
1020 GIC_CLEAR_EDGE_TRIGGER(irq + i);
1021 }
1022 }
1023 } else if (offset < 0xf10) {
1024
1025 goto bad_reg;
1026 } else if (offset < 0xf20) {
1027
1028 if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
1029 goto bad_reg;
1030 }
1031 irq = (offset - 0xf10);
1032
1033 s->sgi_pending[irq][cpu] &= ~value;
1034 if (s->sgi_pending[irq][cpu] == 0) {
1035 GIC_CLEAR_PENDING(irq, 1 << cpu);
1036 }
1037 } else if (offset < 0xf30) {
1038
1039 if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
1040 goto bad_reg;
1041 }
1042 irq = (offset - 0xf20);
1043
1044 GIC_SET_PENDING(irq, 1 << cpu);
1045 s->sgi_pending[irq][cpu] |= value;
1046 } else {
1047 goto bad_reg;
1048 }
1049 gic_update(s);
1050 return;
1051bad_reg:
1052 qemu_log_mask(LOG_GUEST_ERROR,
1053 "gic_dist_writeb: Bad offset %x\n", (int)offset);
1054}
1055
1056static void gic_dist_writew(void *opaque, hwaddr offset,
1057 uint32_t value, bool secure)
1058{
1059 gic_dist_writeb(opaque, offset, value & 0xff, secure);
1060 gic_dist_writeb(opaque, offset + 1, value >> 8, secure);
1061}
1062
1063static void gic_dist_writel(void *opaque, hwaddr offset,
1064 uint32_t value, bool secure)
1065{
1066 GICState *s = (GICState *)opaque;
1067 if (offset == 0xf00) {
1068 int cpu;
1069 int irq;
1070 int mask;
1071 int target_cpu;
1072
1073 cpu = gic_get_current_cpu(s);
1074 irq = value & 0x3ff;
1075 switch ((value >> 24) & 3) {
1076 case 0:
1077 mask = (value >> 16) & ALL_CPU_MASK;
1078 break;
1079 case 1:
1080 mask = ALL_CPU_MASK ^ (1 << cpu);
1081 break;
1082 case 2:
1083 mask = 1 << cpu;
1084 break;
1085 default:
1086 DPRINTF("Bad Soft Int target filter\n");
1087 mask = ALL_CPU_MASK;
1088 break;
1089 }
1090 GIC_SET_PENDING(irq, mask);
1091 target_cpu = ctz32(mask);
1092 while (target_cpu < GIC_N_REALCPU) {
1093 s->sgi_pending[irq][target_cpu] |= (1 << cpu);
1094 mask &= ~(1 << target_cpu);
1095 target_cpu = ctz32(mask);
1096 }
1097 gic_update(s);
1098 return;
1099 }
1100 gic_dist_writew(opaque, offset, value & 0xffff, secure);
1101 gic_dist_writew(opaque, offset + 2, value >> 16, secure);
1102}
1103
1104static void gic_dist_access(MemoryTransaction *tr)
1105{
1106 bool sec = tr->attr.secure;
1107 if (tr->rw) {
1108 switch (tr->size) {
1109 case 1:
1110 gic_dist_writeb(tr->opaque, tr->addr, tr->data.u8, sec);
1111 break;
1112 case 2:
1113 gic_dist_writew(tr->opaque, tr->addr, tr->data.u16, sec);
1114 break;
1115 case 4:
1116 gic_dist_writel(tr->opaque, tr->addr, tr->data.u32, sec);
1117 break;
1118 }
1119 } else {
1120 switch (tr->size) {
1121 case 1:
1122 tr->data.u8 = gic_dist_readb(tr->opaque, tr->addr, sec);
1123 break;
1124 case 2:
1125 tr->data.u16 = gic_dist_readw(tr->opaque, tr->addr, sec);
1126 break;
1127 case 4:
1128 tr->data.u32 = gic_dist_readl(tr->opaque, tr->addr, sec);
1129 break;
1130 }
1131 }
1132#if 0
1133 qemu_log("GIC sz=%d rw=%d addr=%lx data32=%x secure=%d\n",
1134 tr->size, tr->rw, tr->addr, tr->data.u32, sec);
1135#endif
1136}
1137
1138static const MemoryRegionOps gic_dist_ops = {
1139#if 1
1140 .access = gic_dist_access,
1141#else
1142 .old_mmio = {
1143 .read = { gic_dist_readb, gic_dist_readw, gic_dist_readl, },
1144 .write = { gic_dist_writeb, gic_dist_writew, gic_dist_writel, },
1145 },
1146#endif
1147 .endianness = DEVICE_NATIVE_ENDIAN,
1148};
1149
1150#define GICC_ACK_CTL (1 << 2)
1151#define GICC_FIQ_EN (1 << 3)
1152#define GICC_EOIRMODE (1 << 9)
1153#define GICC_EOIRMODE_NS (1 << 10)
1154static uint32_t gicc_encode_ctrl(GICState *s, int cpu, bool secure)
1155{
1156 uint32_t r;
1157
1158 if (secure) {
1159 r = s->gicc_ctrl[cpu].enable_grp[0];
1160 r |= s->gicc_ctrl[cpu].enable_grp[1] << 1;
1161 r |= s->gicc_ctrl[cpu].ack_ctl << 2;
1162 r |= s->gicc_ctrl[cpu].fiq_en << 3;
1163 r |= s->gicc_ctrl[cpu].eoirmode << 9;
1164 r |= s->gicc_ctrl[cpu].eoirmode_ns << 10;
1165 } else {
1166 r = s->gicc_ctrl[cpu].enable_grp[1];
1167 r |= s->gicc_ctrl[cpu].eoirmode_ns << 9;
1168 }
1169 return r;
1170}
1171
1172static void gicc_decode_ctrl(GICState *s, int cpu, bool secure, uint32_t v)
1173{
1174 if (secure) {
1175 s->gicc_ctrl[cpu].enable_grp[0] = v & 1;
1176 s->gicc_ctrl[cpu].enable_grp[1] = v & 2;
1177 s->gicc_ctrl[cpu].ack_ctl = v & GICC_ACK_CTL;
1178 s->gicc_ctrl[cpu].fiq_en = v & GICC_FIQ_EN;
1179 s->gicc_ctrl[cpu].eoirmode = v & GICC_EOIRMODE;
1180 s->gicc_ctrl[cpu].eoirmode_ns = v & GICC_EOIRMODE_NS;
1181 } else {
1182 s->gicc_ctrl[cpu].enable_grp[1] = v & 1;
1183 s->gicc_ctrl[cpu].eoirmode_ns = v & GICC_EOIRMODE;
1184 }
1185}
1186
1187static uint32_t gic_cpu_read(GICState *s, int cpu, int offset, bool secure)
1188{
1189 bool virt = cpu >= GIC_N_REALCPU;
1190
1191 switch (offset) {
1192 case 0x00:
1193 return gicc_encode_ctrl(s, cpu, secure);
1194 case 0x04:
1195 return s->priority_mask[cpu];
1196 case 0x08:
1197 return s->bpr[cpu];
1198 case 0x0c:
1199 if (virt) {
1200 return gic_acknowledge_virq(s, cpu);
1201 } else {
1202 return gic_acknowledge_irq(s, cpu, secure);
1203 }
1204 case 0x14:
1205 return s->running_priority[cpu] == 0x100 ?
1206 IDLE_PRIORITY : s->running_priority[cpu];
1207 case 0x18:
1208 return s->current_pending[cpu];
1209 case 0x1c:
1210 return s->abpr[cpu];
1211 case 0x20:
1212 qemu_log_mask(LOG_UNIMP, "unsupported AIAR\n");
1213 return 0;
1214 case 0xd0: case 0xd4: case 0xd8: case 0xdc:
1215 return s->apr[(offset - 0xd0) / 4][cpu];
1216 case 0xFC:
1217 return s->c_iidr;
1218 default:
1219 qemu_log_mask(LOG_GUEST_ERROR,
1220 "gic_cpu_read: Bad offset %x\n", (int)offset);
1221 return 0;
1222 }
1223}
1224
1225static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value, bool secure)
1226{
1227 bool virt = cpu >= GIC_N_REALCPU;
1228
1229 switch (offset) {
1230 case 0x00:
1231 gicc_decode_ctrl(s, cpu, secure, value);
1232 s->ctrl[cpu] = gicc_encode_ctrl(s, cpu, true);
1233 break;
1234 case 0x04:
1235 s->priority_mask[cpu] = (value & 0xff);
1236 break;
1237 case 0x08:
1238 s->bpr[cpu] = (value & 0x7);
1239 break;
1240 case 0x10:
1241 if (virt) {
1242 gic_complete_virq(s, cpu, value & 0x3ff);
1243 } else {
1244 return gic_complete_irq(s, cpu, value & 0x3ff, secure);
1245 }
1246 break;
1247 case 0x1c:
1248 if (s->revision >= 2) {
1249 s->abpr[cpu] = (value & 0x7);
1250 }
1251 break;
1252 case 0xd0: case 0xd4: case 0xd8: case 0xdc:
1253 s->apr[(offset - 0xd0) / 4][cpu] = value;
1254 qemu_log_mask(LOG_UNIMP, "Writing APR not implemented\n");
1255 break;
1256 case 0x1000:
1257 case 0x10000:
1258 if (offset != s->map_stride) {
1259 qemu_log("Bad write to GIC 0x%x: Wrong GIC map stride?\n", offset);
1260 }
1261 if (virt) {
1262 qemu_log_mask(LOG_UNIMP, "Writing GICV_DIR not implemented\n");
1263 } else {
1264 return gic_complete_irq_force(s, cpu, value & 0x3ff, true, secure);
1265 }
1266 break;
1267 default:
1268 qemu_log_mask(LOG_GUEST_ERROR,
1269 "gic_cpu_write: Bad offset %x\n", (int)offset);
1270 return;
1271 }
1272 gic_update(s);
1273}
1274
1275static void thiscpu_access(MemoryTransaction *tr)
1276{
1277 GICState *s = (GICState *) tr->opaque;
1278 bool sec = tr->attr.secure;
1279
1280 if (tr->rw) {
1281 gic_cpu_write(s, gic_get_current_cpu(s), tr->addr, tr->data.u32, sec);
1282 } else {
1283 tr->data.u32 = gic_cpu_read(s, gic_get_current_cpu(s), tr->addr, sec);
1284 }
1285}
1286
1287static uint32_t gic_hyp_vmcr_read(GICState *s, int vcpu)
1288{
1289 int cpu = vcpu + GIC_N_REALCPU;
1290 uint32_t r;
1291 uint32_t ctrl;
1292
1293 r = extract32(s->priority_mask[cpu], 3, 5) << 27;
1294 r |= extract32(s->bpr[cpu], 0, 3) << 21;
1295 r |= extract32(s->abpr[cpu], 0, 3) << 18;
1296
1297 ctrl = gicc_encode_ctrl(s, cpu, false);
1298 r |= extract32(ctrl, 0, 10);
1299 return r;
1300}
1301
1302static void gic_hyp_vmcr_write(GICState *s, int vcpu, uint32_t value)
1303{
1304 int cpu = vcpu + GIC_N_REALCPU;
1305 uint32_t primask = extract32(value, 27, 5);
1306 uint32_t bpr = extract32(value, 21, 3);
1307 uint32_t abpr = extract32(value, 18, 3);
1308 uint32_t ctrl = extract32(value, 0, 10);
1309
1310 s->priority_mask[cpu] = primask << 3;
1311 s->bpr[cpu] = bpr;
1312 s->abpr[cpu] = abpr;
1313 gicc_decode_ctrl(s, cpu, false, ctrl);
1314}
1315
1316static uint32_t gic_hyp_read(GICState *s, int vcpu, int offset)
1317{
1318 uint32_t r = 0;
1319
1320 switch (offset) {
1321 case 0x00:
1322 r = s->gich.hcr[vcpu];
1323 break;
1324 case 0x04:
1325
1326 r = 5 << 29 | 5 << 26 | (GICV_NR_LR - 1);
1327 break;
1328 case 0x08:
1329 r = gic_hyp_vmcr_read(s, vcpu);
1330 break;
1331 case 0x10:
1332 r = s->gich.misr[vcpu];
1333 break;
1334 case 0x20:
1335 r = s->gich.eisr[vcpu] & 0xffffffff;
1336 qemu_log("eisr0=%x\n", r);
1337 break;
1338 case 0x24:
1339 r = s->gich.eisr[vcpu] >> 32;
1340 qemu_log("eisr1=%x\n", r);
1341 break;
1342 case 0x30:
1343 r = s->gich.elrsr[vcpu] & 0xffffffff;
1344 qemu_log("elrsr0=%x\n", r);
1345 break;
1346 case 0x34:
1347 r = s->gich.elrsr[vcpu] >> 32;
1348 qemu_log("elrsr1=%x\n", r);
1349 break;
1350 case 0xf0:
1351 r = s->gich.apr[vcpu];
1352 break;
1353 case 0x100 ... 0x1fc:
1354 r = s->gich.lr[vcpu][(offset - 0x100) / 4];
1355#if 0
1356 if (r && (r & 0x1ff) == 27) {
1357 qemu_log("READ VCPU%d LR[%d]=%x\n",
1358 vcpu, (offset - 0x100) / 4, r);
1359 }
1360#endif
1361 break;
1362 default:
1363 qemu_log_mask(LOG_GUEST_ERROR,
1364 "%s: Bad offset %x\n", __func__, offset);
1365 }
1366 return r;
1367}
1368
1369static void gic_hyp_write(GICState *s, int vcpu, int offset, uint32_t value)
1370{
1371 switch (offset) {
1372 case 0x00:
1373 s->gich.hcr[vcpu] = value;
1374 gicv_update(s);
1375 break;
1376 case 0x08:
1377 gic_hyp_vmcr_write(s, vcpu, value);
1378 gicv_update(s);
1379 break;
1380 case 0xf0:
1381 s->gich.apr[vcpu] = value;
1382 gicv_update(s);
1383 break;
1384 case 0x100 ... 0x1fc:
1385 if (s->gich.lr[vcpu][(offset - 0x100) / 4] != value) {
1386#if 0
1387 unsigned int state = extract32(s->gich.lr[vcpu][(offset - 0x100) / 4], 28, 2);
1388 if (state) {
1389 qemu_log("BAD: OVERWRITE ACTIVE LR%d! vCPU%d %x -> %x\n",
1390 (offset - 0x100) / 4, vcpu,
1391 s->gich.lr[vcpu][(offset - 0x100) / 4], value);
1392 gic_dump_lrs(s, "BAD");
1393 }
1394#endif
1395 s->gich.lr[vcpu][(offset - 0x100) / 4] = value;
1396#if 0
1397 if (value && (value & 0x1ff) == 27) {
1398 qemu_log("WRITE VCPU%d LR[%d]=%x\n",
1399 vcpu, (offset - 0x100) / 4, value);
1400 }
1401#endif
1402 gicv_update(s);
1403 }
1404 break;
1405 default:
1406 qemu_log_mask(LOG_GUEST_ERROR,
1407 "%s: Bad offset %x\n", __func__, offset);
1408 return;
1409 }
1410}
1411
1412static uint64_t gic_do_hyp_read(void *opaque, hwaddr addr,
1413 unsigned size)
1414{
1415 GICState **backref = (GICState **)opaque;
1416 GICState *s = *backref;
1417 int id = backref - s->backref;
1418 uint64_t r;
1419
1420 r = gic_hyp_read(s, id, addr);
1421 return r;
1422}
1423
1424static void gic_do_hyp_write(void *opaque, hwaddr addr,
1425 uint64_t value, unsigned size)
1426{
1427 GICState **backref = (GICState **)opaque;
1428 GICState *s = *backref;
1429 int id = backref - s->backref;
1430
1431 gic_hyp_write(s, id, addr, value);
1432}
1433
1434static uint64_t gic_thishyp_read(void *opaque, hwaddr addr,
1435 unsigned size)
1436{
1437 GICState *s = (GICState *)opaque;
1438 int id = gic_get_current_cpu(s);
1439 uint64_t r;
1440
1441 r = gic_hyp_read(s, id, addr);
1442 return r;
1443}
1444
1445static void gic_thishyp_write(void *opaque, hwaddr addr,
1446 uint64_t value, unsigned size)
1447{
1448 GICState *s = (GICState *)opaque;
1449 int id = gic_get_current_cpu(s);
1450
1451 gic_hyp_write(s, id, addr, value);
1452}
1453
1454
1455static uint64_t gic_thisvcpu_read(void *opaque, hwaddr addr,
1456 unsigned size)
1457{
1458 GICState *s = (GICState *)opaque;
1459 int id = GIC_N_REALCPU + gic_get_current_cpu(s);
1460 uint64_t r;
1461
1462 r = gic_cpu_read(s, id, addr, false);
1463 return r;
1464}
1465
1466static void gic_thisvcpu_write(void *opaque, hwaddr addr,
1467 uint64_t value, unsigned size)
1468{
1469 GICState *s = (GICState *)opaque;
1470 int id = GIC_N_REALCPU + gic_get_current_cpu(s);
1471
1472 gic_cpu_write(s, id, addr, value, false);
1473}
1474
1475static const MemoryRegionOps gic_thiscpu_ops = {
1476#if 1
1477 .access = thiscpu_access,
1478#else
1479 .read = gic_thiscpu_read,
1480 .write = gic_thiscpu_write,
1481 .endianness = DEVICE_NATIVE_ENDIAN,
1482#endif
1483};
1484
1485static const MemoryRegionOps gic_thishyp_ops = {
1486 .read = gic_thishyp_read,
1487 .write = gic_thishyp_write,
1488 .endianness = DEVICE_NATIVE_ENDIAN,
1489};
1490
1491static const MemoryRegionOps gic_hyp_ops = {
1492 .read = gic_do_hyp_read,
1493 .write = gic_do_hyp_write,
1494 .endianness = DEVICE_NATIVE_ENDIAN,
1495};
1496
1497static const MemoryRegionOps gic_thisvcpu_ops = {
1498 .read = gic_thisvcpu_read,
1499 .write = gic_thisvcpu_write,
1500 .endianness = DEVICE_NATIVE_ENDIAN,
1501};
1502
1503void gic_init_irqs_and_distributor(GICState *s)
1504{
1505 SysBusDevice *sbd = SYS_BUS_DEVICE(s);
1506 int i;
1507
1508 i = s->num_irq - GIC_INTERNAL;
1509
1510
1511
1512
1513
1514
1515
1516 if (s->revision != REV_NVIC) {
1517 i += (GIC_INTERNAL * s->num_cpu);
1518 qdev_init_gpio_in(DEVICE(s), gic_set_irq_cb, i);
1519 }
1520 for (i = 0; i < GIC_N_REALCPU; i++) {
1521 sysbus_init_irq(sbd, &s->parent_irq[i]);
1522 }
1523 for (i = 0; i < GIC_N_REALCPU; i++) {
1524 sysbus_init_irq(sbd, &s->parent_irq[GIC_N_REALCPU + i]);
1525 }
1526 for (i = 0; i < GIC_N_REALCPU; i++) {
1527 sysbus_init_irq(sbd, &s->parent_fiq[i]);
1528 }
1529 for (i = 0; i < GIC_N_REALCPU; i++) {
1530 sysbus_init_irq(sbd, &s->parent_fiq[GIC_N_REALCPU + i]);
1531 }
1532 for (i = 0; i < NUM_CPU(s); i++) {
1533 sysbus_init_irq(sbd, &s->maint[i]);
1534 }
1535 qdev_init_gpio_out_named(DEVICE(s), s->parent_irq, "irq", GIC_N_REALCPU * 2);
1536 qdev_init_gpio_out_named(DEVICE(s), s->parent_fiq, "fiq", GIC_N_REALCPU * 2);
1537 qdev_init_gpio_out_named(DEVICE(s), s->maint, "maint", NUM_CPU(s));
1538 memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s,
1539 "gic_dist", 0x1000);
1540}
1541
1542static void arm_gic_realize(DeviceState *dev, Error **errp)
1543{
1544
1545 int i;
1546 GICState *s = ARM_GIC(dev);
1547 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1548 ARMGICClass *agc = ARM_GIC_GET_CLASS(s);
1549 Error *local_err = NULL;
1550
1551 agc->parent_realize(dev, &local_err);
1552 if (local_err) {
1553 error_propagate(errp, local_err);
1554 return;
1555 }
1556
1557 gic_init_irqs_and_distributor(s);
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567 memory_region_init_io(&s->cpuiomem[0], OBJECT(s), &gic_thiscpu_ops, s,
1568 "gic_cpu", s->revision >= 2 ? s->map_stride * 2 : 0x100);
1569 memory_region_init_io(&s->hypiomem[0], OBJECT(s), &gic_thishyp_ops, s,
1570 "gic_thishyp_cpu", 0x200);
1571 memory_region_init_io(&s->vcpuiomem, OBJECT(s), &gic_thisvcpu_ops, s,
1572 "gic_thisvcpu",
1573 s->revision >= 2 ? s->map_stride * 2 : 0x2000);
1574 for (i = 0; i < NUM_CPU(s); i++) {
1575 char *region_name = g_strdup_printf("gic_hyp_cpu-%d", i);
1576 s->backref[GIC_N_REALCPU + i] = s;
1577 memory_region_init_io(&s->hypiomem[i+1], OBJECT(s), &gic_hyp_ops,
1578 &s->backref[i], region_name, 0x200);
1579 g_free(region_name);
1580 }
1581
1582 sysbus_init_mmio(sbd, &s->iomem);
1583
1584 sysbus_init_mmio(sbd, &s->cpuiomem[0]);
1585#if 0
1586 for (i = 1; i <= NUM_CPU(s); i++) {
1587 sysbus_init_mmio(sbd, &s->cpuiomem[i]);
1588 }
1589#endif
1590 sysbus_init_mmio(sbd, &s->hypiomem[0]);
1591 sysbus_init_mmio(sbd, &s->vcpuiomem);
1592#if 0
1593
1594
1595
1596 for (i = 0; i <= NUM_CPU(s); i++) {
1597 sysbus_init_mmio(sbd, &s->hypiomem[i]);
1598 }
1599#endif
1600}
1601
1602static void arm_gic_fdt_auto_parent(FDTGenericIntc *obj, Error **errp)
1603{
1604 GICState *s = ARM_GIC(obj);
1605 CPUState *cs;
1606 int i = 0;
1607
1608 for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
1609 if (i >= s->num_cpu) {
1610 break;
1611 }
1612 qdev_connect_gpio_out_named(DEVICE(obj), "irq", i,
1613 qdev_get_gpio_in(DEVICE(cs), 0));
1614 i++;
1615 }
1616
1617
1618}
1619
1620static const FDTGenericGPIOSet arm_gic_client_gpios [] = {
1621 {
1622 .names = &fdt_generic_gpio_name_set_interrupts,
1623 .gpios = (FDTGenericGPIOConnection []) {
1624 { .name = "irq", .range = 16 },
1625 { .name = "fiq", .range = 16, .fdt_index = 16 },
1626 { .name = "maint", .range = 4, .fdt_index = 32 },
1627 { },
1628 },
1629 },
1630 {
1631 .names = &fdt_generic_gpio_name_set_gpio,
1632 .gpios = (FDTGenericGPIOConnection []) {
1633 { .name = "pwr_cntrl", .range = 1, .fdt_index = 0 },
1634 { .name = "rst_cntrl", .range = 1, .fdt_index = 1 },
1635 { },
1636 },
1637 },
1638 { },
1639};
1640
1641static void arm_gic_linux_init(LinuxDevice *obj)
1642{
1643 GICState *s = ARM_GIC(obj);
1644 int i;
1645
1646 if (s->disable_linux_gic_init) {
1647 return;
1648 }
1649
1650 for (i = 0 ; i < s->num_irq; ++i) {
1651 s->irq_state[i].group = 1;
1652 }
1653}
1654
1655static void arm_gic_class_init(ObjectClass *klass, void *data)
1656{
1657 DeviceClass *dc = DEVICE_CLASS(klass);
1658 ARMGICClass *agc = ARM_GIC_CLASS(klass);
1659 FDTGenericIntcClass *fgic = FDT_GENERIC_INTC_CLASS(klass);
1660 FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
1661 LinuxDeviceClass *ldc = LINUX_DEVICE_CLASS(klass);
1662
1663 agc->irq_handler = gic_set_irq;
1664 agc->parent_realize = dc->realize;
1665 dc->realize = arm_gic_realize;
1666 fgic->auto_parent = arm_gic_fdt_auto_parent;
1667 fggc->client_gpios = arm_gic_client_gpios;
1668 ldc->linux_init = arm_gic_linux_init;
1669}
1670
1671static const TypeInfo arm_gic_info = {
1672 .name = TYPE_ARM_GIC,
1673 .parent = TYPE_ARM_GIC_COMMON,
1674 .instance_size = sizeof(GICState),
1675 .class_init = arm_gic_class_init,
1676 .class_size = sizeof(ARMGICClass),
1677 .interfaces = (InterfaceInfo []) {
1678 { TYPE_LINUX_DEVICE },
1679 { },
1680 }
1681};
1682
1683static void arm_gic_register_types(void)
1684{
1685 type_register_static(&arm_gic_info);
1686}
1687
1688type_init(arm_gic_register_types)
1689