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