qemu/hw/s390x/s390-virtio-bus.c
<<
>>
Prefs
   1/*
   2 * QEMU S390 virtio target
   3 *
   4 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "hw/hw.h"
  21#include "sysemu/block-backend.h"
  22#include "sysemu/sysemu.h"
  23#include "hw/boards.h"
  24#include "monitor/monitor.h"
  25#include "hw/loader.h"
  26#include "elf.h"
  27#include "hw/virtio/virtio.h"
  28#include "hw/virtio/virtio-rng.h"
  29#include "hw/virtio/virtio-serial.h"
  30#include "hw/virtio/virtio-net.h"
  31#include "hw/virtio/vhost-scsi.h"
  32#include "hw/sysbus.h"
  33#include "sysemu/kvm.h"
  34
  35#include "hw/s390x/s390-virtio-bus.h"
  36#include "hw/virtio/virtio-bus.h"
  37
  38/* #define DEBUG_S390 */
  39
  40#ifdef DEBUG_S390
  41#define DPRINTF(fmt, ...) \
  42    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
  43#else
  44#define DPRINTF(fmt, ...) \
  45    do { } while (0)
  46#endif
  47
  48static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
  49                                VirtIOS390Device *dev);
  50
  51static const TypeInfo s390_virtio_bus_info = {
  52    .name = TYPE_S390_VIRTIO_BUS,
  53    .parent = TYPE_BUS,
  54    .instance_size = sizeof(VirtIOS390Bus),
  55};
  56
  57static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev);
  58
  59/* length of VirtIO device pages */
  60const hwaddr virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
  61
  62static void s390_virtio_bus_reset(void *opaque)
  63{
  64    VirtIOS390Bus *bus = opaque;
  65    bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
  66}
  67
  68void s390_virtio_reset_idx(VirtIOS390Device *dev)
  69{
  70    int i;
  71    hwaddr idx_addr;
  72    uint8_t num_vq;
  73
  74    num_vq = s390_virtio_device_num_vq(dev);
  75    for (i = 0; i < num_vq; i++) {
  76        idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
  77            VIRTIO_VRING_AVAIL_IDX_OFFS;
  78        stw_phys(&address_space_memory, idx_addr, 0);
  79        idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
  80            VIRTIO_VRING_USED_IDX_OFFS;
  81        stw_phys(&address_space_memory, idx_addr, 0);
  82    }
  83}
  84
  85VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
  86{
  87    VirtIOS390Bus *bus;
  88    BusState *_bus;
  89    DeviceState *dev;
  90
  91    /* Create bridge device */
  92    dev = qdev_create(NULL, "s390-virtio-bridge");
  93    qdev_init_nofail(dev);
  94
  95    /* Create bus on bridge device */
  96
  97    _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio");
  98    bus = DO_UPCAST(VirtIOS390Bus, bus, _bus);
  99
 100    bus->dev_page = *ram_size;
 101    bus->dev_offs = bus->dev_page;
 102    bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
 103
 104    /* Enable hotplugging */
 105    qbus_set_hotplug_handler(_bus, dev, &error_abort);
 106
 107    /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */
 108    *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
 109
 110    qemu_register_reset(s390_virtio_bus_reset, bus);
 111    return bus;
 112}
 113
 114static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
 115{
 116    VirtIOS390Bus *bus;
 117    int dev_len;
 118
 119    bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
 120    dev->vdev = vdev;
 121    dev->dev_offs = bus->dev_offs;
 122    dev->feat_len = sizeof(uint32_t); /* always keep 32 bits features */
 123
 124    dev_len = VIRTIO_DEV_OFFS_CONFIG;
 125    dev_len += s390_virtio_device_num_vq(dev) * VIRTIO_VQCONFIG_LEN;
 126    dev_len += dev->feat_len * 2;
 127    dev_len += virtio_bus_get_vdev_config_len(&dev->bus);
 128
 129    bus->dev_offs += dev_len;
 130
 131    dev->host_features = virtio_bus_get_vdev_features(&dev->bus,
 132                                                      dev->host_features);
 133    s390_virtio_device_sync(dev);
 134    s390_virtio_reset_idx(dev);
 135    if (dev->qdev.hotplugged) {
 136        s390_virtio_irq(VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
 137    }
 138
 139    return 0;
 140}
 141
 142static int s390_virtio_net_init(VirtIOS390Device *s390_dev)
 143{
 144    DeviceState *qdev = DEVICE(s390_dev);
 145    VirtIONetS390 *dev = VIRTIO_NET_S390(s390_dev);
 146    DeviceState *vdev = DEVICE(&dev->vdev);
 147
 148    virtio_net_set_config_size(&dev->vdev, s390_dev->host_features);
 149    virtio_net_set_netclient_name(&dev->vdev, qdev->id,
 150                                  object_get_typename(OBJECT(qdev)));
 151    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
 152    if (qdev_init(vdev) < 0) {
 153        return -1;
 154    }
 155
 156    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 157}
 158
 159static void s390_virtio_net_instance_init(Object *obj)
 160{
 161    VirtIONetS390 *dev = VIRTIO_NET_S390(obj);
 162
 163    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 164                                TYPE_VIRTIO_NET);
 165    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
 166                              "bootindex", &error_abort);
 167}
 168
 169static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
 170{
 171    VirtIOBlkS390 *dev = VIRTIO_BLK_S390(s390_dev);
 172    DeviceState *vdev = DEVICE(&dev->vdev);
 173    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
 174    if (qdev_init(vdev) < 0) {
 175        return -1;
 176    }
 177    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 178}
 179
 180static void s390_virtio_blk_instance_init(Object *obj)
 181{
 182    VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj);
 183
 184    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 185                                TYPE_VIRTIO_BLK);
 186    object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
 187                              &error_abort);
 188    object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
 189                              "bootindex", &error_abort);
 190}
 191
 192static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
 193{
 194    VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(s390_dev);
 195    DeviceState *vdev = DEVICE(&dev->vdev);
 196    DeviceState *qdev = DEVICE(s390_dev);
 197    VirtIOS390Bus *bus;
 198    int r;
 199    char *bus_name;
 200
 201    bus = DO_UPCAST(VirtIOS390Bus, bus, qdev->parent_bus);
 202
 203    /*
 204     * For command line compatibility, this sets the virtio-serial-device bus
 205     * name as before.
 206     */
 207    if (qdev->id) {
 208        bus_name = g_strdup_printf("%s.0", qdev->id);
 209        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
 210        g_free(bus_name);
 211    }
 212
 213    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
 214    if (qdev_init(vdev) < 0) {
 215        return -1;
 216    }
 217
 218    r = s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 219    if (!r) {
 220        bus->console = s390_dev;
 221    }
 222
 223    return r;
 224}
 225
 226static void s390_virtio_serial_instance_init(Object *obj)
 227{
 228    VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(obj);
 229
 230    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 231                                TYPE_VIRTIO_SERIAL);
 232}
 233
 234static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
 235{
 236    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev);
 237    DeviceState *vdev = DEVICE(&dev->vdev);
 238    DeviceState *qdev = DEVICE(s390_dev);
 239    char *bus_name;
 240
 241    /*
 242     * For command line compatibility, this sets the virtio-scsi-device bus
 243     * name as before.
 244     */
 245    if (qdev->id) {
 246        bus_name = g_strdup_printf("%s.0", qdev->id);
 247        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
 248        g_free(bus_name);
 249    }
 250
 251    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
 252    if (qdev_init(vdev) < 0) {
 253        return -1;
 254    }
 255
 256    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 257}
 258
 259static void s390_virtio_scsi_instance_init(Object *obj)
 260{
 261    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj);
 262
 263    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 264                                TYPE_VIRTIO_SCSI);
 265}
 266
 267#ifdef CONFIG_VHOST_SCSI
 268static int s390_vhost_scsi_init(VirtIOS390Device *s390_dev)
 269{
 270    VHostSCSIS390 *dev = VHOST_SCSI_S390(s390_dev);
 271    DeviceState *vdev = DEVICE(&dev->vdev);
 272
 273    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
 274    if (qdev_init(vdev) < 0) {
 275        return -1;
 276    }
 277
 278    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 279}
 280
 281static void s390_vhost_scsi_instance_init(Object *obj)
 282{
 283    VHostSCSIS390 *dev = VHOST_SCSI_S390(obj);
 284
 285    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 286                                TYPE_VHOST_SCSI);
 287}
 288#endif
 289
 290
 291static int s390_virtio_rng_init(VirtIOS390Device *s390_dev)
 292{
 293    VirtIORNGS390 *dev = VIRTIO_RNG_S390(s390_dev);
 294    DeviceState *vdev = DEVICE(&dev->vdev);
 295
 296    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
 297    if (qdev_init(vdev) < 0) {
 298        return -1;
 299    }
 300
 301    object_property_set_link(OBJECT(dev),
 302                             OBJECT(dev->vdev.conf.rng), "rng",
 303                             NULL);
 304
 305    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 306}
 307
 308static void s390_virtio_rng_instance_init(Object *obj)
 309{
 310    VirtIORNGS390 *dev = VIRTIO_RNG_S390(obj);
 311
 312    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
 313                                TYPE_VIRTIO_RNG);
 314    object_property_add_alias(obj, "rng", OBJECT(&dev->vdev),
 315                              "rng", &error_abort);
 316}
 317
 318static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
 319{
 320    ram_addr_t token_off;
 321
 322    token_off = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) +
 323                (vq * VIRTIO_VQCONFIG_LEN) +
 324                VIRTIO_VQCONFIG_OFFS_TOKEN;
 325
 326    return ldq_be_phys(&address_space_memory, token_off);
 327}
 328
 329static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
 330{
 331    VirtIODevice *vdev = dev->vdev;
 332    int num_vq;
 333
 334    for (num_vq = 0; num_vq < VIRTIO_PCI_QUEUE_MAX; num_vq++) {
 335        if (!virtio_queue_get_num(vdev, num_vq)) {
 336            break;
 337        }
 338    }
 339
 340    return num_vq;
 341}
 342
 343static ram_addr_t s390_virtio_next_ring(VirtIOS390Bus *bus)
 344{
 345    ram_addr_t r = bus->next_ring;
 346
 347    bus->next_ring += VIRTIO_RING_LEN;
 348    return r;
 349}
 350
 351void s390_virtio_device_sync(VirtIOS390Device *dev)
 352{
 353    VirtIOS390Bus *bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
 354    ram_addr_t cur_offs;
 355    uint8_t num_vq;
 356    int i;
 357
 358    virtio_reset(dev->vdev);
 359
 360    /* Sync dev space */
 361    stb_phys(&address_space_memory,
 362             dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id);
 363
 364    stb_phys(&address_space_memory,
 365             dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ,
 366             s390_virtio_device_num_vq(dev));
 367    stb_phys(&address_space_memory,
 368             dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len);
 369
 370    stb_phys(&address_space_memory,
 371             dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len);
 372
 373    num_vq = s390_virtio_device_num_vq(dev);
 374    stb_phys(&address_space_memory,
 375             dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq);
 376
 377    /* Sync virtqueues */
 378    for (i = 0; i < num_vq; i++) {
 379        ram_addr_t vq = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) +
 380                        (i * VIRTIO_VQCONFIG_LEN);
 381        ram_addr_t vring;
 382
 383        vring = s390_virtio_next_ring(bus);
 384        virtio_queue_set_addr(dev->vdev, i, vring);
 385        virtio_queue_set_vector(dev->vdev, i, i);
 386        stq_be_phys(&address_space_memory,
 387                    vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
 388        stw_be_phys(&address_space_memory,
 389                    vq + VIRTIO_VQCONFIG_OFFS_NUM,
 390                    virtio_queue_get_num(dev->vdev, i));
 391    }
 392
 393    cur_offs = dev->dev_offs;
 394    cur_offs += VIRTIO_DEV_OFFS_CONFIG;
 395    cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
 396
 397    /* Sync feature bitmap */
 398    stl_le_phys(&address_space_memory, cur_offs, dev->host_features);
 399
 400    dev->feat_offs = cur_offs + dev->feat_len;
 401    cur_offs += dev->feat_len * 2;
 402
 403    /* Sync config space */
 404    virtio_bus_get_vdev_config(&dev->bus, dev->vdev->config);
 405
 406    cpu_physical_memory_write(cur_offs,
 407                              dev->vdev->config, dev->vdev->config_len);
 408    cur_offs += dev->vdev->config_len;
 409}
 410
 411void s390_virtio_device_update_status(VirtIOS390Device *dev)
 412{
 413    VirtIODevice *vdev = dev->vdev;
 414    uint32_t features;
 415
 416    virtio_set_status(vdev, ldub_phys(&address_space_memory,
 417                                      dev->dev_offs + VIRTIO_DEV_OFFS_STATUS));
 418
 419    /* Update guest supported feature bitmap */
 420
 421    features = bswap32(ldl_be_phys(&address_space_memory, dev->feat_offs));
 422    virtio_set_features(vdev, features);
 423}
 424
 425VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
 426{
 427    return bus->console;
 428}
 429
 430/* Find a device by vring address */
 431VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
 432                                             ram_addr_t mem,
 433                                             int *vq_num)
 434{
 435    BusChild *kid;
 436    int i;
 437
 438    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
 439        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
 440
 441        for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
 442            if (!virtio_queue_get_addr(dev->vdev, i))
 443                break;
 444            if (virtio_queue_get_addr(dev->vdev, i) == mem) {
 445                if (vq_num) {
 446                    *vq_num = i;
 447                }
 448                return dev;
 449            }
 450        }
 451    }
 452
 453    return NULL;
 454}
 455
 456/* Find a device by device descriptor location */
 457VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
 458{
 459    BusChild *kid;
 460
 461    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
 462        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
 463        if (dev->dev_offs == mem) {
 464            return dev;
 465        }
 466    }
 467
 468    return NULL;
 469}
 470
 471/* DeviceState to VirtIOS390Device. Note: used on datapath,
 472 * be careful and test performance if you change this.
 473 */
 474static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d)
 475{
 476    return container_of(d, VirtIOS390Device, qdev);
 477}
 478
 479/* DeviceState to VirtIOS390Device. TODO: use QOM. */
 480static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d)
 481{
 482    return container_of(d, VirtIOS390Device, qdev);
 483}
 484
 485static void virtio_s390_notify(DeviceState *d, uint16_t vector)
 486{
 487    VirtIOS390Device *dev = to_virtio_s390_device_fast(d);
 488    uint64_t token = s390_virtio_device_vq_token(dev, vector);
 489
 490    s390_virtio_irq(0, token);
 491}
 492
 493static unsigned virtio_s390_get_features(DeviceState *d)
 494{
 495    VirtIOS390Device *dev = to_virtio_s390_device(d);
 496    return dev->host_features;
 497}
 498
 499/**************** S390 Virtio Bus Device Descriptions *******************/
 500
 501static Property s390_virtio_net_properties[] = {
 502    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
 503    DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
 504    DEFINE_PROP_END_OF_LIST(),
 505};
 506
 507static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
 508{
 509    DeviceClass *dc = DEVICE_CLASS(klass);
 510    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 511
 512    k->init = s390_virtio_net_init;
 513    dc->props = s390_virtio_net_properties;
 514}
 515
 516static const TypeInfo s390_virtio_net = {
 517    .name          = TYPE_VIRTIO_NET_S390,
 518    .parent        = TYPE_VIRTIO_S390_DEVICE,
 519    .instance_size = sizeof(VirtIONetS390),
 520    .instance_init = s390_virtio_net_instance_init,
 521    .class_init    = s390_virtio_net_class_init,
 522};
 523
 524static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
 525{
 526    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 527
 528    k->init = s390_virtio_blk_init;
 529}
 530
 531static const TypeInfo s390_virtio_blk = {
 532    .name          = "virtio-blk-s390",
 533    .parent        = TYPE_VIRTIO_S390_DEVICE,
 534    .instance_size = sizeof(VirtIOBlkS390),
 535    .instance_init = s390_virtio_blk_instance_init,
 536    .class_init    = s390_virtio_blk_class_init,
 537};
 538
 539static Property s390_virtio_serial_properties[] = {
 540    DEFINE_PROP_END_OF_LIST(),
 541};
 542
 543static void s390_virtio_serial_class_init(ObjectClass *klass, void *data)
 544{
 545    DeviceClass *dc = DEVICE_CLASS(klass);
 546    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 547
 548    k->init = s390_virtio_serial_init;
 549    dc->props = s390_virtio_serial_properties;
 550}
 551
 552static const TypeInfo s390_virtio_serial = {
 553    .name          = TYPE_VIRTIO_SERIAL_S390,
 554    .parent        = TYPE_VIRTIO_S390_DEVICE,
 555    .instance_size = sizeof(VirtIOSerialS390),
 556    .instance_init = s390_virtio_serial_instance_init,
 557    .class_init    = s390_virtio_serial_class_init,
 558};
 559
 560static Property s390_virtio_rng_properties[] = {
 561    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
 562    DEFINE_PROP_END_OF_LIST(),
 563};
 564
 565static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
 566{
 567    DeviceClass *dc = DEVICE_CLASS(klass);
 568    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 569
 570    k->init = s390_virtio_rng_init;
 571    dc->props = s390_virtio_rng_properties;
 572}
 573
 574static const TypeInfo s390_virtio_rng = {
 575    .name          = TYPE_VIRTIO_RNG_S390,
 576    .parent        = TYPE_VIRTIO_S390_DEVICE,
 577    .instance_size = sizeof(VirtIORNGS390),
 578    .instance_init = s390_virtio_rng_instance_init,
 579    .class_init    = s390_virtio_rng_class_init,
 580};
 581
 582static int s390_virtio_busdev_init(DeviceState *dev)
 583{
 584    VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
 585    VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev);
 586
 587    virtio_s390_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
 588
 589    return _info->init(_dev);
 590}
 591
 592static void s390_virtio_busdev_reset(DeviceState *dev)
 593{
 594    VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
 595
 596    virtio_reset(_dev->vdev);
 597}
 598
 599static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
 600{
 601    DeviceClass *dc = DEVICE_CLASS(klass);
 602
 603    dc->init = s390_virtio_busdev_init;
 604    dc->bus_type = TYPE_S390_VIRTIO_BUS;
 605    dc->reset = s390_virtio_busdev_reset;
 606}
 607
 608static const TypeInfo virtio_s390_device_info = {
 609    .name = TYPE_VIRTIO_S390_DEVICE,
 610    .parent = TYPE_DEVICE,
 611    .instance_size = sizeof(VirtIOS390Device),
 612    .class_init = virtio_s390_device_class_init,
 613    .class_size = sizeof(VirtIOS390DeviceClass),
 614    .abstract = true,
 615};
 616
 617static Property s390_virtio_scsi_properties[] = {
 618    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
 619    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
 620    DEFINE_PROP_END_OF_LIST(),
 621};
 622
 623static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
 624{
 625    DeviceClass *dc = DEVICE_CLASS(klass);
 626    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 627
 628    k->init = s390_virtio_scsi_init;
 629    dc->props = s390_virtio_scsi_properties;
 630}
 631
 632static const TypeInfo s390_virtio_scsi = {
 633    .name          = TYPE_VIRTIO_SCSI_S390,
 634    .parent        = TYPE_VIRTIO_S390_DEVICE,
 635    .instance_size = sizeof(VirtIOSCSIS390),
 636    .instance_init = s390_virtio_scsi_instance_init,
 637    .class_init    = s390_virtio_scsi_class_init,
 638};
 639
 640#ifdef CONFIG_VHOST_SCSI
 641static Property s390_vhost_scsi_properties[] = {
 642    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
 643    DEFINE_PROP_END_OF_LIST(),
 644};
 645
 646static void s390_vhost_scsi_class_init(ObjectClass *klass, void *data)
 647{
 648    DeviceClass *dc = DEVICE_CLASS(klass);
 649    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 650
 651    k->init = s390_vhost_scsi_init;
 652    dc->props = s390_vhost_scsi_properties;
 653}
 654
 655static const TypeInfo s390_vhost_scsi = {
 656    .name          = TYPE_VHOST_SCSI_S390,
 657    .parent        = TYPE_VIRTIO_S390_DEVICE,
 658    .instance_size = sizeof(VHostSCSIS390),
 659    .instance_init = s390_vhost_scsi_instance_init,
 660    .class_init    = s390_vhost_scsi_class_init,
 661};
 662#endif
 663
 664/***************** S390 Virtio Bus Bridge Device *******************/
 665/* Only required to have the virtio bus as child in the system bus */
 666
 667static int s390_virtio_bridge_init(SysBusDevice *dev)
 668{
 669    /* nothing */
 670    return 0;
 671}
 672
 673static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data)
 674{
 675    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 676
 677    k->init = s390_virtio_bridge_init;
 678}
 679
 680static const TypeInfo s390_virtio_bridge_info = {
 681    .name          = "s390-virtio-bridge",
 682    .parent        = TYPE_SYS_BUS_DEVICE,
 683    .instance_size = sizeof(SysBusDevice),
 684    .class_init    = s390_virtio_bridge_class_init,
 685    .interfaces = (InterfaceInfo[]) {
 686        { TYPE_HOTPLUG_HANDLER },
 687        { }
 688    }
 689};
 690
 691/* virtio-s390-bus */
 692
 693static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
 694                                VirtIOS390Device *dev)
 695{
 696    DeviceState *qdev = DEVICE(dev);
 697    char virtio_bus_name[] = "virtio-bus";
 698
 699    qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_S390_BUS,
 700                        qdev, virtio_bus_name);
 701}
 702
 703static void virtio_s390_bus_class_init(ObjectClass *klass, void *data)
 704{
 705    VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
 706    BusClass *bus_class = BUS_CLASS(klass);
 707    bus_class->max_dev = 1;
 708    k->notify = virtio_s390_notify;
 709    k->get_features = virtio_s390_get_features;
 710}
 711
 712static const TypeInfo virtio_s390_bus_info = {
 713    .name          = TYPE_VIRTIO_S390_BUS,
 714    .parent        = TYPE_VIRTIO_BUS,
 715    .instance_size = sizeof(VirtioS390BusState),
 716    .class_init    = virtio_s390_bus_class_init,
 717};
 718
 719static void s390_virtio_register_types(void)
 720{
 721    type_register_static(&virtio_s390_bus_info);
 722    type_register_static(&s390_virtio_bus_info);
 723    type_register_static(&virtio_s390_device_info);
 724    type_register_static(&s390_virtio_serial);
 725    type_register_static(&s390_virtio_blk);
 726    type_register_static(&s390_virtio_net);
 727    type_register_static(&s390_virtio_scsi);
 728#ifdef CONFIG_VHOST_SCSI
 729    type_register_static(&s390_vhost_scsi);
 730#endif
 731    type_register_static(&s390_virtio_rng);
 732    type_register_static(&s390_virtio_bridge_info);
 733}
 734
 735type_init(s390_virtio_register_types)
 736