s390-virtio-bus.c 21.5 KB
Newer Older
A
Alexander Graf 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * QEMU S390 virtio target
 *
 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

A
Alexander Graf 已提交
20
#include "hw/hw.h"
21
#include "block/block.h"
22
#include "sysemu/sysemu.h"
A
Alexander Graf 已提交
23
#include "hw/boards.h"
24
#include "monitor/monitor.h"
A
Alexander Graf 已提交
25
#include "hw/loader.h"
A
Alexander Graf 已提交
26
#include "elf.h"
P
Paolo Bonzini 已提交
27 28 29 30
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-rng.h"
#include "hw/virtio/virtio-serial.h"
#include "hw/virtio/virtio-net.h"
31
#include "hw/virtio/vhost-scsi.h"
A
Alexander Graf 已提交
32
#include "hw/sysbus.h"
33
#include "sysemu/kvm.h"
A
Alexander Graf 已提交
34

A
Alexander Graf 已提交
35
#include "hw/s390x/s390-virtio-bus.h"
P
Paolo Bonzini 已提交
36
#include "hw/virtio/virtio-bus.h"
A
Alexander Graf 已提交
37 38 39 40

/* #define DEBUG_S390 */

#ifdef DEBUG_S390
41
#define DPRINTF(fmt, ...) \
A
Alexander Graf 已提交
42 43
    do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
#else
44
#define DPRINTF(fmt, ...) \
A
Alexander Graf 已提交
45 46 47
    do { } while (0)
#endif

48 49
#define VIRTIO_EXT_CODE   0x2603

50 51
static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
                                VirtIOS390Device *dev);
52

53 54 55 56
static const TypeInfo s390_virtio_bus_info = {
    .name = TYPE_S390_VIRTIO_BUS,
    .parent = TYPE_BUS,
    .instance_size = sizeof(VirtIOS390Bus),
A
Alexander Graf 已提交
57 58 59 60
};

static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev);

61
/* length of VirtIO device pages */
A
Avi Kivity 已提交
62
const hwaddr virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
63

64 65 66 67 68 69
static void s390_virtio_bus_reset(void *opaque)
{
    VirtIOS390Bus *bus = opaque;
    bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
}

70 71 72
void s390_virtio_reset_idx(VirtIOS390Device *dev)
{
    int i;
A
Avi Kivity 已提交
73
    hwaddr idx_addr;
74 75 76 77 78 79 80 81 82 83 84 85 86
    uint8_t num_vq;

    num_vq = s390_virtio_device_num_vq(dev);
    for (i = 0; i < num_vq; i++) {
        idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
            VIRTIO_VRING_AVAIL_IDX_OFFS;
        stw_phys(idx_addr, 0);
        idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
            VIRTIO_VRING_USED_IDX_OFFS;
        stw_phys(idx_addr, 0);
    }
}

A
Alexander Graf 已提交
87 88 89 90 91 92 93 94 95 96 97 98
VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
{
    VirtIOS390Bus *bus;
    BusState *_bus;
    DeviceState *dev;

    /* Create bridge device */
    dev = qdev_create(NULL, "s390-virtio-bridge");
    qdev_init_nofail(dev);

    /* Create bus on bridge device */

99
    _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio");
A
Alexander Graf 已提交
100 101 102 103 104 105
    bus = DO_UPCAST(VirtIOS390Bus, bus, _bus);

    bus->dev_page = *ram_size;
    bus->dev_offs = bus->dev_page;
    bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;

A
Alexander Graf 已提交
106 107 108
    /* Enable hotplugging */
    _bus->allow_hotplug = 1;

A
Alexander Graf 已提交
109 110 111
    /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */
    *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE;

112
    qemu_register_reset(s390_virtio_bus_reset, bus);
A
Alexander Graf 已提交
113 114 115
    return bus;
}

116
static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token)
A
Alexander Graf 已提交
117 118
{
    if (kvm_enabled()) {
119
        kvm_s390_virtio_irq(cpu, config_change, token);
A
Alexander Graf 已提交
120
    } else {
121
        cpu_inject_ext(cpu, VIRTIO_EXT_CODE, config_change, token);
A
Alexander Graf 已提交
122 123 124
    }
}

