x86: factor out cpu_get/put_fpreg()
[armpft.git] / hw / arm_gic.c
blob12f5109924bd2bdbfdb762a436575c6d58875911
1 /*
2 * ARM Generic/Distributed Interrupt Controller
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the GPL.
8 */
10 /* This file contains implementation code for the RealView EB interrupt
11 controller, MPCore distributed interrupt controller and ARMv7-M
12 Nested Vectored Interrupt Controller. */
14 //#define DEBUG_GIC
16 #ifdef DEBUG_GIC
17 #define DPRINTF(fmt, ...) \
18 do { printf("arm_gic: " fmt , ## __VA_ARGS__); } while (0)
19 #else
20 #define DPRINTF(fmt, ...) do {} while(0)
21 #endif
23 #ifdef NVIC
24 static const uint8_t gic_id[] =
25 { 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 };
26 /* The NVIC has 16 internal vectors. However these are not exposed
27 through the normal GIC interface. */
28 #define GIC_BASE_IRQ 32
29 #else
30 static const uint8_t gic_id[] =
31 { 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
32 #define GIC_BASE_IRQ 0
33 #endif
35 #define FROM_SYSBUSGIC(type, dev) \
36 DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev))
38 typedef struct gic_irq_state
40 /* ??? The documentation seems to imply the enable bits are global, even
41 for per-cpu interrupts. This seems strange. */
42 unsigned enabled:1;
43 unsigned pending:NCPU;
44 unsigned active:NCPU;
45 unsigned level:NCPU;
46 unsigned model:1; /* 0 = N:N, 1 = 1:N */
47 unsigned trigger:1; /* nonzero = edge triggered. */
48 } gic_irq_state;
50 #define ALL_CPU_MASK ((1 << NCPU) - 1)
52 #define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
53 #define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
54 #define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
55 #define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
56 #define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
57 #define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
58 #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
59 #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
60 #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
61 #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
62 #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
63 #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
64 #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
65 #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
66 #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
67 #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
68 #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
69 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
70 #define GIC_GET_PRIORITY(irq, cpu) \
71 (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
72 #ifdef NVIC
73 #define GIC_TARGET(irq) 1
74 #else
75 #define GIC_TARGET(irq) s->irq_target[irq]
76 #endif
78 typedef struct gic_state
80 SysBusDevice busdev;
81 qemu_irq parent_irq[NCPU];
82 int enabled;
83 int cpu_enabled[NCPU];
85 gic_irq_state irq_state[GIC_NIRQ];
86 #ifndef NVIC
87 int irq_target[GIC_NIRQ];
88 #endif
89 int priority1[32][NCPU];
90 int priority2[GIC_NIRQ - 32];
91 int last_active[GIC_NIRQ][NCPU];
93 int priority_mask[NCPU];
94 int running_irq[NCPU];
95 int running_priority[NCPU];
96 int current_pending[NCPU];
98 int iomemtype;
99 } gic_state;
101 /* TODO: Many places that call this routine could be optimized. */
102 /* Update interrupt status after enabled or pending bits have been changed. */
103 static void gic_update(gic_state *s)
105 int best_irq;
106 int best_prio;
107 int irq;
108 int level;
109 int cpu;
110 int cm;
112 for (cpu = 0; cpu < NCPU; cpu++) {
113 cm = 1 << cpu;
114 s->current_pending[cpu] = 1023;
115 if (!s->enabled || !s->cpu_enabled[cpu]) {
116 qemu_irq_lower(s->parent_irq[cpu]);
117 return;
119 best_prio = 0x100;
120 best_irq = 1023;
121 for (irq = 0; irq < GIC_NIRQ; irq++) {
122 if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) {
123 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
124 best_prio = GIC_GET_PRIORITY(irq, cpu);
125 best_irq = irq;
129 level = 0;
130 if (best_prio <= s->priority_mask[cpu]) {
131 s->current_pending[cpu] = best_irq;
132 if (best_prio < s->running_priority[cpu]) {
133 DPRINTF("Raised pending IRQ %d\n", best_irq);
134 level = 1;
137 qemu_set_irq(s->parent_irq[cpu], level);
141 static void __attribute__((unused))
142 gic_set_pending_private(gic_state *s, int cpu, int irq)
144 int cm = 1 << cpu;
146 if (GIC_TEST_PENDING(irq, cm))
147 return;
149 DPRINTF("Set %d pending cpu %d\n", irq, cpu);
150 GIC_SET_PENDING(irq, cm);
151 gic_update(s);
154 /* Process a change in an external IRQ input. */
155 static void gic_set_irq(void *opaque, int irq, int level)
157 gic_state *s = (gic_state *)opaque;
158 /* The first external input line is internal interrupt 32. */
159 irq += 32;
160 if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
161 return;
163 if (level) {
164 GIC_SET_LEVEL(irq, ALL_CPU_MASK);
165 if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
166 DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
167 GIC_SET_PENDING(irq, GIC_TARGET(irq));
169 } else {
170 GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
172 gic_update(s);
175 static void gic_set_running_irq(gic_state *s, int cpu, int irq)
177 s->running_irq[cpu] = irq;
178 if (irq == 1023) {
179 s->running_priority[cpu] = 0x100;
180 } else {
181 s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
183 gic_update(s);
186 static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
188 int new_irq;
189 int cm = 1 << cpu;
190 new_irq = s->current_pending[cpu];
191 if (new_irq == 1023
192 || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
193 DPRINTF("ACK no pending IRQ\n");
194 return 1023;
196 s->last_active[new_irq][cpu] = s->running_irq[cpu];
197 /* Clear pending flags for both level and edge triggered interrupts.
198 Level triggered IRQs will be reasserted once they become inactive. */
199 GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
200 gic_set_running_irq(s, cpu, new_irq);
201 DPRINTF("ACK %d\n", new_irq);
202 return new_irq;
205 static void gic_complete_irq(gic_state * s, int cpu, int irq)
207 int update = 0;
208 int cm = 1 << cpu;
209 DPRINTF("EOI %d\n", irq);
210 if (s->running_irq[cpu] == 1023)
211 return; /* No active IRQ. */
212 if (irq != 1023) {
213 /* Mark level triggered interrupts as pending if they are still
214 raised. */
215 if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
216 && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
217 DPRINTF("Set %d pending mask %x\n", irq, cm);
218 GIC_SET_PENDING(irq, cm);
219 update = 1;
222 if (irq != s->running_irq[cpu]) {
223 /* Complete an IRQ that is not currently running. */
224 int tmp = s->running_irq[cpu];
225 while (s->last_active[tmp][cpu] != 1023) {
226 if (s->last_active[tmp][cpu] == irq) {
227 s->last_active[tmp][cpu] = s->last_active[irq][cpu];
228 break;
230 tmp = s->last_active[tmp][cpu];
232 if (update) {
233 gic_update(s);
235 } else {
236 /* Complete the current running IRQ. */
237 gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
241 static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
243 gic_state *s = (gic_state *)opaque;
244 uint32_t res;
245 int irq;
246 int i;
247 int cpu;
248 int cm;
249 int mask;
251 cpu = gic_get_current_cpu();
252 cm = 1 << cpu;
253 if (offset < 0x100) {
254 #ifndef NVIC
255 if (offset == 0)
256 return s->enabled;
257 if (offset == 4)
258 return ((GIC_NIRQ / 32) - 1) | ((NCPU - 1) << 5);
259 if (offset < 0x08)
260 return 0;
261 #endif
262 goto bad_reg;
263 } else if (offset < 0x200) {
264 /* Interrupt Set/Clear Enable. */
265 if (offset < 0x180)
266 irq = (offset - 0x100) * 8;
267 else
268 irq = (offset - 0x180) * 8;
269 irq += GIC_BASE_IRQ;
270 if (irq >= GIC_NIRQ)
271 goto bad_reg;
272 res = 0;
273 for (i = 0; i < 8; i++) {
274 if (GIC_TEST_ENABLED(irq + i)) {
275 res |= (1 << i);
278 } else if (offset < 0x300) {
279 /* Interrupt Set/Clear Pending. */
280 if (offset < 0x280)
281 irq = (offset - 0x200) * 8;
282 else
283 irq = (offset - 0x280) * 8;
284 irq += GIC_BASE_IRQ;
285 if (irq >= GIC_NIRQ)
286 goto bad_reg;
287 res = 0;
288 mask = (irq < 32) ? cm : ALL_CPU_MASK;
289 for (i = 0; i < 8; i++) {
290 if (GIC_TEST_PENDING(irq + i, mask)) {
291 res |= (1 << i);
294 } else if (offset < 0x400) {
295 /* Interrupt Active. */
296 irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
297 if (irq >= GIC_NIRQ)
298 goto bad_reg;
299 res = 0;
300 mask = (irq < 32) ? cm : ALL_CPU_MASK;
301 for (i = 0; i < 8; i++) {
302 if (GIC_TEST_ACTIVE(irq + i, mask)) {
303 res |= (1 << i);
306 } else if (offset < 0x800) {
307 /* Interrupt Priority. */
308 irq = (offset - 0x400) + GIC_BASE_IRQ;
309 if (irq >= GIC_NIRQ)
310 goto bad_reg;
311 res = GIC_GET_PRIORITY(irq, cpu);
312 #ifndef NVIC
313 } else if (offset < 0xc00) {
314 /* Interrupt CPU Target. */
315 irq = (offset - 0x800) + GIC_BASE_IRQ;
316 if (irq >= GIC_NIRQ)
317 goto bad_reg;
318 if (irq >= 29 && irq <= 31) {
319 res = cm;
320 } else {
321 res = GIC_TARGET(irq);
323 } else if (offset < 0xf00) {
324 /* Interrupt Configuration. */
325 irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
326 if (irq >= GIC_NIRQ)
327 goto bad_reg;
328 res = 0;
329 for (i = 0; i < 4; i++) {
330 if (GIC_TEST_MODEL(irq + i))
331 res |= (1 << (i * 2));
332 if (GIC_TEST_TRIGGER(irq + i))
333 res |= (2 << (i * 2));
335 #endif
336 } else if (offset < 0xfe0) {
337 goto bad_reg;
338 } else /* offset >= 0xfe0 */ {
339 if (offset & 3) {
340 res = 0;
341 } else {
342 res = gic_id[(offset - 0xfe0) >> 2];
345 return res;
346 bad_reg:
347 hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
348 return 0;
351 static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
353 uint32_t val;
354 val = gic_dist_readb(opaque, offset);
355 val |= gic_dist_readb(opaque, offset + 1) << 8;
356 return val;
359 static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
361 uint32_t val;
362 #ifdef NVIC
363 gic_state *s = (gic_state *)opaque;
364 uint32_t addr;
365 addr = offset;
366 if (addr < 0x100 || addr > 0xd00)
367 return nvic_readl(s, addr);
368 #endif
369 val = gic_dist_readw(opaque, offset);
370 val |= gic_dist_readw(opaque, offset + 2) << 16;
371 return val;
374 static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
375 uint32_t value)
377 gic_state *s = (gic_state *)opaque;
378 int irq;
379 int i;
380 int cpu;
382 cpu = gic_get_current_cpu();
383 if (offset < 0x100) {
384 #ifdef NVIC
385 goto bad_reg;
386 #else
387 if (offset == 0) {
388 s->enabled = (value & 1);
389 DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
390 } else if (offset < 4) {
391 /* ignored. */
392 } else {
393 goto bad_reg;
395 #endif
396 } else if (offset < 0x180) {
397 /* Interrupt Set Enable. */
398 irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
399 if (irq >= GIC_NIRQ)
400 goto bad_reg;
401 if (irq < 16)
402 value = 0xff;
403 for (i = 0; i < 8; i++) {
404 if (value & (1 << i)) {
405 int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
406 if (!GIC_TEST_ENABLED(irq + i))
407 DPRINTF("Enabled IRQ %d\n", irq + i);
408 GIC_SET_ENABLED(irq + i);
409 /* If a raised level triggered IRQ enabled then mark
410 is as pending. */
411 if (GIC_TEST_LEVEL(irq + i, mask)
412 && !GIC_TEST_TRIGGER(irq + i)) {
413 DPRINTF("Set %d pending mask %x\n", irq + i, mask);
414 GIC_SET_PENDING(irq + i, mask);
418 } else if (offset < 0x200) {
419 /* Interrupt Clear Enable. */
420 irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
421 if (irq >= GIC_NIRQ)
422 goto bad_reg;
423 if (irq < 16)
424 value = 0;
425 for (i = 0; i < 8; i++) {
426 if (value & (1 << i)) {
427 if (GIC_TEST_ENABLED(irq + i))
428 DPRINTF("Disabled IRQ %d\n", irq + i);
429 GIC_CLEAR_ENABLED(irq + i);
432 } else if (offset < 0x280) {
433 /* Interrupt Set Pending. */
434 irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
435 if (irq >= GIC_NIRQ)
436 goto bad_reg;
437 if (irq < 16)
438 irq = 0;
440 for (i = 0; i < 8; i++) {
441 if (value & (1 << i)) {
442 GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
445 } else if (offset < 0x300) {
446 /* Interrupt Clear Pending. */
447 irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
448 if (irq >= GIC_NIRQ)
449 goto bad_reg;
450 for (i = 0; i < 8; i++) {
451 /* ??? This currently clears the pending bit for all CPUs, even
452 for per-CPU interrupts. It's unclear whether this is the
453 corect behavior. */
454 if (value & (1 << i)) {
455 GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
458 } else if (offset < 0x400) {
459 /* Interrupt Active. */
460 goto bad_reg;
461 } else if (offset < 0x800) {
462 /* Interrupt Priority. */
463 irq = (offset - 0x400) + GIC_BASE_IRQ;
464 if (irq >= GIC_NIRQ)
465 goto bad_reg;
466 if (irq < 32) {
467 s->priority1[irq][cpu] = value;
468 } else {
469 s->priority2[irq - 32] = value;
471 #ifndef NVIC
472 } else if (offset < 0xc00) {
473 /* Interrupt CPU Target. */
474 irq = (offset - 0x800) + GIC_BASE_IRQ;
475 if (irq >= GIC_NIRQ)
476 goto bad_reg;
477 if (irq < 29)
478 value = 0;
479 else if (irq < 32)
480 value = ALL_CPU_MASK;
481 s->irq_target[irq] = value & ALL_CPU_MASK;
482 } else if (offset < 0xf00) {
483 /* Interrupt Configuration. */
484 irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
485 if (irq >= GIC_NIRQ)
486 goto bad_reg;
487 if (irq < 32)
488 value |= 0xaa;
489 for (i = 0; i < 4; i++) {
490 if (value & (1 << (i * 2))) {
491 GIC_SET_MODEL(irq + i);
492 } else {
493 GIC_CLEAR_MODEL(irq + i);
495 if (value & (2 << (i * 2))) {
496 GIC_SET_TRIGGER(irq + i);
497 } else {
498 GIC_CLEAR_TRIGGER(irq + i);
501 #endif
502 } else {
503 /* 0xf00 is only handled for 32-bit writes. */
504 goto bad_reg;
506 gic_update(s);
507 return;
508 bad_reg:
509 hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
512 static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
513 uint32_t value)
515 gic_dist_writeb(opaque, offset, value & 0xff);
516 gic_dist_writeb(opaque, offset + 1, value >> 8);
519 static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
520 uint32_t value)
522 gic_state *s = (gic_state *)opaque;
523 #ifdef NVIC
524 uint32_t addr;
525 addr = offset;
526 if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
527 nvic_writel(s, addr, value);
528 return;
530 #endif
531 if (offset == 0xf00) {
532 int cpu;
533 int irq;
534 int mask;
536 cpu = gic_get_current_cpu();
537 irq = value & 0x3ff;
538 switch ((value >> 24) & 3) {
539 case 0:
540 mask = (value >> 16) & ALL_CPU_MASK;
541 break;
542 case 1:
543 mask = 1 << cpu;
544 break;
545 case 2:
546 mask = ALL_CPU_MASK ^ (1 << cpu);
547 break;
548 default:
549 DPRINTF("Bad Soft Int target filter\n");
550 mask = ALL_CPU_MASK;
551 break;
553 GIC_SET_PENDING(irq, mask);
554 gic_update(s);
555 return;
557 gic_dist_writew(opaque, offset, value & 0xffff);
558 gic_dist_writew(opaque, offset + 2, value >> 16);
561 static CPUReadMemoryFunc * const gic_dist_readfn[] = {
562 gic_dist_readb,
563 gic_dist_readw,
564 gic_dist_readl
567 static CPUWriteMemoryFunc * const gic_dist_writefn[] = {
568 gic_dist_writeb,
569 gic_dist_writew,
570 gic_dist_writel
573 #ifndef NVIC
574 static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
576 switch (offset) {
577 case 0x00: /* Control */
578 return s->cpu_enabled[cpu];
579 case 0x04: /* Priority mask */
580 return s->priority_mask[cpu];
581 case 0x08: /* Binary Point */
582 /* ??? Not implemented. */
583 return 0;
584 case 0x0c: /* Acknowledge */
585 return gic_acknowledge_irq(s, cpu);
586 case 0x14: /* Runing Priority */
587 return s->running_priority[cpu];
588 case 0x18: /* Highest Pending Interrupt */
589 return s->current_pending[cpu];
590 default:
591 hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
592 return 0;
596 static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
598 switch (offset) {
599 case 0x00: /* Control */
600 s->cpu_enabled[cpu] = (value & 1);
601 DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis");
602 break;
603 case 0x04: /* Priority mask */
604 s->priority_mask[cpu] = (value & 0xff);
605 break;
606 case 0x08: /* Binary Point */
607 /* ??? Not implemented. */
608 break;
609 case 0x10: /* End Of Interrupt */
610 return gic_complete_irq(s, cpu, value & 0x3ff);
611 default:
612 hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
613 return;
615 gic_update(s);
617 #endif
619 static void gic_reset(gic_state *s)
621 int i;
622 memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
623 for (i = 0 ; i < NCPU; i++) {
624 s->priority_mask[i] = 0xf0;
625 s->current_pending[i] = 1023;
626 s->running_irq[i] = 1023;
627 s->running_priority[i] = 0x100;
628 #ifdef NVIC
629 /* The NVIC doesn't have per-cpu interfaces, so enable by default. */
630 s->cpu_enabled[i] = 1;
631 #else
632 s->cpu_enabled[i] = 0;
633 #endif
635 for (i = 0; i < 16; i++) {
636 GIC_SET_ENABLED(i);
637 GIC_SET_TRIGGER(i);
639 #ifdef NVIC
640 /* The NVIC is always enabled. */
641 s->enabled = 1;
642 #else
643 s->enabled = 0;
644 #endif
647 static void gic_save(QEMUFile *f, void *opaque)
649 gic_state *s = (gic_state *)opaque;
650 int i;
651 int j;
653 qemu_put_be32(f, s->enabled);
654 for (i = 0; i < NCPU; i++) {
655 qemu_put_be32(f, s->cpu_enabled[i]);
656 #ifndef NVIC
657 qemu_put_be32(f, s->irq_target[i]);
658 #endif
659 for (j = 0; j < 32; j++)
660 qemu_put_be32(f, s->priority1[j][i]);
661 for (j = 0; j < GIC_NIRQ; j++)
662 qemu_put_be32(f, s->last_active[j][i]);
663 qemu_put_be32(f, s->priority_mask[i]);
664 qemu_put_be32(f, s->running_irq[i]);
665 qemu_put_be32(f, s->running_priority[i]);
666 qemu_put_be32(f, s->current_pending[i]);
668 for (i = 0; i < GIC_NIRQ - 32; i++) {
669 qemu_put_be32(f, s->priority2[i]);
671 for (i = 0; i < GIC_NIRQ; i++) {
672 qemu_put_byte(f, s->irq_state[i].enabled);
673 qemu_put_byte(f, s->irq_state[i].pending);
674 qemu_put_byte(f, s->irq_state[i].active);
675 qemu_put_byte(f, s->irq_state[i].level);
676 qemu_put_byte(f, s->irq_state[i].model);
677 qemu_put_byte(f, s->irq_state[i].trigger);
681 static int gic_load(QEMUFile *f, void *opaque, int version_id)
683 gic_state *s = (gic_state *)opaque;
684 int i;
685 int j;
687 if (version_id != 1)
688 return -EINVAL;
690 s->enabled = qemu_get_be32(f);
691 for (i = 0; i < NCPU; i++) {
692 s->cpu_enabled[i] = qemu_get_be32(f);
693 #ifndef NVIC
694 s->irq_target[i] = qemu_get_be32(f);
695 #endif
696 for (j = 0; j < 32; j++)
697 s->priority1[j][i] = qemu_get_be32(f);
698 for (j = 0; j < GIC_NIRQ; j++)
699 s->last_active[j][i] = qemu_get_be32(f);
700 s->priority_mask[i] = qemu_get_be32(f);
701 s->running_irq[i] = qemu_get_be32(f);
702 s->running_priority[i] = qemu_get_be32(f);
703 s->current_pending[i] = qemu_get_be32(f);
705 for (i = 0; i < GIC_NIRQ - 32; i++) {
706 s->priority2[i] = qemu_get_be32(f);
708 for (i = 0; i < GIC_NIRQ; i++) {
709 s->irq_state[i].enabled = qemu_get_byte(f);
710 s->irq_state[i].pending = qemu_get_byte(f);
711 s->irq_state[i].active = qemu_get_byte(f);
712 s->irq_state[i].level = qemu_get_byte(f);
713 s->irq_state[i].model = qemu_get_byte(f);
714 s->irq_state[i].trigger = qemu_get_byte(f);
717 return 0;
720 static void gic_init(gic_state *s)
722 int i;
724 qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
725 for (i = 0; i < NCPU; i++) {
726 sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
728 s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
729 gic_dist_writefn, s);
730 gic_reset(s);
731 register_savevm("arm_gic", -1, 1, gic_save, gic_load, s);