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