A
Alexander Graf 已提交
125 126 127 128 129 130 131 132 133 134 135 136 137
static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
{
    VirtIOS390Bus *bus;
    int dev_len;

    bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
    dev->vdev = vdev;
    dev->dev_offs = bus->dev_offs;
    dev->feat_len = sizeof(uint32_t); /* always keep 32 bits features */

    dev_len = VIRTIO_DEV_OFFS_CONFIG;
    dev_len += s390_virtio_device_num_vq(dev) * VIRTIO_VQCONFIG_LEN;
    dev_len += dev->feat_len * 2;
138
    dev_len += virtio_bus_get_vdev_config_len(&dev->bus);
A
Alexander Graf 已提交
139 140 141

    bus->dev_offs += dev_len;

142 143
    dev->host_features = virtio_bus_get_vdev_features(&dev->bus,
                                                      dev->host_features);
A
Alexander Graf 已提交
144
    s390_virtio_device_sync(dev);
145
    s390_virtio_reset_idx(dev);
A
Alexander Graf 已提交
146
    if (dev->qdev.hotplugged) {
147
        S390CPU *cpu = s390_cpu_addr2state(0);
148
        s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
A
Alexander Graf 已提交
149 150
    }

A
Alexander Graf 已提交
151 152 153
    return 0;
}

154
static int s390_virtio_net_init(VirtIOS390Device *s390_dev)
A
Alexander Graf 已提交
155
{
156
    DeviceState *qdev = DEVICE(s390_dev);
157 158
    VirtIONetS390 *dev = VIRTIO_NET_S390(s390_dev);
    DeviceState *vdev = DEVICE(&dev->vdev);
A
Alexander Graf 已提交
159

160
    virtio_net_set_config_size(&dev->vdev, s390_dev->host_features);
161 162
    virtio_net_set_netclient_name(&dev->vdev, qdev->id,
                                  object_get_typename(OBJECT(qdev)));
163 164
    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
    if (qdev_init(vdev) < 0) {
A
Alexander Graf 已提交
165 166 167
        return -1;
    }

168 169 170 171 172 173
    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
}

static void s390_virtio_net_instance_init(Object *obj)
{
    VirtIONetS390 *dev = VIRTIO_NET_S390(obj);
174
    object_initialize(&dev->vdev, TYPE_VIRTIO_NET);
175
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
A
Alexander Graf 已提交
176 177
}

178
static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
A
Alexander Graf 已提交
179
{
180 181 182 183 184
    VirtIOBlkS390 *dev = VIRTIO_BLK_S390(s390_dev);
    DeviceState *vdev = DEVICE(&dev->vdev);
    virtio_blk_set_conf(vdev, &(dev->blk));
    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
    if (qdev_init(vdev) < 0) {
A
Alexander Graf 已提交
185 186
        return -1;
    }
187 188
    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
}
A
Alexander Graf 已提交
189

190 191 192
static void s390_virtio_blk_instance_init(Object *obj)
{
    VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj);
193
    object_initialize(&dev->vdev, TYPE_VIRTIO_BLK);
194
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
A
Alexander Graf 已提交
195 196
}

197
static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
A
Alexander Graf 已提交
198
{
199 200 201
    VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(s390_dev);
    DeviceState *vdev = DEVICE(&dev->vdev);
    DeviceState *qdev = DEVICE(s390_dev);
A
Alexander Graf 已提交
202 203
    VirtIOS390Bus *bus;
    int r;
204
    char *bus_name;
A
Alexander Graf 已提交
205

206
    bus = DO_UPCAST(VirtIOS390Bus, bus, qdev->parent_bus);
A
Alexander Graf 已提交
207

208 209 210 211 212 213 214 215 216 217
    /*
     * For command line compatibility, this sets the virtio-serial-device bus
     * name as before.
     */
    if (qdev->id) {
        bus_name = g_strdup_printf("%s.0", qdev->id);
        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
        g_free(bus_name);
    }

218 219
    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
    if (qdev_init(vdev) < 0) {
A
Alexander Graf 已提交
220 221 222
        return -1;
    }

223
    r = s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
A
Alexander Graf 已提交
224
    if (!r) {
225
        bus->console = s390_dev;
A
Alexander Graf 已提交
226 227 228 229 230
    }

    return r;
}

231 232 233
static void s390_virtio_serial_instance_init(Object *obj)
{
    VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(obj);
234
    object_initialize(&dev->vdev, TYPE_VIRTIO_SERIAL);
235 236 237
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
}

