qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

s390_flic_kvm.c (18800B)


      1 /*
      2  * QEMU S390x KVM floating interrupt controller (flic)
      3  *
      4  * Copyright 2014 IBM Corp.
      5  * Author(s): Jens Freimann <jfrei@linux.vnet.ibm.com>
      6  *            Cornelia Huck <cornelia.huck@de.ibm.com>
      7  *
      8  * This work is licensed under the terms of the GNU GPL, version 2 or (at
      9  * your option) any later version. See the COPYING file in the top-level
     10  * directory.
     11  */
     12 
     13 #include "qemu/osdep.h"
     14 #include "kvm/kvm_s390x.h"
     15 #include <sys/ioctl.h>
     16 #include "qemu/error-report.h"
     17 #include "qemu/module.h"
     18 #include "qapi/error.h"
     19 #include "sysemu/kvm.h"
     20 #include "hw/s390x/s390_flic.h"
     21 #include "hw/s390x/adapter.h"
     22 #include "hw/s390x/css.h"
     23 #include "migration/qemu-file-types.h"
     24 #include "trace.h"
     25 #include "qom/object.h"
     26 
     27 #define FLIC_SAVE_INITIAL_SIZE qemu_real_host_page_size()
     28 #define FLIC_FAILED (-1UL)
     29 #define FLIC_SAVEVM_VERSION 1
     30 
     31 struct KVMS390FLICState{
     32     S390FLICState parent_obj;
     33 
     34     uint32_t fd;
     35     bool clear_io_supported;
     36 };
     37 
     38 static KVMS390FLICState *s390_get_kvm_flic(S390FLICState *fs)
     39 {
     40     static KVMS390FLICState *flic;
     41 
     42     if (!flic) {
     43         /* we only have one flic device, so this is fine to cache */
     44         flic = KVM_S390_FLIC(fs);
     45     }
     46     return flic;
     47 }
     48 
     49 /**
     50  * flic_get_all_irqs - store all pending irqs in buffer
     51  * @buf: pointer to buffer which is passed to kernel
     52  * @len: length of buffer
     53  * @flic: pointer to flic device state
     54  *
     55  * Returns: -ENOMEM if buffer is too small,
     56  * -EINVAL if attr.group is invalid,
     57  * -EFAULT if copying to userspace failed,
     58  * on success return number of stored interrupts
     59  */
     60 static int flic_get_all_irqs(KVMS390FLICState *flic,
     61                              void *buf, int len)
     62 {
     63     struct kvm_device_attr attr = {
     64         .group = KVM_DEV_FLIC_GET_ALL_IRQS,
     65         .addr = (uint64_t) buf,
     66         .attr = len,
     67     };
     68     int rc;
     69 
     70     rc = ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr);
     71 
     72     return rc == -1 ? -errno : rc;
     73 }
     74 
     75 static void flic_enable_pfault(KVMS390FLICState *flic)
     76 {
     77     struct kvm_device_attr attr = {
     78         .group = KVM_DEV_FLIC_APF_ENABLE,
     79     };
     80     int rc;
     81 
     82     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
     83 
     84     if (rc) {
     85         fprintf(stderr, "flic: couldn't enable pfault\n");
     86     }
     87 }
     88 
     89 static void flic_disable_wait_pfault(KVMS390FLICState *flic)
     90 {
     91     struct kvm_device_attr attr = {
     92         .group = KVM_DEV_FLIC_APF_DISABLE_WAIT,
     93     };
     94     int rc;
     95 
     96     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
     97 
     98     if (rc) {
     99         fprintf(stderr, "flic: couldn't disable pfault\n");
    100     }
    101 }
    102 
    103 /** flic_enqueue_irqs - returns 0 on success
    104  * @buf: pointer to buffer which is passed to kernel
    105  * @len: length of buffer
    106  * @flic: pointer to flic device state
    107  *
    108  * Returns: -EINVAL if attr.group is unknown
    109  */
    110 static int flic_enqueue_irqs(void *buf, uint64_t len,
    111                             KVMS390FLICState *flic)
    112 {
    113     int rc;
    114     struct kvm_device_attr attr = {
    115         .group = KVM_DEV_FLIC_ENQUEUE,
    116         .addr = (uint64_t) buf,
    117         .attr = len,
    118     };
    119 
    120     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
    121 
    122     return rc ? -errno : 0;
    123 }
    124 
    125 static void kvm_s390_inject_flic(S390FLICState *fs, struct kvm_s390_irq *irq)
    126 {
    127     static bool use_flic = true;
    128     int r;
    129 
    130     if (use_flic) {
    131         r = flic_enqueue_irqs(irq, sizeof(*irq), s390_get_kvm_flic(fs));
    132         if (r == -ENOSYS) {
    133             use_flic = false;
    134         }
    135         if (!r) {
    136             return;
    137         }
    138     }
    139     /* fallback to legacy KVM IOCTL in case FLIC fails */
    140     kvm_s390_floating_interrupt_legacy(irq);
    141 }
    142 
    143 static void kvm_s390_inject_service(S390FLICState *fs, uint32_t parm)
    144 {
    145         struct kvm_s390_irq irq = {
    146         .type = KVM_S390_INT_SERVICE,
    147         .u.ext.ext_params = parm,
    148     };
    149 
    150     kvm_s390_inject_flic(fs, &irq);
    151 }
    152 
    153 static void kvm_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id,
    154                                uint16_t subchannel_nr, uint32_t io_int_parm,
    155                                uint32_t io_int_word)
    156 {
    157     struct kvm_s390_irq irq = {
    158         .u.io.subchannel_id = subchannel_id,
    159         .u.io.subchannel_nr = subchannel_nr,
    160         .u.io.io_int_parm = io_int_parm,
    161         .u.io.io_int_word = io_int_word,
    162     };
    163 
    164     if (io_int_word & IO_INT_WORD_AI) {
    165         irq.type = KVM_S390_INT_IO(1, 0, 0, 0);
    166     } else {
    167         irq.type = KVM_S390_INT_IO(0, (subchannel_id & 0xff00) >> 8,
    168                                       (subchannel_id & 0x0006),
    169                                       subchannel_nr);
    170     }
    171     kvm_s390_inject_flic(fs, &irq);
    172 }
    173 
    174 static void kvm_s390_inject_crw_mchk(S390FLICState *fs)
    175 {
    176     struct kvm_s390_irq irq = {
    177         .type = KVM_S390_MCHK,
    178         .u.mchk.cr14 = CR14_CHANNEL_REPORT_SC,
    179         .u.mchk.mcic = s390_build_validity_mcic() | MCIC_SC_CP,
    180     };
    181 
    182     kvm_s390_inject_flic(fs, &irq);
    183 }
    184 
    185 static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
    186                            uint16_t subchannel_nr)
    187 {
    188     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
    189     int rc;
    190     uint32_t sid = subchannel_id << 16 | subchannel_nr;
    191     struct kvm_device_attr attr = {
    192         .group = KVM_DEV_FLIC_CLEAR_IO_IRQ,
    193         .addr = (uint64_t) &sid,
    194         .attr = sizeof(sid),
    195     };
    196     if (unlikely(!flic->clear_io_supported)) {
    197         return -ENOSYS;
    198     }
    199     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
    200     return rc ? -errno : 0;
    201 }
    202 
    203 static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
    204                                     uint16_t mode)
    205 {
    206     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
    207     struct kvm_s390_ais_req req = {
    208         .isc = isc,
    209         .mode = mode,
    210     };
    211     struct kvm_device_attr attr = {
    212         .group = KVM_DEV_FLIC_AISM,
    213         .addr = (uint64_t)&req,
    214     };
    215 
    216     if (!fs->ais_supported) {
    217         return -ENOSYS;
    218     }
    219 
    220     return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
    221 }
    222 
    223 static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type,
    224                                 uint8_t isc, uint8_t flags)
    225 {
    226     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
    227     uint32_t id = css_get_adapter_id(type, isc);
    228     struct kvm_device_attr attr = {
    229         .group = KVM_DEV_FLIC_AIRQ_INJECT,
    230         .attr = id,
    231     };
    232 
    233     if (!fs->ais_supported) {
    234         return -ENOSYS;
    235     }
    236 
    237     return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
    238 }
    239 
    240 /**
    241  * __get_all_irqs - store all pending irqs in buffer
    242  * @flic: pointer to flic device state
    243  * @buf: pointer to pointer to a buffer
    244  * @len: length of buffer
    245  *
    246  * Returns: return value of flic_get_all_irqs
    247  * Note: Retry and increase buffer size until flic_get_all_irqs
    248  * either returns a value >= 0 or a negative error code.
    249  * -ENOMEM is an exception, which means the buffer is too small
    250  * and we should try again. Other negative error codes can be
    251  * -EFAULT and -EINVAL which we ignore at this point
    252  */
    253 static int __get_all_irqs(KVMS390FLICState *flic,
    254                           void **buf, int len)
    255 {
    256     int r;
    257 
    258     do {
    259         /* returns -ENOMEM if buffer is too small and number
    260          * of queued interrupts on success */
    261         r = flic_get_all_irqs(flic, *buf, len);
    262         if (r >= 0) {
    263             break;
    264         }
    265         len *= 2;
    266         *buf = g_try_realloc(*buf, len);
    267         if (!buf) {
    268             return -ENOMEM;
    269         }
    270     } while (r == -ENOMEM && len <= KVM_S390_FLIC_MAX_BUFFER);
    271 
    272     return r;
    273 }
    274 
    275 static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
    276                                         uint8_t isc, bool swap,
    277                                         bool is_maskable, uint8_t flags)
    278 {
    279     struct kvm_s390_io_adapter adapter = {
    280         .id = id,
    281         .isc = isc,
    282         .maskable = is_maskable,
    283         .swap = swap,
    284         .flags = flags,
    285     };
    286     KVMS390FLICState *flic = KVM_S390_FLIC(fs);
    287     int r;
    288     struct kvm_device_attr attr = {
    289         .group = KVM_DEV_FLIC_ADAPTER_REGISTER,
    290         .addr = (uint64_t)&adapter,
    291     };
    292 
    293     if (!kvm_gsi_routing_enabled()) {
    294         /* nothing to do */
    295         return 0;
    296     }
    297 
    298     r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
    299 
    300     return r ? -errno : 0;
    301 }
    302 
    303 static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
    304                                    uint64_t map_addr, bool do_map)
    305 {
    306     struct kvm_s390_io_adapter_req req = {
    307         .id = id,
    308         .type = do_map ? KVM_S390_IO_ADAPTER_MAP : KVM_S390_IO_ADAPTER_UNMAP,
    309         .addr = map_addr,
    310     };
    311     struct kvm_device_attr attr = {
    312         .group = KVM_DEV_FLIC_ADAPTER_MODIFY,
    313         .addr = (uint64_t)&req,
    314     };
    315     KVMS390FLICState *flic = s390_get_kvm_flic(fs);
    316     int r;
    317 
    318     if (!kvm_gsi_routing_enabled()) {
    319         /* nothing to do */
    320         return 0;
    321     }
    322 
    323     r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
    324     return r ? -errno : 0;
    325 }
    326 
    327 static int kvm_s390_add_adapter_routes(S390FLICState *fs,
    328                                        AdapterRoutes *routes)
    329 {
    330     int ret, i;
    331     uint64_t ind_offset = routes->adapter.ind_offset;
    332 
    333     if (!kvm_gsi_routing_enabled()) {
    334         return -ENOSYS;
    335     }
    336 
    337     for (i = 0; i < routes->num_routes; i++) {
    338         ret = kvm_irqchip_add_adapter_route(kvm_state, &routes->adapter);
    339         if (ret < 0) {
    340             goto out_undo;
    341         }
    342         routes->gsi[i] = ret;
    343         routes->adapter.ind_offset++;
    344     }
    345     kvm_irqchip_commit_routes(kvm_state);
    346 
    347     /* Restore passed-in structure to original state. */
    348     routes->adapter.ind_offset = ind_offset;
    349     return 0;
    350 out_undo:
    351     while (--i >= 0) {
    352         kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
    353         routes->gsi[i] = -1;
    354     }
    355     routes->adapter.ind_offset = ind_offset;
    356     return ret;
    357 }
    358 
    359 static void kvm_s390_release_adapter_routes(S390FLICState *fs,
    360                                             AdapterRoutes *routes)
    361 {
    362     int i;
    363 
    364     if (!kvm_gsi_routing_enabled()) {
    365         return;
    366     }
    367 
    368     for (i = 0; i < routes->num_routes; i++) {
    369         if (routes->gsi[i] >= 0) {
    370             kvm_irqchip_release_virq(kvm_state, routes->gsi[i]);
    371             routes->gsi[i] = -1;
    372         }
    373     }
    374 }
    375 
    376 /**
    377  * kvm_flic_save - Save pending floating interrupts
    378  * @f: QEMUFile containing migration state
    379  * @opaque: pointer to flic device state
    380  * @size: ignored
    381  *
    382  * Note: Pass buf and len to kernel. Start with one page and
    383  * increase until buffer is sufficient or maxium size is
    384  * reached
    385  */
    386 static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
    387                          const VMStateField *field, JSONWriter *vmdesc)
    388 {
    389     KVMS390FLICState *flic = opaque;
    390     int len = FLIC_SAVE_INITIAL_SIZE;
    391     void *buf;
    392     int count;
    393     int r = 0;
    394 
    395     flic_disable_wait_pfault((struct KVMS390FLICState *) opaque);
    396 
    397     buf = g_try_malloc0(len);
    398     if (!buf) {
    399         /* Storing FLIC_FAILED into the count field here will cause the
    400          * target system to fail when attempting to load irqs from the
    401          * migration state */
    402         error_report("flic: couldn't allocate memory");
    403         qemu_put_be64(f, FLIC_FAILED);
    404         return -ENOMEM;
    405     }
    406 
    407     count = __get_all_irqs(flic, &buf, len);
    408     if (count < 0) {
    409         error_report("flic: couldn't retrieve irqs from kernel, rc %d",
    410                      count);
    411         /* Storing FLIC_FAILED into the count field here will cause the
    412          * target system to fail when attempting to load irqs from the
    413          * migration state */
    414         qemu_put_be64(f, FLIC_FAILED);
    415         r = count;
    416     } else {
    417         qemu_put_be64(f, count);
    418         qemu_put_buffer(f, (uint8_t *) buf,
    419                         count * sizeof(struct kvm_s390_irq));
    420     }
    421     g_free(buf);
    422 
    423     return r;
    424 }
    425 
    426 /**
    427  * kvm_flic_load - Load pending floating interrupts
    428  * @f: QEMUFile containing migration state
    429  * @opaque: pointer to flic device state
    430  * @size: ignored
    431  *
    432  * Returns: value of flic_enqueue_irqs, -EINVAL on error
    433  * Note: Do nothing when no interrupts where stored
    434  * in QEMUFile
    435  */
    436 static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size,
    437                          const VMStateField *field)
    438 {
    439     uint64_t len = 0;
    440     uint64_t count = 0;
    441     void *buf = NULL;
    442     int r = 0;
    443 
    444     flic_enable_pfault((struct KVMS390FLICState *) opaque);
    445 
    446     count = qemu_get_be64(f);
    447     len = count * sizeof(struct kvm_s390_irq);
    448     if (count == FLIC_FAILED) {
    449         return -EINVAL;
    450     }
    451     if (count == 0) {
    452         return 0;
    453     }
    454     buf = g_try_malloc0(len);
    455     if (!buf) {
    456         return -ENOMEM;
    457     }
    458 
    459     if (qemu_get_buffer(f, (uint8_t *) buf, len) != len) {
    460         r = -EINVAL;
    461         goto out_free;
    462     }
    463     r = flic_enqueue_irqs(buf, len, (struct KVMS390FLICState *) opaque);
    464 
    465 out_free:
    466     g_free(buf);
    467     return r;
    468 }
    469 
    470 typedef struct KVMS390FLICStateMigTmp {
    471     KVMS390FLICState *parent;
    472     uint8_t simm;
    473     uint8_t nimm;
    474 } KVMS390FLICStateMigTmp;
    475 
    476 static int kvm_flic_ais_pre_save(void *opaque)
    477 {
    478     KVMS390FLICStateMigTmp *tmp = opaque;
    479     KVMS390FLICState *flic = tmp->parent;
    480     struct kvm_s390_ais_all ais;
    481     struct kvm_device_attr attr = {
    482         .group = KVM_DEV_FLIC_AISM_ALL,
    483         .addr = (uint64_t)&ais,
    484         .attr = sizeof(ais),
    485     };
    486 
    487     if (ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr)) {
    488         error_report("Failed to retrieve kvm flic ais states");
    489         return -EINVAL;
    490     }
    491 
    492     tmp->simm = ais.simm;
    493     tmp->nimm = ais.nimm;
    494 
    495     return 0;
    496 }
    497 
    498 static int kvm_flic_ais_post_load(void *opaque, int version_id)
    499 {
    500     KVMS390FLICStateMigTmp *tmp = opaque;
    501     KVMS390FLICState *flic = tmp->parent;
    502     struct kvm_s390_ais_all ais = {
    503         .simm = tmp->simm,
    504         .nimm = tmp->nimm,
    505     };
    506     struct kvm_device_attr attr = {
    507         .group = KVM_DEV_FLIC_AISM_ALL,
    508         .addr = (uint64_t)&ais,
    509     };
    510 
    511     /* This can happen when the user mis-configures its guests in an
    512      * incompatible fashion or without a CPU model. For example using
    513      * qemu with -cpu host (which is not migration safe) and do a
    514      * migration from a host that has AIS to a host that has no AIS.
    515      * In that case the target system will reject the migration here.
    516      */
    517     if (!ais_needed(flic)) {
    518         return -ENOSYS;
    519     }
    520 
    521     return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
    522 }
    523 
    524 static const VMStateDescription kvm_s390_flic_ais_tmp = {
    525     .name = "s390-flic-ais-tmp",
    526     .pre_save = kvm_flic_ais_pre_save,
    527     .post_load = kvm_flic_ais_post_load,
    528     .fields = (VMStateField[]) {
    529         VMSTATE_UINT8(simm, KVMS390FLICStateMigTmp),
    530         VMSTATE_UINT8(nimm, KVMS390FLICStateMigTmp),
    531         VMSTATE_END_OF_LIST()
    532     }
    533 };
    534 
    535 static const VMStateDescription kvm_s390_flic_vmstate_ais = {
    536     .name = "s390-flic/ais",
    537     .version_id = 1,
    538     .minimum_version_id = 1,
    539     .needed = ais_needed,
    540     .fields = (VMStateField[]) {
    541         VMSTATE_WITH_TMP(KVMS390FLICState, KVMS390FLICStateMigTmp,
    542                          kvm_s390_flic_ais_tmp),
    543         VMSTATE_END_OF_LIST()
    544     }
    545 };
    546 
    547 static const VMStateDescription kvm_s390_flic_vmstate = {
    548     /* should have been like kvm-s390-flic,
    549      * can't change without breaking compat */
    550     .name = "s390-flic",
    551     .version_id = FLIC_SAVEVM_VERSION,
    552     .minimum_version_id = FLIC_SAVEVM_VERSION,
    553     .fields = (VMStateField[]) {
    554         {
    555             .name = "irqs",
    556             .info = &(const VMStateInfo) {
    557                 .name = "irqs",
    558                 .get = kvm_flic_load,
    559                 .put = kvm_flic_save,
    560             },
    561             .flags = VMS_SINGLE,
    562         },
    563         VMSTATE_END_OF_LIST()
    564     },
    565     .subsections = (const VMStateDescription * []) {
    566         &kvm_s390_flic_vmstate_ais,
    567         NULL
    568     }
    569 };
    570 
    571 struct KVMS390FLICStateClass {
    572     S390FLICStateClass parent_class;
    573     DeviceRealize parent_realize;
    574 };
    575 typedef struct KVMS390FLICStateClass KVMS390FLICStateClass;
    576 
    577 DECLARE_CLASS_CHECKERS(KVMS390FLICStateClass, KVM_S390_FLIC,
    578                        TYPE_KVM_S390_FLIC)
    579 
    580 
    581 static void kvm_s390_flic_realize(DeviceState *dev, Error **errp)
    582 {
    583     KVMS390FLICState *flic_state = KVM_S390_FLIC(dev);
    584     struct kvm_create_device cd = {0};
    585     struct kvm_device_attr test_attr = {0};
    586     int ret;
    587     Error *err = NULL;
    588 
    589     KVM_S390_FLIC_GET_CLASS(dev)->parent_realize(dev, &err);
    590     if (err) {
    591         error_propagate(errp, err);
    592         return;
    593     }
    594     flic_state->fd = -1;
    595 
    596     cd.type = KVM_DEV_TYPE_FLIC;
    597     ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
    598     if (ret < 0) {
    599         error_setg_errno(errp, errno, "Creating the KVM device failed");
    600         trace_flic_create_device(errno);
    601         return;
    602     }
    603     flic_state->fd = cd.fd;
    604 
    605     /* Check clear_io_irq support */
    606     test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ;
    607     flic_state->clear_io_supported = !ioctl(flic_state->fd,
    608                                             KVM_HAS_DEVICE_ATTR, test_attr);
    609 }
    610 
    611 static void kvm_s390_flic_reset(DeviceState *dev)
    612 {
    613     KVMS390FLICState *flic = KVM_S390_FLIC(dev);
    614     S390FLICState *fs = S390_FLIC_COMMON(dev);
    615     struct kvm_device_attr attr = {
    616         .group = KVM_DEV_FLIC_CLEAR_IRQS,
    617     };
    618     int rc = 0;
    619     uint8_t isc;
    620 
    621     if (flic->fd == -1) {
    622         return;
    623     }
    624 
    625     flic_disable_wait_pfault(flic);
    626 
    627     if (fs->ais_supported) {
    628         for (isc = 0; isc <= MAX_ISC; isc++) {
    629             rc = kvm_s390_modify_ais_mode(fs, isc, SIC_IRQ_MODE_ALL);
    630             if (rc) {
    631                 error_report("Failed to reset ais mode for isc %d: %s",
    632                              isc, strerror(-rc));
    633             }
    634         }
    635     }
    636 
    637     rc = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
    638     if (rc) {
    639         trace_flic_reset_failed(errno);
    640     }
    641 
    642     flic_enable_pfault(flic);
    643 }
    644 
    645 static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
    646 {
    647     DeviceClass *dc = DEVICE_CLASS(oc);
    648     S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc);
    649 
    650     KVM_S390_FLIC_CLASS(oc)->parent_realize = dc->realize;
    651     dc->realize = kvm_s390_flic_realize;
    652     dc->vmsd = &kvm_s390_flic_vmstate;
    653     dc->reset = kvm_s390_flic_reset;
    654     fsc->register_io_adapter = kvm_s390_register_io_adapter;
    655     fsc->io_adapter_map = kvm_s390_io_adapter_map;
    656     fsc->add_adapter_routes = kvm_s390_add_adapter_routes;
    657     fsc->release_adapter_routes = kvm_s390_release_adapter_routes;
    658     fsc->clear_io_irq = kvm_s390_clear_io_flic;
    659     fsc->modify_ais_mode = kvm_s390_modify_ais_mode;
    660     fsc->inject_airq = kvm_s390_inject_airq;
    661     fsc->inject_service = kvm_s390_inject_service;
    662     fsc->inject_io = kvm_s390_inject_io;
    663     fsc->inject_crw_mchk = kvm_s390_inject_crw_mchk;
    664 }
    665 
    666 static const TypeInfo kvm_s390_flic_info = {
    667     .name          = TYPE_KVM_S390_FLIC,
    668     .parent        = TYPE_S390_FLIC_COMMON,
    669     .instance_size = sizeof(KVMS390FLICState),
    670     .class_size    = sizeof(KVMS390FLICStateClass),
    671     .class_init    = kvm_s390_flic_class_init,
    672 };
    673 
    674 static void kvm_s390_flic_register_types(void)
    675 {
    676     type_register_static(&kvm_s390_flic_info);
    677 }
    678 
    679 type_init(kvm_s390_flic_register_types)