xref: /openbmc/qemu/hw/intc/arm_gic_kvm.c (revision 0ed93f4c)
1 /*
2  * ARM Generic Interrupt Controller using KVM in-kernel support
3  *
4  * Copyright (c) 2012 Linaro Limited
5  * Written by Peter Maydell
6  * Save/Restore logic added by Christoffer Dall.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "qemu/osdep.h"
23 #include "qapi/error.h"
24 #include "qemu/module.h"
25 #include "cpu.h"
26 #include "hw/sysbus.h"
27 #include "migration/blocker.h"
28 #include "sysemu/kvm.h"
29 #include "kvm_arm.h"
30 #include "gic_internal.h"
31 #include "vgic_common.h"
32 #include "qom/object.h"
33 
34 #define TYPE_KVM_ARM_GIC "kvm-arm-gic"
35 typedef struct KVMARMGICClass KVMARMGICClass;
36 /* This is reusing the GICState typedef from ARM_GIC_COMMON */
37 DECLARE_OBJ_CHECKERS(GICState, KVMARMGICClass,
38                      KVM_ARM_GIC, TYPE_KVM_ARM_GIC)
39 
40 struct KVMARMGICClass {
41     ARMGICCommonClass parent_class;
42     DeviceRealize parent_realize;
43     void (*parent_reset)(DeviceState *dev);
44 };
45 
46 void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
47 {
48     /* Meaning of the 'irq' parameter:
49      *  [0..N-1] : external interrupts
50      *  [N..N+31] : PPI (internal) interrupts for CPU 0
51      *  [N+32..N+63] : PPI (internal interrupts for CPU 1
52      *  ...
53      * Convert this to the kernel's desired encoding, which
54      * has separate fields in the irq number for type,
55      * CPU number and interrupt number.
56      */
57     int irqtype, cpu;
58 
59     if (irq < (num_irq - GIC_INTERNAL)) {
60         /* External interrupt. The kernel numbers these like the GIC
61          * hardware, with external interrupt IDs starting after the
62          * internal ones.
63          */
64         irqtype = KVM_ARM_IRQ_TYPE_SPI;
65         cpu = 0;
66         irq += GIC_INTERNAL;
67     } else {
68         /* Internal interrupt: decode into (cpu, interrupt id) */
69         irqtype = KVM_ARM_IRQ_TYPE_PPI;
70         irq -= (num_irq - GIC_INTERNAL);
71         cpu = irq / GIC_INTERNAL;
72         irq %= GIC_INTERNAL;
73     }
74     kvm_arm_set_irq(cpu, irqtype, irq, !!level);
75 }
76 
77 static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
78 {
79     GICState *s = (GICState *)opaque;
80 
81     kvm_arm_gic_set_irq(s->num_irq, irq, level);
82 }
83 
84 static bool kvm_arm_gic_can_save_restore(GICState *s)
85 {
86     return s->dev_fd >= 0;
87 }
88 
89 #define KVM_VGIC_ATTR(offset, cpu) \
90     ((((uint64_t)(cpu) << KVM_DEV_ARM_VGIC_CPUID_SHIFT) & \
91       KVM_DEV_ARM_VGIC_CPUID_MASK) | \
92      (((uint64_t)(offset) << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) & \
93       KVM_DEV_ARM_VGIC_OFFSET_MASK))
94 
95 static void kvm_gicd_access(GICState *s, int offset, int cpu,
96                             uint32_t *val, bool write)
97 {
98     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
99                       KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
100 }
101 
102 static void kvm_gicc_access(GICState *s, int offset, int cpu,
103                             uint32_t *val, bool write)
104 {
105     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
106                       KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
107 }
108 
109 #define for_each_irq_reg(_ctr, _max_irq, _field_width) \
110     for (_ctr = 0; _ctr < ((_max_irq) / (32 / (_field_width))); _ctr++)
111 
112 /*
113  * Translate from the in-kernel field for an IRQ value to/from the qemu
114  * representation.
115  */
116 typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
117                                   uint32_t *field, bool to_kernel);
118 
119 /* synthetic translate function used for clear/set registers to completely
120  * clear a setting using a clear-register before setting the remaining bits
121  * using a set-register */
122 static void translate_clear(GICState *s, int irq, int cpu,
123                             uint32_t *field, bool to_kernel)
124 {
125     if (to_kernel) {
126         *field = ~0;
127     } else {
128         /* does not make sense: qemu model doesn't use set/clear regs */
129         abort();
130     }
131 }
132 
133 static void translate_group(GICState *s, int irq, int cpu,
134                             uint32_t *field, bool to_kernel)
135 {
136     int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
137 
138     if (to_kernel) {
139         *field = GIC_DIST_TEST_GROUP(irq, cm);
140     } else {
141         if (*field & 1) {
142             GIC_DIST_SET_GROUP(irq, cm);
143         }
144     }
145 }
146 
147 static void translate_enabled(GICState *s, int irq, int cpu,
148                               uint32_t *field, bool to_kernel)
149 {
150     int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
151 
152     if (to_kernel) {
153         *field = GIC_DIST_TEST_ENABLED(irq, cm);
154     } else {
155         if (*field & 1) {
156             GIC_DIST_SET_ENABLED(irq, cm);
157         }
158     }
159 }
160 
161 static void translate_pending(GICState *s, int irq, int cpu,
162                               uint32_t *field, bool to_kernel)
163 {
164     int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
165 
166     if (to_kernel) {
167         *field = gic_test_pending(s, irq, cm);
168     } else {
169         if (*field & 1) {
170             GIC_DIST_SET_PENDING(irq, cm);
171             /* TODO: Capture is level-line is held high in the kernel */
172         }
173     }
174 }
175 
176 static void translate_active(GICState *s, int irq, int cpu,
177                              uint32_t *field, bool to_kernel)
178 {
179     int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
180 
181     if (to_kernel) {
182         *field = GIC_DIST_TEST_ACTIVE(irq, cm);
183     } else {
184         if (*field & 1) {
185             GIC_DIST_SET_ACTIVE(irq, cm);
186         }
187     }
188 }
189 
190 static void translate_trigger(GICState *s, int irq, int cpu,
191                               uint32_t *field, bool to_kernel)
192 {
193     if (to_kernel) {
194         *field = (GIC_DIST_TEST_EDGE_TRIGGER(irq)) ? 0x2 : 0x0;
195     } else {
196         if (*field & 0x2) {
197             GIC_DIST_SET_EDGE_TRIGGER(irq);
198         }
199     }
200 }
201 
202 static void translate_priority(GICState *s, int irq, int cpu,
203                                uint32_t *field, bool to_kernel)
204 {
205     if (to_kernel) {
206         *field = GIC_DIST_GET_PRIORITY(irq, cpu) & 0xff;
207     } else {
208         gic_dist_set_priority(s, cpu, irq,
209                               *field & 0xff, MEMTXATTRS_UNSPECIFIED);
210     }
211 }
212 
213 static void translate_targets(GICState *s, int irq, int cpu,
214                               uint32_t *field, bool to_kernel)
215 {
216     if (to_kernel) {
217         *field = s->irq_target[irq] & 0xff;
218     } else {
219         s->irq_target[irq] = *field & 0xff;
220     }
221 }
222 
223 static void translate_sgisource(GICState *s, int irq, int cpu,
224                                 uint32_t *field, bool to_kernel)
225 {
226     if (to_kernel) {
227         *field = s->sgi_pending[irq][cpu] & 0xff;
228     } else {
229         s->sgi_pending[irq][cpu] = *field & 0xff;
230     }
231 }
232 
233 /* Read a register group from the kernel VGIC */
234 static void kvm_dist_get(GICState *s, uint32_t offset, int width,
235                          int maxirq, vgic_translate_fn translate_fn)
236 {
237     uint32_t reg;
238     int i;
239     int j;
240     int irq;
241     int cpu;
242     int regsz = 32 / width; /* irqs per kernel register */
243     uint32_t field;
244 
245     for_each_irq_reg(i, maxirq, width) {
246         irq = i * regsz;
247         cpu = 0;
248         while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
249             kvm_gicd_access(s, offset, cpu, &reg, false);
250             for (j = 0; j < regsz; j++) {
251                 field = extract32(reg, j * width, width);
252                 translate_fn(s, irq + j, cpu, &field, false);
253             }
254 
255             cpu++;
256         }
257         offset += 4;
258     }
259 }
260 
261 /* Write a register group to the kernel VGIC */
262 static void kvm_dist_put(GICState *s, uint32_t offset, int width,
263                          int maxirq, vgic_translate_fn translate_fn)
264 {
265     uint32_t reg;
266     int i;
267     int j;
268     int irq;
269     int cpu;
270     int regsz = 32 / width; /* irqs per kernel register */
271     uint32_t field;
272 
273     for_each_irq_reg(i, maxirq, width) {
274         irq = i * regsz;
275         cpu = 0;
276         while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
277             reg = 0;
278             for (j = 0; j < regsz; j++) {
279                 translate_fn(s, irq + j, cpu, &field, true);
280                 reg = deposit32(reg, j * width, width, field);
281             }
282             kvm_gicd_access(s, offset, cpu, &reg, true);
283 
284             cpu++;
285         }
286         offset += 4;
287     }
288 }
289 
290 static void kvm_arm_gic_put(GICState *s)
291 {
292     uint32_t reg;
293     int i;
294     int cpu;
295     int num_cpu;
296     int num_irq;
297 
298     /* Note: We do the restore in a slightly different order than the save
299      * (where the order doesn't matter and is simply ordered according to the
300      * register offset values */
301 
302     /*****************************************************************
303      * Distributor State
304      */
305 
306     /* s->ctlr -> GICD_CTLR */
307     reg = s->ctlr;
308     kvm_gicd_access(s, 0x0, 0, &reg, true);
309 
310     /* Sanity checking on GICD_TYPER and s->num_irq, s->num_cpu */
311     kvm_gicd_access(s, 0x4, 0, &reg, false);
312     num_irq = ((reg & 0x1f) + 1) * 32;
313     num_cpu = ((reg & 0xe0) >> 5) + 1;
314 
315     if (num_irq < s->num_irq) {
316             fprintf(stderr, "Restoring %u IRQs, but kernel supports max %d\n",
317                     s->num_irq, num_irq);
318             abort();
319     } else if (num_cpu != s->num_cpu) {
320             fprintf(stderr, "Restoring %u CPU interfaces, kernel only has %d\n",
321                     s->num_cpu, num_cpu);
322             /* Did we not create the VCPUs in the kernel yet? */
323             abort();
324     }
325 
326     /* TODO: Consider checking compatibility with the IIDR ? */
327 
328     /* irq_state[n].enabled -> GICD_ISENABLERn */
329     kvm_dist_put(s, 0x180, 1, s->num_irq, translate_clear);
330     kvm_dist_put(s, 0x100, 1, s->num_irq, translate_enabled);
331 
332     /* irq_state[n].group -> GICD_IGROUPRn */
333     kvm_dist_put(s, 0x80, 1, s->num_irq, translate_group);
334 
335     /* s->irq_target[irq] -> GICD_ITARGETSRn
336      * (restore targets before pending to ensure the pending state is set on
337      * the appropriate CPU interfaces in the kernel) */
338     kvm_dist_put(s, 0x800, 8, s->num_irq, translate_targets);
339 
340     /* irq_state[n].trigger -> GICD_ICFGRn
341      * (restore configuration registers before pending IRQs so we treat
342      * level/edge correctly) */
343     kvm_dist_put(s, 0xc00, 2, s->num_irq, translate_trigger);
344 
345     /* irq_state[n].pending + irq_state[n].level -> GICD_ISPENDRn */
346     kvm_dist_put(s, 0x280, 1, s->num_irq, translate_clear);
347     kvm_dist_put(s, 0x200, 1, s->num_irq, translate_pending);
348 
349     /* irq_state[n].active -> GICD_ISACTIVERn */
350     kvm_dist_put(s, 0x380, 1, s->num_irq, translate_clear);
351     kvm_dist_put(s, 0x300, 1, s->num_irq, translate_active);
352 
353 
354     /* s->priorityX[irq] -> ICD_IPRIORITYRn */
355     kvm_dist_put(s, 0x400, 8, s->num_irq, translate_priority);
356 
357     /* s->sgi_pending -> ICD_CPENDSGIRn */
358     kvm_dist_put(s, 0xf10, 8, GIC_NR_SGIS, translate_clear);
359     kvm_dist_put(s, 0xf20, 8, GIC_NR_SGIS, translate_sgisource);
360 
361 
362     /*****************************************************************
363      * CPU Interface(s) State
364      */
365 
366     for (cpu = 0; cpu < s->num_cpu; cpu++) {
367         /* s->cpu_ctlr[cpu] -> GICC_CTLR */
368         reg = s->cpu_ctlr[cpu];
369         kvm_gicc_access(s, 0x00, cpu, &reg, true);
370 
371         /* s->priority_mask[cpu] -> GICC_PMR */
372         reg = (s->priority_mask[cpu] & 0xff);
373         kvm_gicc_access(s, 0x04, cpu, &reg, true);
374 
375         /* s->bpr[cpu] -> GICC_BPR */
376         reg = (s->bpr[cpu] & 0x7);
377         kvm_gicc_access(s, 0x08, cpu, &reg, true);
378 
379         /* s->abpr[cpu] -> GICC_ABPR */
380         reg = (s->abpr[cpu] & 0x7);
381         kvm_gicc_access(s, 0x1c, cpu, &reg, true);
382 
383         /* s->apr[n][cpu] -> GICC_APRn */
384         for (i = 0; i < 4; i++) {
385             reg = s->apr[i][cpu];
386             kvm_gicc_access(s, 0xd0 + i * 4, cpu, &reg, true);
387         }
388     }
389 }
390 
391 static void kvm_arm_gic_get(GICState *s)
392 {
393     uint32_t reg;
394     int i;
395     int cpu;
396 
397     /*****************************************************************
398      * Distributor State
399      */
400 
401     /* GICD_CTLR -> s->ctlr */
402     kvm_gicd_access(s, 0x0, 0, &reg, false);
403     s->ctlr = reg;
404 
405     /* Sanity checking on GICD_TYPER -> s->num_irq, s->num_cpu */
406     kvm_gicd_access(s, 0x4, 0, &reg, false);
407     s->num_irq = ((reg & 0x1f) + 1) * 32;
408     s->num_cpu = ((reg & 0xe0) >> 5) + 1;
409 
410     if (s->num_irq > GIC_MAXIRQ) {
411             fprintf(stderr, "Too many IRQs reported from the kernel: %d\n",
412                     s->num_irq);
413             abort();
414     }
415 
416     /* GICD_IIDR -> ? */
417     kvm_gicd_access(s, 0x8, 0, &reg, false);
418 
419     /* Clear all the IRQ settings */
420     for (i = 0; i < s->num_irq; i++) {
421         memset(&s->irq_state[i], 0, sizeof(s->irq_state[0]));
422     }
423 
424     /* GICD_IGROUPRn -> irq_state[n].group */
425     kvm_dist_get(s, 0x80, 1, s->num_irq, translate_group);
426 
427     /* GICD_ISENABLERn -> irq_state[n].enabled */
428     kvm_dist_get(s, 0x100, 1, s->num_irq, translate_enabled);
429 
430     /* GICD_ISPENDRn -> irq_state[n].pending + irq_state[n].level */
431     kvm_dist_get(s, 0x200, 1, s->num_irq, translate_pending);
432 
433     /* GICD_ISACTIVERn -> irq_state[n].active */
434     kvm_dist_get(s, 0x300, 1, s->num_irq, translate_active);
435 
436     /* GICD_ICFRn -> irq_state[n].trigger */
437     kvm_dist_get(s, 0xc00, 2, s->num_irq, translate_trigger);
438 
439     /* GICD_IPRIORITYRn -> s->priorityX[irq] */
440     kvm_dist_get(s, 0x400, 8, s->num_irq, translate_priority);
441 
442     /* GICD_ITARGETSRn -> s->irq_target[irq] */
443     kvm_dist_get(s, 0x800, 8, s->num_irq, translate_targets);
444 
445     /* GICD_CPENDSGIRn -> s->sgi_pending */
446     kvm_dist_get(s, 0xf10, 8, GIC_NR_SGIS, translate_sgisource);
447 
448 
449     /*****************************************************************
450      * CPU Interface(s) State
451      */
452 
453     for (cpu = 0; cpu < s->num_cpu; cpu++) {
454         /* GICC_CTLR -> s->cpu_ctlr[cpu] */
455         kvm_gicc_access(s, 0x00, cpu, &reg, false);
456         s->cpu_ctlr[cpu] = reg;
457 
458         /* GICC_PMR -> s->priority_mask[cpu] */
459         kvm_gicc_access(s, 0x04, cpu, &reg, false);
460         s->priority_mask[cpu] = (reg & 0xff);
461 
462         /* GICC_BPR -> s->bpr[cpu] */
463         kvm_gicc_access(s, 0x08, cpu, &reg, false);
464         s->bpr[cpu] = (reg & 0x7);
465 
466         /* GICC_ABPR -> s->abpr[cpu] */
467         kvm_gicc_access(s, 0x1c, cpu, &reg, false);
468         s->abpr[cpu] = (reg & 0x7);
469 
470         /* GICC_APRn -> s->apr[n][cpu] */
471         for (i = 0; i < 4; i++) {
472             kvm_gicc_access(s, 0xd0 + i * 4, cpu, &reg, false);
473             s->apr[i][cpu] = reg;
474         }
475     }
476 }
477 
478 static void kvm_arm_gic_reset(DeviceState *dev)
479 {
480     GICState *s = ARM_GIC_COMMON(dev);
481     KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
482 
483     kgc->parent_reset(dev);
484 
485     if (kvm_arm_gic_can_save_restore(s)) {
486         kvm_arm_gic_put(s);
487     }
488 }
489 
490 static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
491 {
492     int i;
493     GICState *s = KVM_ARM_GIC(dev);
494     KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
495     Error *local_err = NULL;
496     int ret;
497 
498     kgc->parent_realize(dev, &local_err);
499     if (local_err) {
500         error_propagate(errp, local_err);
501         return;
502     }
503 
504     if (s->security_extn) {
505         error_setg(errp, "the in-kernel VGIC does not implement the "
506                    "security extensions");
507         return;
508     }
509 
510     if (s->virt_extn) {
511         error_setg(errp, "the in-kernel VGIC does not implement the "
512                    "virtualization extensions");
513         return;
514     }
515 
516     if (!kvm_arm_gic_can_save_restore(s)) {
517         error_setg(&s->migration_blocker, "This operating system kernel does "
518                                           "not support vGICv2 migration");
519         if (migrate_add_blocker(s->migration_blocker, errp) < 0) {
520             error_free(s->migration_blocker);
521             return;
522         }
523     }
524 
525     gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL, NULL);
526 
527     for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
528         qemu_irq irq = qdev_get_gpio_in(dev, i);
529         kvm_irqchip_set_qemuirq_gsi(kvm_state, irq, i);
530     }
531 
532     /* Try to create the device via the device control API */
533     s->dev_fd = -1;
534     ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
535     if (ret >= 0) {
536         s->dev_fd = ret;
537 
538         /* Newstyle API is used, we may have attributes */
539         if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
540             uint32_t numirqs = s->num_irq;
541             kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0,
542                               &numirqs, true, &error_abort);
543         }
544         /* Tell the kernel to complete VGIC initialization now */
545         if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
546                                   KVM_DEV_ARM_VGIC_CTRL_INIT)) {
547             kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
548                               KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true,
549                               &error_abort);
550         }
551     } else if (kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) {
552         error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
553         error_append_hint(errp,
554                           "Perhaps the host CPU does not support GICv2?\n");
555     } else if (ret != -ENODEV && ret != -ENOTSUP) {
556         /*
557          * Very ancient kernel without KVM_CAP_DEVICE_CTRL: assume that
558          * ENODEV or ENOTSUP mean "can't create GICv2 with KVM_CREATE_DEVICE",
559          * and that we will get a GICv2 via KVM_CREATE_IRQCHIP.
560          */
561         error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
562         return;
563     }
564 
565     /* Distributor */
566     kvm_arm_register_device(&s->iomem,
567                             (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
568                             | KVM_VGIC_V2_ADDR_TYPE_DIST,
569                             KVM_DEV_ARM_VGIC_GRP_ADDR,
570                             KVM_VGIC_V2_ADDR_TYPE_DIST,
571                             s->dev_fd, 0);
572     /* CPU interface for current core. Unlike arm_gic, we don't
573      * provide the "interface for core #N" memory regions, because
574      * cores with a VGIC don't have those.
575      */
576     kvm_arm_register_device(&s->cpuiomem[0],
577                             (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
578                             | KVM_VGIC_V2_ADDR_TYPE_CPU,
579                             KVM_DEV_ARM_VGIC_GRP_ADDR,
580                             KVM_VGIC_V2_ADDR_TYPE_CPU,
581                             s->dev_fd, 0);
582 
583     if (kvm_has_gsi_routing()) {
584         /* set up irq routing */
585         for (i = 0; i < s->num_irq - GIC_INTERNAL; ++i) {
586             kvm_irqchip_add_irq_route(kvm_state, i, 0, i);
587         }
588 
589         kvm_gsi_routing_allowed = true;
590 
591         kvm_irqchip_commit_routes(kvm_state);
592     }
593 }
594 
595 static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
596 {
597     DeviceClass *dc = DEVICE_CLASS(klass);
598     ARMGICCommonClass *agcc = ARM_GIC_COMMON_CLASS(klass);
599     KVMARMGICClass *kgc = KVM_ARM_GIC_CLASS(klass);
600 
601     agcc->pre_save = kvm_arm_gic_get;
602     agcc->post_load = kvm_arm_gic_put;
603     device_class_set_parent_realize(dc, kvm_arm_gic_realize,
604                                     &kgc->parent_realize);
605     device_class_set_parent_reset(dc, kvm_arm_gic_reset, &kgc->parent_reset);
606 }
607 
608 static const TypeInfo kvm_arm_gic_info = {
609     .name = TYPE_KVM_ARM_GIC,
610     .parent = TYPE_ARM_GIC_COMMON,
611     .instance_size = sizeof(GICState),
612     .class_init = kvm_arm_gic_class_init,
613     .class_size = sizeof(KVMARMGICClass),
614 };
615 
616 static void kvm_arm_gic_register_types(void)
617 {
618     type_register_static(&kvm_arm_gic_info);
619 }
620 
621 type_init(kvm_arm_gic_register_types)
622