238
static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
239
{
240 241
    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev);
    DeviceState *vdev = DEVICE(&dev->vdev);
242 243 244 245 246 247 248 249 250 251 252 253
    DeviceState *qdev = DEVICE(s390_dev);
    char *bus_name;

    /*
     * For command line compatibility, this sets the virtio-scsi-device bus
     * name as before.
     */
    if (qdev->id) {
        bus_name = g_strdup_printf("%s.0", qdev->id);
        virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name);
        g_free(bus_name);
    }
254

255 256
    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
    if (qdev_init(vdev) < 0) {
257 258 259
        return -1;
    }

260 261 262 263 264 265
    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
}

static void s390_virtio_scsi_instance_init(Object *obj)
{
    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj);
266
    object_initialize(&dev->vdev, TYPE_VIRTIO_SCSI);
267
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
268 269
}

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
#ifdef CONFIG_VHOST_SCSI
static int s390_vhost_scsi_init(VirtIOS390Device *s390_dev)
{
    VHostSCSIS390 *dev = VHOST_SCSI_S390(s390_dev);
    DeviceState *vdev = DEVICE(&dev->vdev);

    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
    if (qdev_init(vdev) < 0) {
        return -1;
    }

    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
}

static void s390_vhost_scsi_instance_init(Object *obj)
{
    VHostSCSIS390 *dev = VHOST_SCSI_S390(obj);
287
    object_initialize(&dev->vdev, TYPE_VHOST_SCSI);
288 289 290 291
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
}
#endif

292 293

static int s390_virtio_rng_init(VirtIOS390Device *s390_dev)
294
{
295 296
    VirtIORNGS390 *dev = VIRTIO_RNG_S390(s390_dev);
    DeviceState *vdev = DEVICE(&dev->vdev);
297

298 299
    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
    if (qdev_init(vdev) < 0) {
300 301 302
        return -1;
    }

303
    object_property_set_link(OBJECT(dev),
304
                             OBJECT(dev->vdev.conf.rng), "rng",
305 306 307 308 309 310 311 312
                             NULL);

    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
}

static void s390_virtio_rng_instance_init(Object *obj)
{
    VirtIORNGS390 *dev = VIRTIO_RNG_S390(obj);
313
    object_initialize(&dev->vdev, TYPE_VIRTIO_RNG);
314 315 316
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
                             (Object **)&dev->vdev.conf.rng, NULL);
317 318
}

A
Alexander Graf 已提交
319 320 321 322 323 324 325 326
static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
{
    ram_addr_t token_off;

    token_off = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) +
                (vq * VIRTIO_VQCONFIG_LEN) +
                VIRTIO_VQCONFIG_OFFS_TOKEN;

327
    return ldq_be_phys(token_off);
A
Alexander Graf 已提交
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
}

static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
{
    VirtIODevice *vdev = dev->vdev;
    int num_vq;

    for (num_vq = 0; num_vq < VIRTIO_PCI_QUEUE_MAX; num_vq++) {
        if (!virtio_queue_get_num(vdev, num_vq)) {
            break;
        }
    }

    return num_vq;
}

static ram_addr_t s390_virtio_next_ring(VirtIOS390Bus *bus)
{
    ram_addr_t r = bus->next_ring;

    bus->next_ring += VIRTIO_RING_LEN;
    return r;
}

A
Alexander Graf 已提交
352
void s390_virtio_device_sync(VirtIOS390Device *dev)
A
Alexander Graf 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
{
    VirtIOS390Bus *bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
    ram_addr_t cur_offs;
    uint8_t num_vq;
    int i;

    virtio_reset(dev->vdev);

    /* Sync dev space */
    stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id);

    stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, s390_virtio_device_num_vq(dev));
    stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len);

    stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len);

    num_vq = s390_virtio_device_num_vq(dev);
    stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq);

    /* Sync virtqueues */
    for (i = 0; i < num_vq; i++) {
        ram_addr_t vq = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) +
                        (i * VIRTIO_VQCONFIG_LEN);
        ram_addr_t vring;

        vring = s390_virtio_next_ring(bus);
        virtio_queue_set_addr(dev->vdev, i, vring);
        virtio_queue_set_vector(dev->vdev, i, i);
