qemu/hw/intc/s390_flic_kvm.c
<<
>>
Prefs
   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)
 680