cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

s390_flic_kvm.c (18798B)


      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
     31struct KVMS390FLICState{
     32    S390FLICState parent_obj;
     33
     34    uint32_t fd;
     35    bool clear_io_supported;
     36};
     37
     38static 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 */
     60static 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
     75static 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
     89static 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 */
    110static 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
    125static 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
    143static 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
    153static 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
    174static 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
    185static 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
    203static 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
    223static 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 */
    253static 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
    275static 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
    303static 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
    327static 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;
    350out_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
    359static 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 */
    386static 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 */
    436static 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
    465out_free:
    466    g_free(buf);
    467    return r;
    468}
    469
    470typedef struct KVMS390FLICStateMigTmp {
    471    KVMS390FLICState *parent;
    472    uint8_t simm;
    473    uint8_t nimm;
    474} KVMS390FLICStateMigTmp;
    475
    476static 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
    498static 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
    524static 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
    535static 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
    547static 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
    571struct KVMS390FLICStateClass {
    572    S390FLICStateClass parent_class;
    573    DeviceRealize parent_realize;
    574};
    575typedef struct KVMS390FLICStateClass KVMS390FLICStateClass;
    576
    577DECLARE_CLASS_CHECKERS(KVMS390FLICStateClass, KVM_S390_FLIC,
    578                       TYPE_KVM_S390_FLIC)
    579
    580
    581static 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
    611static 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
    645static 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
    666static 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
    674static void kvm_s390_flic_register_types(void)
    675{
    676    type_register_static(&kvm_s390_flic_info);
    677}
    678
    679type_init(kvm_s390_flic_register_types)