381 382
        stq_be_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
        stw_be_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i));
A
Alexander Graf 已提交
383 384 385 386 387 388 389
    }

    cur_offs = dev->dev_offs;
    cur_offs += VIRTIO_DEV_OFFS_CONFIG;
    cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;

    /* Sync feature bitmap */
390
    stl_le_phys(cur_offs, dev->host_features);
A
Alexander Graf 已提交
391 392 393 394 395

    dev->feat_offs = cur_offs + dev->feat_len;
    cur_offs += dev->feat_len * 2;

    /* Sync config space */
396
    virtio_bus_get_vdev_config(&dev->bus, dev->vdev->config);
A
Alexander Graf 已提交
397

398 399
    cpu_physical_memory_write(cur_offs,
                              dev->vdev->config, dev->vdev->config_len);
A
Alexander Graf 已提交
400 401 402 403 404 405 406 407
    cur_offs += dev->vdev->config_len;
}

void s390_virtio_device_update_status(VirtIOS390Device *dev)
{
    VirtIODevice *vdev = dev->vdev;
    uint32_t features;

408
    virtio_set_status(vdev, ldub_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS));
A
Alexander Graf 已提交
409 410 411

    /* Update guest supported feature bitmap */

412
    features = bswap32(ldl_be_phys(dev->feat_offs));
413
    virtio_set_features(vdev, features);
A
Alexander Graf 已提交
414 415 416 417 418 419 420 421 422 423 424 425
}

VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
{
    return bus->console;
}

/* Find a device by vring address */
VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
                                             ram_addr_t mem,
                                             int *vq_num)
{
A
Anthony Liguori 已提交
426
    BusChild *kid;
A
Alexander Graf 已提交
427 428
    int i;

A
Anthony Liguori 已提交
429 430 431
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;

A
Alexander Graf 已提交
432
        for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
A
Anthony Liguori 已提交
433
            if (!virtio_queue_get_addr(dev->vdev, i))
A
Alexander Graf 已提交
434
                break;
A
Anthony Liguori 已提交
435
            if (virtio_queue_get_addr(dev->vdev, i) == mem) {
A
Alexander Graf 已提交
436 437 438
                if (vq_num) {
                    *vq_num = i;
                }
A
Anthony Liguori 已提交
439
                return dev;
A
Alexander Graf 已提交
440 441 442 443 444 445 446 447 448 449
            }
        }
    }

    return NULL;
}

/* Find a device by device descriptor location */
VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
{
A
Anthony Liguori 已提交
450
    BusChild *kid;
A
Alexander Graf 已提交
451

A
Anthony Liguori 已提交
452 453 454 455
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
        VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
        if (dev->dev_offs == mem) {
            return dev;
A
Alexander Graf 已提交
456 457 458 459 460 461
        }
    }

    return NULL;
}

462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
/* DeviceState to VirtIOS390Device. Note: used on datapath,
 * be careful and test performance if you change this.
 */
static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d)
{
    return container_of(d, VirtIOS390Device, qdev);
}

/* DeviceState to VirtIOS390Device. TODO: use QOM. */
static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d)
{
    return container_of(d, VirtIOS390Device, qdev);
}

static void virtio_s390_notify(DeviceState *d, uint16_t vector)
A
Alexander Graf 已提交
477
{
478
    VirtIOS390Device *dev = to_virtio_s390_device_fast(d);
A
Alexander Graf 已提交
479
    uint64_t token = s390_virtio_device_vq_token(dev, vector);
480
    S390CPU *cpu = s390_cpu_addr2state(0);
A
Alexander Graf 已提交
481

482
    s390_virtio_irq(cpu, 0, token);
A
Alexander Graf 已提交
483 484
}

485
static unsigned virtio_s390_get_features(DeviceState *d)
486
{
487
    VirtIOS390Device *dev = to_virtio_s390_device(d);
488 489 490
    return dev->host_features;
}

A
Alexander Graf 已提交
491 492
/**************** S390 Virtio Bus Device Descriptions *******************/

493
static Property s390_virtio_net_properties[] = {
494
    DEFINE_NIC_PROPERTIES(VirtIONetS390, vdev.nic_conf),
495
    DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
496
    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetS390, vdev.net_conf),
497 498 499
    DEFINE_PROP_END_OF_LIST(),
};

