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