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