500 501
static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
{
502 503
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
504

505 506
    k->init = s390_virtio_net_init;
    dc->props = s390_virtio_net_properties;
507 508
}

509
static const TypeInfo s390_virtio_net = {
510
    .name          = TYPE_VIRTIO_NET_S390,
511
    .parent        = TYPE_VIRTIO_S390_DEVICE,
512 513
    .instance_size = sizeof(VirtIONetS390),
    .instance_init = s390_virtio_net_instance_init,
514 515 516 517
    .class_init    = s390_virtio_net_class_init,
};

static Property s390_virtio_blk_properties[] = {
518
    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkS390, blk),
519
    DEFINE_PROP_END_OF_LIST(),
A
Alexander Graf 已提交
520 521
};

522 523
static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
{
524 525
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
526

527 528
    k->init = s390_virtio_blk_init;
    dc->props = s390_virtio_blk_properties;
529 530
}

531
static const TypeInfo s390_virtio_blk = {
532 533
    .name          = "virtio-blk-s390",
    .parent        = TYPE_VIRTIO_S390_DEVICE,
534 535
    .instance_size = sizeof(VirtIOBlkS390),
    .instance_init = s390_virtio_blk_instance_init,
536 537 538 539
    .class_init    = s390_virtio_blk_class_init,
};

static Property s390_virtio_serial_properties[] = {
540
    DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerialS390, vdev.serial),
541
    DEFINE_PROP_END_OF_LIST(),
A
Alexander Graf 已提交
542 543
};

544 545
static void s390_virtio_serial_class_init(ObjectClass *klass, void *data)
{
546 547
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
548

549 550
    k->init = s390_virtio_serial_init;
    dc->props = s390_virtio_serial_properties;
551 552
}

553
static const TypeInfo s390_virtio_serial = {
554
    .name          = TYPE_VIRTIO_SERIAL_S390,
555
    .parent        = TYPE_VIRTIO_S390_DEVICE,
556 557
    .instance_size = sizeof(VirtIOSerialS390),
    .instance_init = s390_virtio_serial_instance_init,
558
    .class_init    = s390_virtio_serial_class_init,
A
Alexander Graf 已提交
559 560
};

561 562 563 564 565 566
static Property s390_virtio_rng_properties[] = {
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
    DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNGS390, vdev.conf),
    DEFINE_PROP_END_OF_LIST(),
};

567 568
static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
{
569
    DeviceClass *dc = DEVICE_CLASS(klass);
570 571 572
    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);

    k->init = s390_virtio_rng_init;
573
    dc->props = s390_virtio_rng_properties;
574 575
}

576
static const TypeInfo s390_virtio_rng = {
577
    .name          = TYPE_VIRTIO_RNG_S390,
578
    .parent        = TYPE_VIRTIO_S390_DEVICE,
579 580
    .instance_size = sizeof(VirtIORNGS390),
    .instance_init = s390_virtio_rng_instance_init,
581 582 583
    .class_init    = s390_virtio_rng_class_init,
};

A
Anthony Liguori 已提交
584
static int s390_virtio_busdev_init(DeviceState *dev)
A
Alexander Graf 已提交
585 586
{
    VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
587
    VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev);
A
Alexander Graf 已提交
588

589
    virtio_s390_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
590

A
Alexander Graf 已提交
591 592 593
    return _info->init(_dev);
}

594 595 596 597 598 599 600
static void s390_virtio_busdev_reset(DeviceState *dev)
{
    VirtIOS390Device *_dev = (VirtIOS390Device *)dev;

    virtio_reset(_dev->vdev);
}

601
static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
A
Alexander Graf 已提交
602
{
603
    DeviceClass *dc = DEVICE_CLASS(klass);
A
Alexander Graf 已提交
604

605
    dc->init = s390_virtio_busdev_init;
606
    dc->bus_type = TYPE_S390_VIRTIO_BUS;
607
    dc->unplug = qdev_simple_unplug_cb;
608
    dc->reset = s390_virtio_busdev_reset;
A
Alexander Graf 已提交
609 610
}

611
static const TypeInfo virtio_s390_device_info = {
612 613 614
    .name = TYPE_VIRTIO_S390_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(VirtIOS390Device),
615
    .class_init = virtio_s390_device_class_init,
616
    .class_size = sizeof(VirtIOS390DeviceClass),
617 618 619
    .abstract = true,
};

