qemu

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

virtio-ccw.c (41333B)


      1 /*
      2  * virtio ccw target implementation
      3  *
      4  * Copyright 2012,2015 IBM Corp.
      5  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
      6  *            Pierre Morel <pmorel@linux.vnet.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 "qapi/error.h"
     15 #include "exec/address-spaces.h"
     16 #include "sysemu/kvm.h"
     17 #include "net/net.h"
     18 #include "hw/virtio/virtio.h"
     19 #include "migration/qemu-file-types.h"
     20 #include "hw/virtio/virtio-net.h"
     21 #include "qemu/bitops.h"
     22 #include "qemu/error-report.h"
     23 #include "qemu/log.h"
     24 #include "qemu/module.h"
     25 #include "hw/virtio/virtio-access.h"
     26 #include "hw/virtio/virtio-bus.h"
     27 #include "hw/s390x/adapter.h"
     28 #include "hw/s390x/s390_flic.h"
     29 
     30 #include "hw/s390x/ioinst.h"
     31 #include "hw/s390x/css.h"
     32 #include "virtio-ccw.h"
     33 #include "trace.h"
     34 #include "hw/s390x/css-bridge.h"
     35 #include "hw/s390x/s390-virtio-ccw.h"
     36 #include "sysemu/replay.h"
     37 
     38 #define NR_CLASSIC_INDICATOR_BITS 64
     39 
     40 bool have_virtio_ccw = true;
     41 
     42 static int virtio_ccw_dev_post_load(void *opaque, int version_id)
     43 {
     44     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(opaque);
     45     CcwDevice *ccw_dev = CCW_DEVICE(dev);
     46     CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
     47 
     48     ccw_dev->sch->driver_data = dev;
     49     if (ccw_dev->sch->thinint_active) {
     50         dev->routes.adapter.adapter_id = css_get_adapter_id(
     51                                          CSS_IO_ADAPTER_VIRTIO,
     52                                          dev->thinint_isc);
     53     }
     54     /* Re-fill subch_id after loading the subchannel states.*/
     55     if (ck->refill_ids) {
     56         ck->refill_ids(ccw_dev);
     57     }
     58     return 0;
     59 }
     60 
     61 typedef struct VirtioCcwDeviceTmp {
     62     VirtioCcwDevice *parent;
     63     uint16_t config_vector;
     64 } VirtioCcwDeviceTmp;
     65 
     66 static int virtio_ccw_dev_tmp_pre_save(void *opaque)
     67 {
     68     VirtioCcwDeviceTmp *tmp = opaque;
     69     VirtioCcwDevice *dev = tmp->parent;
     70     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
     71 
     72     tmp->config_vector = vdev->config_vector;
     73 
     74     return 0;
     75 }
     76 
     77 static int virtio_ccw_dev_tmp_post_load(void *opaque, int version_id)
     78 {
     79     VirtioCcwDeviceTmp *tmp = opaque;
     80     VirtioCcwDevice *dev = tmp->parent;
     81     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
     82 
     83     vdev->config_vector = tmp->config_vector;
     84     return 0;
     85 }
     86 
     87 const VMStateDescription vmstate_virtio_ccw_dev_tmp = {
     88     .name = "s390_virtio_ccw_dev_tmp",
     89     .pre_save = virtio_ccw_dev_tmp_pre_save,
     90     .post_load = virtio_ccw_dev_tmp_post_load,
     91     .fields = (VMStateField[]) {
     92         VMSTATE_UINT16(config_vector, VirtioCcwDeviceTmp),
     93         VMSTATE_END_OF_LIST()
     94     }
     95 };
     96 
     97 const VMStateDescription vmstate_virtio_ccw_dev = {
     98     .name = "s390_virtio_ccw_dev",
     99     .version_id = 1,
    100     .minimum_version_id = 1,
    101     .post_load = virtio_ccw_dev_post_load,
    102     .fields = (VMStateField[]) {
    103         VMSTATE_CCW_DEVICE(parent_obj, VirtioCcwDevice),
    104         VMSTATE_PTR_TO_IND_ADDR(indicators, VirtioCcwDevice),
    105         VMSTATE_PTR_TO_IND_ADDR(indicators2, VirtioCcwDevice),
    106         VMSTATE_PTR_TO_IND_ADDR(summary_indicator, VirtioCcwDevice),
    107         /*
    108          * Ugly hack because VirtIODevice does not migrate itself.
    109          * This also makes legacy via vmstate_save_state possible.
    110          */
    111         VMSTATE_WITH_TMP(VirtioCcwDevice, VirtioCcwDeviceTmp,
    112                          vmstate_virtio_ccw_dev_tmp),
    113         VMSTATE_STRUCT(routes, VirtioCcwDevice, 1, vmstate_adapter_routes,
    114                        AdapterRoutes),
    115         VMSTATE_UINT8(thinint_isc, VirtioCcwDevice),
    116         VMSTATE_INT32(revision, VirtioCcwDevice),
    117         VMSTATE_END_OF_LIST()
    118     }
    119 };
    120 
    121 static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
    122                                VirtioCcwDevice *dev);
    123 
    124 VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
    125 {
    126     VirtIODevice *vdev = NULL;
    127     VirtioCcwDevice *dev = sch->driver_data;
    128 
    129     if (dev) {
    130         vdev = virtio_bus_get_device(&dev->bus);
    131     }
    132     return vdev;
    133 }
    134 
    135 static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
    136 {
    137     virtio_bus_start_ioeventfd(&dev->bus);
    138 }
    139 
    140 static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
    141 {
    142     virtio_bus_stop_ioeventfd(&dev->bus);
    143 }
    144 
    145 static bool virtio_ccw_ioeventfd_enabled(DeviceState *d)
    146 {
    147     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
    148 
    149     return (dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) != 0;
    150 }
    151 
    152 static int virtio_ccw_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
    153                                        int n, bool assign)
    154 {
    155     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
    156     CcwDevice *ccw_dev = CCW_DEVICE(dev);
    157     SubchDev *sch = ccw_dev->sch;
    158     uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
    159 
    160     return s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
    161 }
    162 
    163 /* Communication blocks used by several channel commands. */
    164 typedef struct VqInfoBlockLegacy {
    165     uint64_t queue;
    166     uint32_t align;
    167     uint16_t index;
    168     uint16_t num;
    169 } QEMU_PACKED VqInfoBlockLegacy;
    170 
    171 typedef struct VqInfoBlock {
    172     uint64_t desc;
    173     uint32_t res0;
    174     uint16_t index;
    175     uint16_t num;
    176     uint64_t avail;
    177     uint64_t used;
    178 } QEMU_PACKED VqInfoBlock;
    179 
    180 typedef struct VqConfigBlock {
    181     uint16_t index;
    182     uint16_t num_max;
    183 } QEMU_PACKED VqConfigBlock;
    184 
    185 typedef struct VirtioFeatDesc {
    186     uint32_t features;
    187     uint8_t index;
    188 } QEMU_PACKED VirtioFeatDesc;
    189 
    190 typedef struct VirtioThinintInfo {
    191     hwaddr summary_indicator;
    192     hwaddr device_indicator;
    193     uint64_t ind_bit;
    194     uint8_t isc;
    195 } QEMU_PACKED VirtioThinintInfo;
    196 
    197 typedef struct VirtioRevInfo {
    198     uint16_t revision;
    199     uint16_t length;
    200     uint8_t data[];
    201 } QEMU_PACKED VirtioRevInfo;
    202 
    203 /* Specify where the virtqueues for the subchannel are in guest memory. */
    204 static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
    205                               VqInfoBlockLegacy *linfo)
    206 {
    207     VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
    208     uint16_t index = info ? info->index : linfo->index;
    209     uint16_t num = info ? info->num : linfo->num;
    210     uint64_t desc = info ? info->desc : linfo->queue;
    211 
    212     if (index >= VIRTIO_QUEUE_MAX) {
    213         return -EINVAL;
    214     }
    215 
    216     /* Current code in virtio.c relies on 4K alignment. */
    217     if (linfo && desc && (linfo->align != 4096)) {
    218         return -EINVAL;
    219     }
    220 
    221     if (!vdev) {
    222         return -EINVAL;
    223     }
    224 
    225     if (info) {
    226         virtio_queue_set_rings(vdev, index, desc, info->avail, info->used);
    227     } else {
    228         virtio_queue_set_addr(vdev, index, desc);
    229     }
    230     if (!desc) {
    231         virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR);
    232     } else {
    233         if (info) {
    234             /* virtio-1 allows changing the ring size. */
    235             if (virtio_queue_get_max_num(vdev, index) < num) {
    236                 /* Fail if we exceed the maximum number. */
    237                 return -EINVAL;
    238             }
    239             virtio_queue_set_num(vdev, index, num);
    240         } else if (virtio_queue_get_num(vdev, index) > num) {
    241             /* Fail if we don't have a big enough queue. */
    242             return -EINVAL;
    243         }
    244         /* We ignore possible increased num for legacy for compatibility. */
    245         virtio_queue_set_vector(vdev, index, index);
    246     }
    247     /* tell notify handler in case of config change */
    248     vdev->config_vector = VIRTIO_QUEUE_MAX;
    249     return 0;
    250 }
    251 
    252 static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev)
    253 {
    254     CcwDevice *ccw_dev = CCW_DEVICE(dev);
    255 
    256     virtio_bus_reset(&dev->bus);
    257     if (dev->indicators) {
    258         release_indicator(&dev->routes.adapter, dev->indicators);
    259         dev->indicators = NULL;
    260     }
    261     if (dev->indicators2) {
    262         release_indicator(&dev->routes.adapter, dev->indicators2);
    263         dev->indicators2 = NULL;
    264     }
    265     if (dev->summary_indicator) {
    266         release_indicator(&dev->routes.adapter, dev->summary_indicator);
    267         dev->summary_indicator = NULL;
    268     }
    269     ccw_dev->sch->thinint_active = false;
    270 }
    271 
    272 static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
    273                                     bool is_legacy)
    274 {
    275     int ret;
    276     VqInfoBlock info;
    277     VqInfoBlockLegacy linfo;
    278     size_t info_len = is_legacy ? sizeof(linfo) : sizeof(info);
    279 
    280     if (check_len) {
    281         if (ccw.count != info_len) {
    282             return -EINVAL;
    283         }
    284     } else if (ccw.count < info_len) {
    285         /* Can't execute command. */
    286         return -EINVAL;
    287     }
    288     if (!ccw.cda) {
    289         return -EFAULT;
    290     }
    291     if (is_legacy) {
    292         ret = ccw_dstream_read(&sch->cds, linfo);
    293         if (ret) {
    294             return ret;
    295         }
    296         linfo.queue = be64_to_cpu(linfo.queue);
    297         linfo.align = be32_to_cpu(linfo.align);
    298         linfo.index = be16_to_cpu(linfo.index);
    299         linfo.num = be16_to_cpu(linfo.num);
    300         ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
    301     } else {
    302         ret = ccw_dstream_read(&sch->cds, info);
    303         if (ret) {
    304             return ret;
    305         }
    306         info.desc = be64_to_cpu(info.desc);
    307         info.index = be16_to_cpu(info.index);
    308         info.num = be16_to_cpu(info.num);
    309         info.avail = be64_to_cpu(info.avail);
    310         info.used = be64_to_cpu(info.used);
    311         ret = virtio_ccw_set_vqs(sch, &info, NULL);
    312     }
    313     sch->curr_status.scsw.count = 0;
    314     return ret;
    315 }
    316 
    317 static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
    318 {
    319     int ret;
    320     VirtioRevInfo revinfo;
    321     uint8_t status;
    322     VirtioFeatDesc features;
    323     hwaddr indicators;
    324     VqConfigBlock vq_config;
    325     VirtioCcwDevice *dev = sch->driver_data;
    326     VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
    327     bool check_len;
    328     int len;
    329     VirtioThinintInfo thinint;
    330 
    331     if (!dev) {
    332         return -EINVAL;
    333     }
    334 
    335     trace_virtio_ccw_interpret_ccw(sch->cssid, sch->ssid, sch->schid,
    336                                    ccw.cmd_code);
    337     check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC));
    338 
    339     if (dev->revision < 0 && ccw.cmd_code != CCW_CMD_SET_VIRTIO_REV) {
    340         if (dev->force_revision_1) {
    341             /*
    342              * virtio-1 drivers must start with negotiating to a revision >= 1,
    343              * so post a command reject for all other commands
    344              */
    345             return -ENOSYS;
    346         } else {
    347             /*
    348              * If the driver issues any command that is not SET_VIRTIO_REV,
    349              * we'll have to operate the device in legacy mode.
    350              */
    351             dev->revision = 0;
    352         }
    353     }
    354 
    355     /* Look at the command. */
    356     switch (ccw.cmd_code) {
    357     case CCW_CMD_SET_VQ:
    358         ret = virtio_ccw_handle_set_vq(sch, ccw, check_len, dev->revision < 1);
    359         break;
    360     case CCW_CMD_VDEV_RESET:
    361         virtio_ccw_reset_virtio(dev);
    362         ret = 0;
    363         break;
    364     case CCW_CMD_READ_FEAT:
    365         if (check_len) {
    366             if (ccw.count != sizeof(features)) {
    367                 ret = -EINVAL;
    368                 break;
    369             }
    370         } else if (ccw.count < sizeof(features)) {
    371             /* Can't execute command. */
    372             ret = -EINVAL;
    373             break;
    374         }
    375         if (!ccw.cda) {
    376             ret = -EFAULT;
    377         } else {
    378             VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
    379 
    380             ccw_dstream_advance(&sch->cds, sizeof(features.features));
    381             ret = ccw_dstream_read(&sch->cds, features.index);
    382             if (ret) {
    383                 break;
    384             }
    385             if (features.index == 0) {
    386                 if (dev->revision >= 1) {
    387                     /* Don't offer legacy features for modern devices. */
    388                     features.features = (uint32_t)
    389                         (vdev->host_features & ~vdc->legacy_features);
    390                 } else {
    391                     features.features = (uint32_t)vdev->host_features;
    392                 }
    393             } else if ((features.index == 1) && (dev->revision >= 1)) {
    394                 /*
    395                  * Only offer feature bits beyond 31 if the guest has
    396                  * negotiated at least revision 1.
    397                  */
    398                 features.features = (uint32_t)(vdev->host_features >> 32);
    399             } else {
    400                 /* Return zeroes if the guest supports more feature bits. */
    401                 features.features = 0;
    402             }
    403             ccw_dstream_rewind(&sch->cds);
    404             features.features = cpu_to_le32(features.features);
    405             ret = ccw_dstream_write(&sch->cds, features.features);
    406             if (!ret) {
    407                 sch->curr_status.scsw.count = ccw.count - sizeof(features);
    408             }
    409         }
    410         break;
    411     case CCW_CMD_WRITE_FEAT:
    412         if (check_len) {
    413             if (ccw.count != sizeof(features)) {
    414                 ret = -EINVAL;
    415                 break;
    416             }
    417         } else if (ccw.count < sizeof(features)) {
    418             /* Can't execute command. */
    419             ret = -EINVAL;
    420             break;
    421         }
    422         if (!ccw.cda) {
    423             ret = -EFAULT;
    424         } else {
    425             ret = ccw_dstream_read(&sch->cds, features);
    426             if (ret) {
    427                 break;
    428             }
    429             features.features = le32_to_cpu(features.features);
    430             if (features.index == 0) {
    431                 virtio_set_features(vdev,
    432                                     (vdev->guest_features & 0xffffffff00000000ULL) |
    433                                     features.features);
    434             } else if ((features.index == 1) && (dev->revision >= 1)) {
    435                 /*
    436                  * If the guest did not negotiate at least revision 1,
    437                  * we did not offer it any feature bits beyond 31. Such a
    438                  * guest passing us any bit here is therefore buggy.
    439                  */
    440                 virtio_set_features(vdev,
    441                                     (vdev->guest_features & 0x00000000ffffffffULL) |
    442                                     ((uint64_t)features.features << 32));
    443             } else {
    444                 /*
    445                  * If the guest supports more feature bits, assert that it
    446                  * passes us zeroes for those we don't support.
    447                  */
    448                 if (features.features) {
    449                     qemu_log_mask(LOG_GUEST_ERROR,
    450                                   "Guest bug: features[%i]=%x (expected 0)",
    451                                   features.index, features.features);
    452                     /* XXX: do a unit check here? */
    453                 }
    454             }
    455             sch->curr_status.scsw.count = ccw.count - sizeof(features);
    456             ret = 0;
    457         }
    458         break;
    459     case CCW_CMD_READ_CONF:
    460         if (check_len) {
    461             if (ccw.count > vdev->config_len) {
    462                 ret = -EINVAL;
    463                 break;
    464             }
    465         }
    466         len = MIN(ccw.count, vdev->config_len);
    467         if (!ccw.cda) {
    468             ret = -EFAULT;
    469         } else {
    470             virtio_bus_get_vdev_config(&dev->bus, vdev->config);
    471             ret = ccw_dstream_write_buf(&sch->cds, vdev->config, len);
    472             if (ret) {
    473                 sch->curr_status.scsw.count = ccw.count - len;
    474             }
    475         }
    476         break;
    477     case CCW_CMD_WRITE_CONF:
    478         if (check_len) {
    479             if (ccw.count > vdev->config_len) {
    480                 ret = -EINVAL;
    481                 break;
    482             }
    483         }
    484         len = MIN(ccw.count, vdev->config_len);
    485         if (!ccw.cda) {
    486             ret = -EFAULT;
    487         } else {
    488             ret = ccw_dstream_read_buf(&sch->cds, vdev->config, len);
    489             if (!ret) {
    490                 virtio_bus_set_vdev_config(&dev->bus, vdev->config);
    491                 sch->curr_status.scsw.count = ccw.count - len;
    492             }
    493         }
    494         break;
    495     case CCW_CMD_READ_STATUS:
    496         if (check_len) {
    497             if (ccw.count != sizeof(status)) {
    498                 ret = -EINVAL;
    499                 break;
    500             }
    501         } else if (ccw.count < sizeof(status)) {
    502             /* Can't execute command. */
    503             ret = -EINVAL;
    504             break;
    505         }
    506         if (!ccw.cda) {
    507             ret = -EFAULT;
    508         } else {
    509             address_space_stb(&address_space_memory, ccw.cda, vdev->status,
    510                                         MEMTXATTRS_UNSPECIFIED, NULL);
    511             sch->curr_status.scsw.count = ccw.count - sizeof(vdev->status);
    512             ret = 0;
    513         }
    514         break;
    515     case CCW_CMD_WRITE_STATUS:
    516         if (check_len) {
    517             if (ccw.count != sizeof(status)) {
    518                 ret = -EINVAL;
    519                 break;
    520             }
    521         } else if (ccw.count < sizeof(status)) {
    522             /* Can't execute command. */
    523             ret = -EINVAL;
    524             break;
    525         }
    526         if (!ccw.cda) {
    527             ret = -EFAULT;
    528         } else {
    529             ret = ccw_dstream_read(&sch->cds, status);
    530             if (ret) {
    531                 break;
    532             }
    533             if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
    534                 virtio_ccw_stop_ioeventfd(dev);
    535             }
    536             if (virtio_set_status(vdev, status) == 0) {
    537                 if (vdev->status == 0) {
    538                     virtio_ccw_reset_virtio(dev);
    539                 }
    540                 if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
    541                     virtio_ccw_start_ioeventfd(dev);
    542                 }
    543                 sch->curr_status.scsw.count = ccw.count - sizeof(status);
    544                 ret = 0;
    545             } else {
    546                 /* Trigger a command reject. */
    547                 ret = -ENOSYS;
    548             }
    549         }
    550         break;
    551     case CCW_CMD_SET_IND:
    552         if (check_len) {
    553             if (ccw.count != sizeof(indicators)) {
    554                 ret = -EINVAL;
    555                 break;
    556             }
    557         } else if (ccw.count < sizeof(indicators)) {
    558             /* Can't execute command. */
    559             ret = -EINVAL;
    560             break;
    561         }
    562         if (sch->thinint_active) {
    563             /* Trigger a command reject. */
    564             ret = -ENOSYS;
    565             break;
    566         }
    567         if (virtio_get_num_queues(vdev) > NR_CLASSIC_INDICATOR_BITS) {
    568             /* More queues than indicator bits --> trigger a reject */
    569             ret = -ENOSYS;
    570             break;
    571         }
    572         if (!ccw.cda) {
    573             ret = -EFAULT;
    574         } else {
    575             ret = ccw_dstream_read(&sch->cds, indicators);
    576             if (ret) {
    577                 break;
    578             }
    579             indicators = be64_to_cpu(indicators);
    580             dev->indicators = get_indicator(indicators, sizeof(uint64_t));
    581             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
    582             ret = 0;
    583         }
    584         break;
    585     case CCW_CMD_SET_CONF_IND:
    586         if (check_len) {
    587             if (ccw.count != sizeof(indicators)) {
    588                 ret = -EINVAL;
    589                 break;
    590             }
    591         } else if (ccw.count < sizeof(indicators)) {
    592             /* Can't execute command. */
    593             ret = -EINVAL;
    594             break;
    595         }
    596         if (!ccw.cda) {
    597             ret = -EFAULT;
    598         } else {
    599             ret = ccw_dstream_read(&sch->cds, indicators);
    600             if (ret) {
    601                 break;
    602             }
    603             indicators = be64_to_cpu(indicators);
    604             dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
    605             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
    606             ret = 0;
    607         }
    608         break;
    609     case CCW_CMD_READ_VQ_CONF:
    610         if (check_len) {
    611             if (ccw.count != sizeof(vq_config)) {
    612                 ret = -EINVAL;
    613                 break;
    614             }
    615         } else if (ccw.count < sizeof(vq_config)) {
    616             /* Can't execute command. */
    617             ret = -EINVAL;
    618             break;
    619         }
    620         if (!ccw.cda) {
    621             ret = -EFAULT;
    622         } else {
    623             ret = ccw_dstream_read(&sch->cds, vq_config.index);
    624             if (ret) {
    625                 break;
    626             }
    627             vq_config.index = be16_to_cpu(vq_config.index);
    628             if (vq_config.index >= VIRTIO_QUEUE_MAX) {
    629                 ret = -EINVAL;
    630                 break;
    631             }
    632             vq_config.num_max = virtio_queue_get_num(vdev,
    633                                                      vq_config.index);
    634             vq_config.num_max = cpu_to_be16(vq_config.num_max);
    635             ret = ccw_dstream_write(&sch->cds, vq_config.num_max);
    636             if (!ret) {
    637                 sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
    638             }
    639         }
    640         break;
    641     case CCW_CMD_SET_IND_ADAPTER:
    642         if (check_len) {
    643             if (ccw.count != sizeof(thinint)) {
    644                 ret = -EINVAL;
    645                 break;
    646             }
    647         } else if (ccw.count < sizeof(thinint)) {
    648             /* Can't execute command. */
    649             ret = -EINVAL;
    650             break;
    651         }
    652         if (!ccw.cda) {
    653             ret = -EFAULT;
    654         } else if (dev->indicators && !sch->thinint_active) {
    655             /* Trigger a command reject. */
    656             ret = -ENOSYS;
    657         } else {
    658             if (ccw_dstream_read(&sch->cds, thinint)) {
    659                 ret = -EFAULT;
    660             } else {
    661                 thinint.ind_bit = be64_to_cpu(thinint.ind_bit);
    662                 thinint.summary_indicator =
    663                     be64_to_cpu(thinint.summary_indicator);
    664                 thinint.device_indicator =
    665                     be64_to_cpu(thinint.device_indicator);
    666 
    667                 dev->summary_indicator =
    668                     get_indicator(thinint.summary_indicator, sizeof(uint8_t));
    669                 dev->indicators =
    670                     get_indicator(thinint.device_indicator,
    671                                   thinint.ind_bit / 8 + 1);
    672                 dev->thinint_isc = thinint.isc;
    673                 dev->routes.adapter.ind_offset = thinint.ind_bit;
    674                 dev->routes.adapter.summary_offset = 7;
    675                 dev->routes.adapter.adapter_id = css_get_adapter_id(
    676                                                  CSS_IO_ADAPTER_VIRTIO,
    677                                                  dev->thinint_isc);
    678                 sch->thinint_active = ((dev->indicators != NULL) &&
    679                                        (dev->summary_indicator != NULL));
    680                 sch->curr_status.scsw.count = ccw.count - sizeof(thinint);
    681                 ret = 0;
    682             }
    683         }
    684         break;
    685     case CCW_CMD_SET_VIRTIO_REV:
    686         len = sizeof(revinfo);
    687         if (ccw.count < len) {
    688             ret = -EINVAL;
    689             break;
    690         }
    691         if (!ccw.cda) {
    692             ret = -EFAULT;
    693             break;
    694         }
    695         ret = ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
    696         if (ret < 0) {
    697             break;
    698         }
    699         revinfo.revision = be16_to_cpu(revinfo.revision);
    700         revinfo.length = be16_to_cpu(revinfo.length);
    701         if (ccw.count < len + revinfo.length ||
    702             (check_len && ccw.count > len + revinfo.length)) {
    703             ret = -EINVAL;
    704             break;
    705         }
    706         /*
    707          * Once we start to support revisions with additional data, we'll
    708          * need to fetch it here. Nothing to do for now, though.
    709          */
    710         if (dev->revision >= 0 ||
    711             revinfo.revision > virtio_ccw_rev_max(dev) ||
    712             (dev->force_revision_1 && !revinfo.revision)) {
    713             ret = -ENOSYS;
    714             break;
    715         }
    716         ret = 0;
    717         dev->revision = revinfo.revision;
    718         break;
    719     default:
    720         ret = -ENOSYS;
    721         break;
    722     }
    723     return ret;
    724 }
    725 
    726 static void virtio_sch_disable_cb(SubchDev *sch)
    727 {
    728     VirtioCcwDevice *dev = sch->driver_data;
    729 
    730     dev->revision = -1;
    731 }
    732 
    733 static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
    734 {
    735     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
    736     CcwDevice *ccw_dev = CCW_DEVICE(dev);
    737     CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
    738     SubchDev *sch;
    739     Error *err = NULL;
    740     int i;
    741 
    742     sch = css_create_sch(ccw_dev->devno, errp);
    743     if (!sch) {
    744         return;
    745     }
    746     if (!virtio_ccw_rev_max(dev) && dev->force_revision_1) {
    747         error_setg(&err, "Invalid value of property max_rev "
    748                    "(is %d expected >= 1)", virtio_ccw_rev_max(dev));
    749         goto out_err;
    750     }
    751 
    752     sch->driver_data = dev;
    753     sch->ccw_cb = virtio_ccw_cb;
    754     sch->disable_cb = virtio_sch_disable_cb;
    755     sch->id.reserved = 0xff;
    756     sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
    757     sch->do_subchannel_work = do_subchannel_work_virtual;
    758     sch->irb_cb = build_irb_virtual;
    759     ccw_dev->sch = sch;
    760     dev->indicators = NULL;
    761     dev->revision = -1;
    762     for (i = 0; i < ADAPTER_ROUTES_MAX_GSI; i++) {
    763         dev->routes.gsi[i] = -1;
    764     }
    765     css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
    766 
    767     trace_virtio_ccw_new_device(
    768         sch->cssid, sch->ssid, sch->schid, sch->devno,
    769         ccw_dev->devno.valid ? "user-configured" : "auto-configured");
    770 
    771     if (kvm_enabled() && !kvm_eventfds_enabled()) {
    772         dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
    773     }
    774 
    775     /* fd-based ioevents can't be synchronized in record/replay */
    776     if (replay_mode != REPLAY_MODE_NONE) {
    777         dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
    778     }
    779 
    780     if (k->realize) {
    781         k->realize(dev, &err);
    782         if (err) {
    783             goto out_err;
    784         }
    785     }
    786 
    787     ck->realize(ccw_dev, &err);
    788     if (err) {
    789         goto out_err;
    790     }
    791 
    792     return;
    793 
    794 out_err:
    795     error_propagate(errp, err);
    796     css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
    797     ccw_dev->sch = NULL;
    798     g_free(sch);
    799 }
    800 
    801 static void virtio_ccw_device_unrealize(VirtioCcwDevice *dev)
    802 {
    803     VirtIOCCWDeviceClass *dc = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
    804     CcwDevice *ccw_dev = CCW_DEVICE(dev);
    805     SubchDev *sch = ccw_dev->sch;
    806 
    807     if (dc->unrealize) {
    808         dc->unrealize(dev);
    809     }
    810 
    811     if (sch) {
    812         css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
    813         g_free(sch);
    814         ccw_dev->sch = NULL;
    815     }
    816     if (dev->indicators) {
    817         release_indicator(&dev->routes.adapter, dev->indicators);
    818         dev->indicators = NULL;
    819     }
    820 }
    821 
    822 /* DeviceState to VirtioCcwDevice. Note: used on datapath,
    823  * be careful and test performance if you change this.
    824  */
    825 static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d)
    826 {
    827     CcwDevice *ccw_dev = to_ccw_dev_fast(d);
    828 
    829     return container_of(ccw_dev, VirtioCcwDevice, parent_obj);
    830 }
    831 
    832 static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
    833                                      uint8_t to_be_set)
    834 {
    835     uint8_t expected, actual;
    836     hwaddr len = 1;
    837     /* avoid  multiple fetches */
    838     uint8_t volatile *ind_addr;
    839 
    840     ind_addr = cpu_physical_memory_map(ind_loc, &len, true);
    841     if (!ind_addr) {
    842         error_report("%s(%x.%x.%04x): unable to access indicator",
    843                      __func__, sch->cssid, sch->ssid, sch->schid);
    844         return -1;
    845     }
    846     actual = *ind_addr;
    847     do {
    848         expected = actual;
    849         actual = qatomic_cmpxchg(ind_addr, expected, expected | to_be_set);
    850     } while (actual != expected);
    851     trace_virtio_ccw_set_ind(ind_loc, actual, actual | to_be_set);
    852     cpu_physical_memory_unmap((void *)ind_addr, len, 1, len);
    853 
    854     return actual;
    855 }
    856 
    857 static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
    858 {
    859     VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d);
    860     CcwDevice *ccw_dev = to_ccw_dev_fast(d);
    861     SubchDev *sch = ccw_dev->sch;
    862     uint64_t indicators;
    863 
    864     if (vector == VIRTIO_NO_VECTOR) {
    865         return;
    866     }
    867     /*
    868      * vector < VIRTIO_QUEUE_MAX: notification for a virtqueue
    869      * vector == VIRTIO_QUEUE_MAX: configuration change notification
    870      * bits beyond that are unused and should never be notified for
    871      */
    872     assert(vector <= VIRTIO_QUEUE_MAX);
    873 
    874     if (vector < VIRTIO_QUEUE_MAX) {
    875         if (!dev->indicators) {
    876             return;
    877         }
    878         if (sch->thinint_active) {
    879             /*
    880              * In the adapter interrupt case, indicators points to a
    881              * memory area that may be (way) larger than 64 bit and
    882              * ind_bit indicates the start of the indicators in a big
    883              * endian notation.
    884              */
    885             uint64_t ind_bit = dev->routes.adapter.ind_offset;
    886 
    887             virtio_set_ind_atomic(sch, dev->indicators->addr +
    888                                   (ind_bit + vector) / 8,
    889                                   0x80 >> ((ind_bit + vector) % 8));
    890             if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr,
    891                                        0x01)) {
    892                 css_adapter_interrupt(CSS_IO_ADAPTER_VIRTIO, dev->thinint_isc);
    893             }
    894         } else {
    895             assert(vector < NR_CLASSIC_INDICATOR_BITS);
    896             indicators = address_space_ldq(&address_space_memory,
    897                                            dev->indicators->addr,
    898                                            MEMTXATTRS_UNSPECIFIED,
    899                                            NULL);
    900             indicators |= 1ULL << vector;
    901             address_space_stq(&address_space_memory, dev->indicators->addr,
    902                               indicators, MEMTXATTRS_UNSPECIFIED, NULL);
    903             css_conditional_io_interrupt(sch);
    904         }
    905     } else {
    906         if (!dev->indicators2) {
    907             return;
    908         }
    909         indicators = address_space_ldq(&address_space_memory,
    910                                        dev->indicators2->addr,
    911                                        MEMTXATTRS_UNSPECIFIED,
    912                                        NULL);
    913         indicators |= 1ULL;
    914         address_space_stq(&address_space_memory, dev->indicators2->addr,
    915                           indicators, MEMTXATTRS_UNSPECIFIED, NULL);
    916         css_conditional_io_interrupt(sch);
    917     }
    918 }
    919 
    920 static void virtio_ccw_reset(DeviceState *d)
    921 {
    922     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
    923     VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
    924 
    925     virtio_ccw_reset_virtio(dev);
    926     if (vdc->parent_reset) {
    927         vdc->parent_reset(d);
    928     }
    929 }
    930 
    931 static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
    932 {
    933     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
    934 
    935     if (running) {
    936         virtio_ccw_start_ioeventfd(dev);
    937     } else {
    938         virtio_ccw_stop_ioeventfd(dev);
    939     }
    940 }
    941 
    942 static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
    943 {
    944     CcwDevice *dev = CCW_DEVICE(d);
    945 
    946     return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
    947 }
    948 
    949 static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
    950 {
    951     int r;
    952     CcwDevice *ccw_dev = CCW_DEVICE(dev);
    953 
    954     if (!ccw_dev->sch->thinint_active) {
    955         return -EINVAL;
    956     }
    957 
    958     r = map_indicator(&dev->routes.adapter, dev->summary_indicator);
    959     if (r) {
    960         return r;
    961     }
    962     r = map_indicator(&dev->routes.adapter, dev->indicators);
    963     if (r) {
    964         return r;
    965     }
    966     dev->routes.adapter.summary_addr = dev->summary_indicator->map;
    967     dev->routes.adapter.ind_addr = dev->indicators->map;
    968 
    969     return 0;
    970 }
    971 
    972 static int virtio_ccw_setup_irqroutes(VirtioCcwDevice *dev, int nvqs)
    973 {
    974     int i;
    975     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
    976     int ret;
    977     S390FLICState *fs = s390_get_flic();
    978     S390FLICStateClass *fsc = s390_get_flic_class(fs);
    979 
    980     ret = virtio_ccw_get_mappings(dev);
    981     if (ret) {
    982         return ret;
    983     }
    984     for (i = 0; i < nvqs; i++) {
    985         if (!virtio_queue_get_num(vdev, i)) {
    986             break;
    987         }
    988     }
    989     dev->routes.num_routes = i;
    990     return fsc->add_adapter_routes(fs, &dev->routes);
    991 }
    992 
    993 static void virtio_ccw_release_irqroutes(VirtioCcwDevice *dev, int nvqs)
    994 {
    995     S390FLICState *fs = s390_get_flic();
    996     S390FLICStateClass *fsc = s390_get_flic_class(fs);
    997 
    998     fsc->release_adapter_routes(fs, &dev->routes);
    999 }
   1000 
   1001 static int virtio_ccw_add_irqfd(VirtioCcwDevice *dev, int n)
   1002 {
   1003     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1004     VirtQueue *vq = virtio_get_queue(vdev, n);
   1005     EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
   1006 
   1007     return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, notifier, NULL,
   1008                                               dev->routes.gsi[n]);
   1009 }
   1010 
   1011 static void virtio_ccw_remove_irqfd(VirtioCcwDevice *dev, int n)
   1012 {
   1013     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1014     VirtQueue *vq = virtio_get_queue(vdev, n);
   1015     EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
   1016     int ret;
   1017 
   1018     ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, notifier,
   1019                                                 dev->routes.gsi[n]);
   1020     assert(ret == 0);
   1021 }
   1022 
   1023 static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
   1024                                          bool assign, bool with_irqfd)
   1025 {
   1026     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1027     VirtQueue *vq = virtio_get_queue(vdev, n);
   1028     EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
   1029     VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
   1030 
   1031     if (assign) {
   1032         int r = event_notifier_init(notifier, 0);
   1033 
   1034         if (r < 0) {
   1035             return r;
   1036         }
   1037         virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
   1038         if (with_irqfd) {
   1039             r = virtio_ccw_add_irqfd(dev, n);
   1040             if (r) {
   1041                 virtio_queue_set_guest_notifier_fd_handler(vq, false,
   1042                                                            with_irqfd);
   1043                 return r;
   1044             }
   1045         }
   1046         /*
   1047          * We do not support individual masking for channel devices, so we
   1048          * need to manually trigger any guest masking callbacks here.
   1049          */
   1050         if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) {
   1051             k->guest_notifier_mask(vdev, n, false);
   1052         }
   1053         /* get lost events and re-inject */
   1054         if (k->guest_notifier_pending &&
   1055             k->guest_notifier_pending(vdev, n)) {
   1056             event_notifier_set(notifier);
   1057         }
   1058     } else {
   1059         if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) {
   1060             k->guest_notifier_mask(vdev, n, true);
   1061         }
   1062         if (with_irqfd) {
   1063             virtio_ccw_remove_irqfd(dev, n);
   1064         }
   1065         virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
   1066         event_notifier_cleanup(notifier);
   1067     }
   1068     return 0;
   1069 }
   1070 
   1071 static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
   1072                                           bool assigned)
   1073 {
   1074     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1075     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1076     CcwDevice *ccw_dev = CCW_DEVICE(d);
   1077     bool with_irqfd = ccw_dev->sch->thinint_active && kvm_irqfds_enabled();
   1078     int r, n;
   1079 
   1080     if (with_irqfd && assigned) {
   1081         /* irq routes need to be set up before assigning irqfds */
   1082         r = virtio_ccw_setup_irqroutes(dev, nvqs);
   1083         if (r < 0) {
   1084             goto irqroute_error;
   1085         }
   1086     }
   1087     for (n = 0; n < nvqs; n++) {
   1088         if (!virtio_queue_get_num(vdev, n)) {
   1089             break;
   1090         }
   1091         r = virtio_ccw_set_guest_notifier(dev, n, assigned, with_irqfd);
   1092         if (r < 0) {
   1093             goto assign_error;
   1094         }
   1095     }
   1096     if (with_irqfd && !assigned) {
   1097         /* release irq routes after irqfds have been released */
   1098         virtio_ccw_release_irqroutes(dev, nvqs);
   1099     }
   1100     return 0;
   1101 
   1102 assign_error:
   1103     while (--n >= 0) {
   1104         virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
   1105     }
   1106 irqroute_error:
   1107     if (with_irqfd && assigned) {
   1108         virtio_ccw_release_irqroutes(dev, nvqs);
   1109     }
   1110     return r;
   1111 }
   1112 
   1113 static void virtio_ccw_save_queue(DeviceState *d, int n, QEMUFile *f)
   1114 {
   1115     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1116     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1117 
   1118     qemu_put_be16(f, virtio_queue_vector(vdev, n));
   1119 }
   1120 
   1121 static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f)
   1122 {
   1123     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1124     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1125     uint16_t vector;
   1126 
   1127     qemu_get_be16s(f, &vector);
   1128     virtio_queue_set_vector(vdev, n , vector);
   1129 
   1130     return 0;
   1131 }
   1132 
   1133 static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
   1134 {
   1135     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1136     vmstate_save_state(f, &vmstate_virtio_ccw_dev, dev, NULL);
   1137 }
   1138 
   1139 static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
   1140 {
   1141     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1142     return vmstate_load_state(f, &vmstate_virtio_ccw_dev, dev, 1);
   1143 }
   1144 
   1145 static void virtio_ccw_pre_plugged(DeviceState *d, Error **errp)
   1146 {
   1147    VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1148    VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1149 
   1150     if (dev->max_rev >= 1) {
   1151         virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1);
   1152     }
   1153 }
   1154 
   1155 /* This is called by virtio-bus just after the device is plugged. */
   1156 static void virtio_ccw_device_plugged(DeviceState *d, Error **errp)
   1157 {
   1158     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1159     VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
   1160     CcwDevice *ccw_dev = CCW_DEVICE(d);
   1161     SubchDev *sch = ccw_dev->sch;
   1162     int n = virtio_get_num_queues(vdev);
   1163     S390FLICState *flic = s390_get_flic();
   1164 
   1165     if (!virtio_has_feature(vdev->host_features, VIRTIO_F_VERSION_1)) {
   1166         dev->max_rev = 0;
   1167     }
   1168 
   1169     if (!virtio_ccw_rev_max(dev) && !virtio_legacy_allowed(vdev)) {
   1170         /*
   1171          * To avoid migration issues, we allow legacy mode when legacy
   1172          * check is disabled in the old machine types (< 5.1).
   1173          */
   1174         if (virtio_legacy_check_disabled(vdev)) {
   1175             warn_report("device requires revision >= 1, but for backward "
   1176                         "compatibility max_revision=0 is allowed");
   1177         } else {
   1178             error_setg(errp, "Invalid value of property max_rev "
   1179                        "(is %d expected >= 1)", virtio_ccw_rev_max(dev));
   1180             return;
   1181         }
   1182     }
   1183 
   1184     if (virtio_get_num_queues(vdev) > VIRTIO_QUEUE_MAX) {
   1185         error_setg(errp, "The number of virtqueues %d "
   1186                    "exceeds virtio limit %d", n,
   1187                    VIRTIO_QUEUE_MAX);
   1188         return;
   1189     }
   1190     if (virtio_get_num_queues(vdev) > flic->adapter_routes_max_batch) {
   1191         error_setg(errp, "The number of virtqueues %d "
   1192                    "exceeds flic adapter route limit %d", n,
   1193                    flic->adapter_routes_max_batch);
   1194         return;
   1195     }
   1196 
   1197     sch->id.cu_model = virtio_bus_get_vdev_id(&dev->bus);
   1198 
   1199 
   1200     css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
   1201                           d->hotplugged, 1);
   1202 }
   1203 
   1204 static void virtio_ccw_device_unplugged(DeviceState *d)
   1205 {
   1206     VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
   1207 
   1208     virtio_ccw_stop_ioeventfd(dev);
   1209 }
   1210 /**************** Virtio-ccw Bus Device Descriptions *******************/
   1211 
   1212 static void virtio_ccw_busdev_realize(DeviceState *dev, Error **errp)
   1213 {
   1214     VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
   1215 
   1216     virtio_ccw_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
   1217     virtio_ccw_device_realize(_dev, errp);
   1218 }
   1219 
   1220 static void virtio_ccw_busdev_unrealize(DeviceState *dev)
   1221 {
   1222     VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
   1223 
   1224     virtio_ccw_device_unrealize(_dev);
   1225 }
   1226 
   1227 static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
   1228                                      DeviceState *dev, Error **errp)
   1229 {
   1230     VirtioCcwDevice *_dev = to_virtio_ccw_dev_fast(dev);
   1231 
   1232     virtio_ccw_stop_ioeventfd(_dev);
   1233 }
   1234 
   1235 static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
   1236 {
   1237     DeviceClass *dc = DEVICE_CLASS(klass);
   1238     CCWDeviceClass *k = CCW_DEVICE_CLASS(dc);
   1239     VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_CLASS(klass);
   1240 
   1241     k->unplug = virtio_ccw_busdev_unplug;
   1242     dc->realize = virtio_ccw_busdev_realize;
   1243     dc->unrealize = virtio_ccw_busdev_unrealize;
   1244     device_class_set_parent_reset(dc, virtio_ccw_reset, &vdc->parent_reset);
   1245 }
   1246 
   1247 static const TypeInfo virtio_ccw_device_info = {
   1248     .name = TYPE_VIRTIO_CCW_DEVICE,
   1249     .parent = TYPE_CCW_DEVICE,
   1250     .instance_size = sizeof(VirtioCcwDevice),
   1251     .class_init = virtio_ccw_device_class_init,
   1252     .class_size = sizeof(VirtIOCCWDeviceClass),
   1253     .abstract = true,
   1254 };
   1255 
   1256 /* virtio-ccw-bus */
   1257 
   1258 static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
   1259                                VirtioCcwDevice *dev)
   1260 {
   1261     DeviceState *qdev = DEVICE(dev);
   1262     char virtio_bus_name[] = "virtio-bus";
   1263 
   1264     qbus_init(bus, bus_size, TYPE_VIRTIO_CCW_BUS, qdev, virtio_bus_name);
   1265 }
   1266 
   1267 static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
   1268 {
   1269     VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
   1270     BusClass *bus_class = BUS_CLASS(klass);
   1271 
   1272     bus_class->max_dev = 1;
   1273     k->notify = virtio_ccw_notify;
   1274     k->vmstate_change = virtio_ccw_vmstate_change;
   1275     k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
   1276     k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
   1277     k->save_queue = virtio_ccw_save_queue;
   1278     k->load_queue = virtio_ccw_load_queue;
   1279     k->save_config = virtio_ccw_save_config;
   1280     k->load_config = virtio_ccw_load_config;
   1281     k->pre_plugged = virtio_ccw_pre_plugged;
   1282     k->device_plugged = virtio_ccw_device_plugged;
   1283     k->device_unplugged = virtio_ccw_device_unplugged;
   1284     k->ioeventfd_enabled = virtio_ccw_ioeventfd_enabled;
   1285     k->ioeventfd_assign = virtio_ccw_ioeventfd_assign;
   1286 }
   1287 
   1288 static const TypeInfo virtio_ccw_bus_info = {
   1289     .name = TYPE_VIRTIO_CCW_BUS,
   1290     .parent = TYPE_VIRTIO_BUS,
   1291     .instance_size = sizeof(VirtioCcwBusState),
   1292     .class_size = sizeof(VirtioCcwBusClass),
   1293     .class_init = virtio_ccw_bus_class_init,
   1294 };
   1295 
   1296 static void virtio_ccw_register(void)
   1297 {
   1298     type_register_static(&virtio_ccw_bus_info);
   1299     type_register_static(&virtio_ccw_device_info);
   1300 }
   1301 
   1302 type_init(virtio_ccw_register)