620
static Property s390_virtio_scsi_properties[] = {
621
    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIS390, vdev.parent_obj.conf),
622
    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
623 624 625 626 627 628 629 630 631 632 633 634
    DEFINE_PROP_END_OF_LIST(),
};

static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);

    k->init = s390_virtio_scsi_init;
    dc->props = s390_virtio_scsi_properties;
}

635
static const TypeInfo s390_virtio_scsi = {
636
    .name          = TYPE_VIRTIO_SCSI_S390,
637
    .parent        = TYPE_VIRTIO_S390_DEVICE,
638 639
    .instance_size = sizeof(VirtIOSCSIS390),
    .instance_init = s390_virtio_scsi_instance_init,
640 641
    .class_init    = s390_virtio_scsi_class_init,
};
A
Alexander Graf 已提交
642

643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
#ifdef CONFIG_VHOST_SCSI
static Property s390_vhost_scsi_properties[] = {
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features),
    DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSIS390, vdev.parent_obj.conf),
    DEFINE_PROP_END_OF_LIST(),
};

static void s390_vhost_scsi_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);

    k->init = s390_vhost_scsi_init;
    dc->props = s390_vhost_scsi_properties;
}

static const TypeInfo s390_vhost_scsi = {
    .name          = TYPE_VHOST_SCSI_S390,
    .parent        = TYPE_VIRTIO_S390_DEVICE,
    .instance_size = sizeof(VHostSCSIS390),
    .instance_init = s390_vhost_scsi_instance_init,
    .class_init    = s390_vhost_scsi_class_init,
};
#endif

A
Alexander Graf 已提交
668 669 670 671 672 673 674 675 676
/***************** S390 Virtio Bus Bridge Device *******************/
/* Only required to have the virtio bus as child in the system bus */

static int s390_virtio_bridge_init(SysBusDevice *dev)
{
    /* nothing */
    return 0;
}

677 678
static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data)
{
679
    DeviceClass *dc = DEVICE_CLASS(klass);
680 681 682
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = s390_virtio_bridge_init;
683
    dc->no_user = 1;
684 685
}

686
static const TypeInfo s390_virtio_bridge_info = {
687 688 689 690
    .name          = "s390-virtio-bridge",
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(SysBusDevice),
    .class_init    = s390_virtio_bridge_class_init,
A
Alexander Graf 已提交
691 692
};

693 694
/* virtio-s390-bus */

695 696
static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
                                VirtIOS390Device *dev)
697 698 699
{
    DeviceState *qdev = DEVICE(dev);
    BusState *qbus;
700 701
    char virtio_bus_name[] = "virtio-bus";

702 703
    qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_S390_BUS,
                        qdev, virtio_bus_name);
704
    qbus = BUS(bus);
705
    qbus->allow_hotplug = 1;
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
}

static void virtio_s390_bus_class_init(ObjectClass *klass, void *data)
{
    VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
    BusClass *bus_class = BUS_CLASS(klass);
    bus_class->max_dev = 1;
    k->notify = virtio_s390_notify;
    k->get_features = virtio_s390_get_features;
}

static const TypeInfo virtio_s390_bus_info = {
    .name          = TYPE_VIRTIO_S390_BUS,
    .parent        = TYPE_VIRTIO_BUS,
    .instance_size = sizeof(VirtioS390BusState),
    .class_init    = virtio_s390_bus_class_init,
};

A
Andreas Färber 已提交
724
static void s390_virtio_register_types(void)
A
Alexander Graf 已提交
725
{
726
    type_register_static(&virtio_s390_bus_info);
727
    type_register_static(&s390_virtio_bus_info);
A
Andreas Färber 已提交
728 729 730 731
    type_register_static(&virtio_s390_device_info);
    type_register_static(&s390_virtio_serial);
    type_register_static(&s390_virtio_blk);
    type_register_static(&s390_virtio_net);
732
    type_register_static(&s390_virtio_scsi);
733
#ifdef CONFIG_VHOST_SCSI
734
    type_register_static(&s390_vhost_scsi);
735
#endif
736
    type_register_static(&s390_virtio_rng);
737
    type_register_static(&s390_virtio_bridge_info);
A
Alexander Graf 已提交
738 739
}

A
Andreas Färber 已提交
740
type_init(s390_virtio_register_types)