virtio-pci.c 34.6 KB
Newer Older
P
Paul Brook 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Virtio PCI Bindings
 *
 * Copyright IBM, Corp. 2007
 * Copyright (c) 2009 CodeSourcery
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *  Paul Brook        <paul@codesourcery.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
14 15
 * Contributions after 2012-01-13 are licensed under the terms of the
 * GNU GPL, version 2 or (at your option) any later version.
P
Paul Brook 已提交
16 17 18 19 20
 */

#include <inttypes.h>

#include "virtio.h"
21 22
#include "virtio-blk.h"
#include "virtio-net.h"
23
#include "virtio-serial.h"
24
#include "virtio-scsi.h"
25
#include "pci/pci.h"
26
#include "qemu/error-report.h"
27 28
#include "pci/msi.h"
#include "pci/msix.h"
29
#include "loader.h"
30
#include "kvm.h"
B
Blue Swirl 已提交
31
#include "blockdev.h"
32
#include "virtio-pci.h"
33
#include "qemu/range.h"
P
Paul Brook 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

/* from Linux's linux/virtio_pci.h */

/* A 32-bit r/o bitmask of the features supported by the host */
#define VIRTIO_PCI_HOST_FEATURES        0

/* A 32-bit r/w bitmask of features activated by the guest */
#define VIRTIO_PCI_GUEST_FEATURES       4

/* A 32-bit r/w PFN for the currently selected queue */
#define VIRTIO_PCI_QUEUE_PFN            8

/* A 16-bit r/o queue size for the currently selected queue */
#define VIRTIO_PCI_QUEUE_NUM            12

/* A 16-bit r/w queue selector */
#define VIRTIO_PCI_QUEUE_SEL            14

/* A 16-bit r/w queue notifier */
#define VIRTIO_PCI_QUEUE_NOTIFY         16

/* An 8-bit device status register.  */
#define VIRTIO_PCI_STATUS               18

/* An 8-bit r/o interrupt status register.  Reading the value will return the
 * current contents of the ISR and will also clear it.  This is effectively
 * a read-and-acknowledge. */
#define VIRTIO_PCI_ISR                  19

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
/* MSI-X registers: only enabled if MSI-X is enabled. */
/* A 16-bit vector for configuration changes. */
#define VIRTIO_MSI_CONFIG_VECTOR        20
/* A 16-bit vector for selected queue notifications. */
#define VIRTIO_MSI_QUEUE_VECTOR         22

/* Config space size */
#define VIRTIO_PCI_CONFIG_NOMSI         20
#define VIRTIO_PCI_CONFIG_MSI           24
#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
                                         VIRTIO_PCI_CONFIG_MSI : \
                                         VIRTIO_PCI_CONFIG_NOMSI)

/* The remaining space is defined by each driver as the per-driver
 * configuration space */
#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
                                         VIRTIO_PCI_CONFIG_MSI : \
                                         VIRTIO_PCI_CONFIG_NOMSI)
P
Paul Brook 已提交
81 82 83 84 85

/* How many bits to shift physical queue address written to QUEUE_PFN.
 * 12 is historical, and due to x86 page size. */
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12

86 87
/* Flags track per-device state like workarounds for quirks in older guests. */
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG  (1 << 0)
88

P
Paul Brook 已提交
89 90 91 92 93 94
/* QEMU doesn't strictly need write barriers since everything runs in
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
 * KVM or if kqemu gets SMP support.
 */
#define wmb() do { } while (0)

95 96 97
/* HACK for virtio to determine if it's running a big endian guest */
bool virtio_is_big_endian(void);

P
Paul Brook 已提交
98 99
/* virtio device */

100
static void virtio_pci_notify(void *opaque, uint16_t vector)
P
Paul Brook 已提交
101 102
{
    VirtIOPCIProxy *proxy = opaque;
103 104 105 106
    if (msix_enabled(&proxy->pci_dev))
        msix_notify(&proxy->pci_dev, vector);
    else
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
P
Paul Brook 已提交
107 108
}

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
static void virtio_pci_save_config(void * opaque, QEMUFile *f)
{
    VirtIOPCIProxy *proxy = opaque;
    pci_device_save(&proxy->pci_dev, f);
    msix_save(&proxy->pci_dev, f);
    if (msix_present(&proxy->pci_dev))
        qemu_put_be16(f, proxy->vdev->config_vector);
}

static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
{
    VirtIOPCIProxy *proxy = opaque;
    if (msix_present(&proxy->pci_dev))
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
}

static int virtio_pci_load_config(void * opaque, QEMUFile *f)
{
    VirtIOPCIProxy *proxy = opaque;
    int ret;
    ret = pci_device_load(&proxy->pci_dev, f);
130
    if (ret) {
131
        return ret;
132
    }
133
    msix_unuse_all_vectors(&proxy->pci_dev);
134
    msix_load(&proxy->pci_dev, f);
135
    if (msix_present(&proxy->pci_dev)) {
136
        qemu_get_be16s(f, &proxy->vdev->config_vector);
137 138 139 140 141 142
    } else {
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
    }
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
    }
143 144 145 146 147 148 149
    return 0;
}

static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
{
    VirtIOPCIProxy *proxy = opaque;
    uint16_t vector;
150 151 152 153 154
    if (msix_present(&proxy->pci_dev)) {
        qemu_get_be16s(f, &vector);
    } else {
        vector = VIRTIO_NO_VECTOR;
    }
155
    virtio_queue_set_vector(proxy->vdev, n, vector);
156 157 158
    if (vector != VIRTIO_NO_VECTOR) {
        return msix_vector_use(&proxy->pci_dev, vector);
    }
159 160 161
    return 0;
}

162
static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
P
Paolo Bonzini 已提交
163
                                                 int n, bool assign, bool set_handler)
164 165 166
{
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
A
Avi Kivity 已提交
167 168
    int r = 0;

169 170 171
    if (assign) {
        r = event_notifier_init(notifier, 1);
        if (r < 0) {
172 173
            error_report("%s: unable to init event notifier: %d",
                         __func__, r);
174 175
            return r;
        }
P
Paolo Bonzini 已提交
176
        virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
A
Avi Kivity 已提交
177
        memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
178
                                  true, n, notifier);
179
    } else {
A
Avi Kivity 已提交
180
        memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
181
                                  true, n, notifier);
P
Paolo Bonzini 已提交
182
        virtio_queue_set_host_notifier_fd_handler(vq, false, false);
183 184 185 186 187
        event_notifier_cleanup(notifier);
    }
    return r;
}

188
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
189 190 191 192 193 194
{
    int n, r;

    if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
        proxy->ioeventfd_disabled ||
        proxy->ioeventfd_started) {
195
        return;
196 197 198 199 200 201 202
    }

    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
        if (!virtio_queue_get_num(proxy->vdev, n)) {
            continue;
        }

P
Paolo Bonzini 已提交
203
        r = virtio_pci_set_host_notifier_internal(proxy, n, true, true);
204 205 206 207 208
        if (r < 0) {
            goto assign_error;
        }
    }
    proxy->ioeventfd_started = true;
209
    return;
210 211 212 213 214 215 216

assign_error:
    while (--n >= 0) {
        if (!virtio_queue_get_num(proxy->vdev, n)) {
            continue;
        }

P
Paolo Bonzini 已提交
217
        r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
218
        assert(r >= 0);
219 220
    }
    proxy->ioeventfd_started = false;
221
    error_report("%s: failed. Fallback to a userspace (slower).", __func__);
222 223
}

224
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
225
{
226
    int r;
227 228 229
    int n;

    if (!proxy->ioeventfd_started) {
230
        return;
231 232 233 234 235 236 237
    }

    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
        if (!virtio_queue_get_num(proxy->vdev, n)) {
            continue;
        }

P
Paolo Bonzini 已提交
238
        r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
239
        assert(r >= 0);
240 241 242 243
    }
    proxy->ioeventfd_started = false;
}

244
void virtio_pci_reset(DeviceState *d)
245
{
246
    VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
247
    virtio_pci_stop_ioeventfd(proxy);
248
    virtio_reset(proxy->vdev);
249
    msix_unuse_all_vectors(&proxy->pci_dev);
250
    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
251 252
}

P
Paul Brook 已提交
253 254 255 256
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
    VirtIOPCIProxy *proxy = opaque;
    VirtIODevice *vdev = proxy->vdev;
A
Avi Kivity 已提交
257
    hwaddr pa;
P
Paul Brook 已提交
258 259 260 261 262

    switch (addr) {
    case VIRTIO_PCI_GUEST_FEATURES:
	/* Guest does not negotiate properly?  We have to assume nothing. */
	if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
263
            val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
P
Paul Brook 已提交
264
	}
265
        virtio_set_features(vdev, val);
P
Paul Brook 已提交
266 267
        break;
    case VIRTIO_PCI_QUEUE_PFN:
A
Avi Kivity 已提交
268
        pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
269
        if (pa == 0) {
270
            virtio_pci_stop_ioeventfd(proxy);
271 272 273
            virtio_reset(proxy->vdev);
            msix_unuse_all_vectors(&proxy->pci_dev);
        }
274 275
        else
            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
P
Paul Brook 已提交
276 277 278 279 280 281
        break;
    case VIRTIO_PCI_QUEUE_SEL:
        if (val < VIRTIO_PCI_QUEUE_MAX)
            vdev->queue_sel = val;
        break;
    case VIRTIO_PCI_QUEUE_NOTIFY:
282 283 284
        if (val < VIRTIO_PCI_QUEUE_MAX) {
            virtio_queue_notify(vdev, val);
        }
P
Paul Brook 已提交
285 286
        break;
    case VIRTIO_PCI_STATUS:
287 288 289 290
        if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
            virtio_pci_stop_ioeventfd(proxy);
        }

291
        virtio_set_status(vdev, val & 0xFF);
292 293 294 295 296

        if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
            virtio_pci_start_ioeventfd(proxy);
        }

297 298 299 300
        if (vdev->status == 0) {
            virtio_reset(proxy->vdev);
            msix_unuse_all_vectors(&proxy->pci_dev);
        }
301 302 303 304 305 306

        /* Linux before 2.6.34 sets the device as OK without enabling
           the PCI device bus master bit. In this case we need to disable
           some safety checks. */
        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
307
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
308
        }
P
Paul Brook 已提交
309
        break;
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
    case VIRTIO_MSI_CONFIG_VECTOR:
        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
        /* Make it possible for guest to discover an error took place. */
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
            val = VIRTIO_NO_VECTOR;
        vdev->config_vector = val;
        break;
    case VIRTIO_MSI_QUEUE_VECTOR:
        msix_vector_unuse(&proxy->pci_dev,
                          virtio_queue_vector(vdev, vdev->queue_sel));
        /* Make it possible for guest to discover an error took place. */
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
            val = VIRTIO_NO_VECTOR;
        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
        break;
    default:
326 327
        error_report("%s: unexpected address 0x%x value 0x%x",
                     __func__, addr, val);
328
        break;
P
Paul Brook 已提交
329 330 331
    }
}

332
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
P
Paul Brook 已提交
333 334 335 336 337 338
{
    VirtIODevice *vdev = proxy->vdev;
    uint32_t ret = 0xFFFFFFFF;

    switch (addr) {
    case VIRTIO_PCI_HOST_FEATURES:
339
        ret = proxy->host_features;
P
Paul Brook 已提交
340 341
        break;
    case VIRTIO_PCI_GUEST_FEATURES:
342
        ret = vdev->guest_features;
P
Paul Brook 已提交
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
        break;
    case VIRTIO_PCI_QUEUE_PFN:
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
        break;
    case VIRTIO_PCI_QUEUE_NUM:
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
        break;
    case VIRTIO_PCI_QUEUE_SEL:
        ret = vdev->queue_sel;
        break;
    case VIRTIO_PCI_STATUS:
        ret = vdev->status;
        break;
    case VIRTIO_PCI_ISR:
        /* reading from the ISR also clears it. */
        ret = vdev->isr;
        vdev->isr = 0;
361
        qemu_set_irq(proxy->pci_dev.irq[0], 0);
P
Paul Brook 已提交
362
        break;
363 364 365 366 367 368
    case VIRTIO_MSI_CONFIG_VECTOR:
        ret = vdev->config_vector;
        break;
    case VIRTIO_MSI_QUEUE_VECTOR:
        ret = virtio_queue_vector(vdev, vdev->queue_sel);
        break;
P
Paul Brook 已提交
369 370 371 372 373 374 375
    default:
        break;
    }

    return ret;
}

376 377
static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr,
                                       unsigned size)
P
Paul Brook 已提交
378 379
{
    VirtIOPCIProxy *proxy = opaque;
380
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
381
    uint64_t val = 0;
382
    if (addr < config) {
383
        return virtio_ioport_read(proxy, addr);
384 385
    }
    addr -= config;
P
Paul Brook 已提交
386

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
    switch (size) {
    case 1:
        val = virtio_config_readb(proxy->vdev, addr);
        break;
    case 2:
        val = virtio_config_readw(proxy->vdev, addr);
        if (virtio_is_big_endian()) {
            val = bswap16(val);
        }
        break;
    case 4:
        val = virtio_config_readl(proxy->vdev, addr);
        if (virtio_is_big_endian()) {
            val = bswap32(val);
        }
        break;
403
    }
404
    return val;
P
Paul Brook 已提交
405 406
}

407 408
static void virtio_pci_config_write(void *opaque, hwaddr addr,
                                    uint64_t val, unsigned size)
P
Paul Brook 已提交
409 410
{
    VirtIOPCIProxy *proxy = opaque;
411 412 413 414 415 416
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
    if (addr < config) {
        virtio_ioport_write(proxy, addr, val);
        return;
    }
    addr -= config;
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
    /*
     * Virtio-PCI is odd. Ioports are LE but config space is target native
     * endian.
     */
    switch (size) {
    case 1:
        virtio_config_writeb(proxy->vdev, addr, val);
        break;
    case 2:
        if (virtio_is_big_endian()) {
            val = bswap16(val);
        }
        virtio_config_writew(proxy->vdev, addr, val);
        break;
    case 4:
        if (virtio_is_big_endian()) {
            val = bswap32(val);
        }
        virtio_config_writel(proxy->vdev, addr, val);
        break;
437
    }
P
Paul Brook 已提交
438 439
}

A
Avi Kivity 已提交
440
static const MemoryRegionOps virtio_pci_config_ops = {
441 442 443 444 445 446
    .read = virtio_pci_config_read,
    .write = virtio_pci_config_write,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 4,
    },
A
Avi Kivity 已提交
447 448
    .endianness = DEVICE_LITTLE_ENDIAN,
};
449 450 451 452

static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
                                uint32_t val, int len)
{
453 454
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

455 456 457 458 459 460 461 462
    pci_default_write_config(pci_dev, address, val, len);

    if (range_covers_byte(address, len, PCI_COMMAND) &&
        !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
        !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
        virtio_pci_stop_ioeventfd(proxy);
        virtio_set_status(proxy->vdev,
                          proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
463
    }
P
Paul Brook 已提交
464 465
}

466 467
static unsigned virtio_pci_get_features(void *opaque)
{
468 469
    VirtIOPCIProxy *proxy = opaque;
    return proxy->host_features;
470 471
}

472 473 474 475 476 477
static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
                                        unsigned int queue_no,
                                        unsigned int vector,
                                        MSIMessage msg)
{
    VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
478
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
479
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
480
    int ret;
481 482 483 484 485 486 487 488 489 490

    if (irqfd->users == 0) {
        ret = kvm_irqchip_add_msi_route(kvm_state, msg);
        if (ret < 0) {
            return ret;
        }
        irqfd->virq = ret;
    }
    irqfd->users++;

J
Jan Kiszka 已提交
491
    ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
492 493 494 495 496 497 498
    if (ret < 0) {
        if (--irqfd->users == 0) {
            kvm_irqchip_release_virq(kvm_state, irqfd->virq);
        }
        return ret;
    }

499
    virtio_queue_set_guest_notifier_fd_handler(vq, true, true);
500 501 502 503 504 505 506 507
    return 0;
}

static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
                                             unsigned int queue_no,
                                             unsigned int vector)
{
    VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
508
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
509
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
510
    int ret;
511

J
Jan Kiszka 已提交
512
    ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq);
513 514 515 516 517 518
    assert(ret == 0);

    if (--irqfd->users == 0) {
        kvm_irqchip_release_virq(kvm_state, irqfd->virq);
    }

519
    virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
}

static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector,
                                     MSIMessage msg)
{
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
    VirtIODevice *vdev = proxy->vdev;
    int ret, queue_no;

    for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
        if (!virtio_queue_get_num(vdev, queue_no)) {
            break;
        }
        if (virtio_queue_vector(vdev, queue_no) != vector) {
            continue;
        }
        ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector, msg);
        if (ret < 0) {
            goto undo;
        }
    }
    return 0;

undo:
    while (--queue_no >= 0) {
        if (virtio_queue_vector(vdev, queue_no) != vector) {
            continue;
        }
        kvm_virtio_pci_vq_vector_release(proxy, queue_no, vector);
    }
    return ret;
}

static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector)
{
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
    VirtIODevice *vdev = proxy->vdev;
    int queue_no;

    for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
        if (!virtio_queue_get_num(vdev, queue_no)) {
            break;
        }
        if (virtio_queue_vector(vdev, queue_no) != vector) {
            continue;
        }
        kvm_virtio_pci_vq_vector_release(proxy, queue_no, vector);
    }
}

570 571 572 573 574 575 576 577 578 579 580
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
{
    VirtIOPCIProxy *proxy = opaque;
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);

    if (assign) {
        int r = event_notifier_init(notifier, 0);
        if (r < 0) {
            return r;
        }
581
        virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
582
    } else {
583
        virtio_queue_set_guest_notifier_fd_handler(vq, false, false);
584 585 586 587 588 589
        event_notifier_cleanup(notifier);
    }

    return 0;
}

590 591 592 593 594 595
static bool virtio_pci_query_guest_notifiers(void *opaque)
{
    VirtIOPCIProxy *proxy = opaque;
    return msix_enabled(&proxy->pci_dev);
}

596 597 598 599 600 601
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
{
    VirtIOPCIProxy *proxy = opaque;
    VirtIODevice *vdev = proxy->vdev;
    int r, n;

602
    /* Must unset vector notifier while guest notifier is still assigned */
603
    if (kvm_msi_via_irqfd_enabled() && !assign) {
604 605 606 607 608
        msix_unset_vector_notifiers(&proxy->pci_dev);
        g_free(proxy->vector_irqfd);
        proxy->vector_irqfd = NULL;
    }

609 610 611 612 613 614 615 616 617 618 619
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
        if (!virtio_queue_get_num(vdev, n)) {
            break;
        }

        r = virtio_pci_set_guest_notifier(opaque, n, assign);
        if (r < 0) {
            goto assign_error;
        }
    }

620
    /* Must set vector notifier after guest notifier has been assigned */
621
    if (kvm_msi_via_irqfd_enabled() && assign) {
622 623 624 625 626 627 628 629 630 631 632
        proxy->vector_irqfd =
            g_malloc0(sizeof(*proxy->vector_irqfd) *
                      msix_nr_vectors_allocated(&proxy->pci_dev));
        r = msix_set_vector_notifiers(&proxy->pci_dev,
                                      kvm_virtio_pci_vector_use,
                                      kvm_virtio_pci_vector_release);
        if (r < 0) {
            goto assign_error;
        }
    }

633 634 635 636
    return 0;

assign_error:
    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
637
    assert(assign);
638 639 640 641 642 643
    while (--n >= 0) {
        virtio_pci_set_guest_notifier(opaque, n, !assign);
    }
    return r;
}

644 645 646
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
{
    VirtIOPCIProxy *proxy = opaque;
647 648 649 650 651

    /* Stop using ioeventfd for virtqueue kick if the device starts using host
     * notifiers.  This makes it easy to avoid stepping on each others' toes.
     */
    proxy->ioeventfd_disabled = assign;
652
    if (assign) {
653 654 655 656 657 658
        virtio_pci_stop_ioeventfd(proxy);
    }
    /* We don't need to start here: it's not needed because backend
     * currently only stops on status change away from ok,
     * reset, vmstop and such. If we do add code to start here,
     * need to check vmstate, device state etc. */
P
Paolo Bonzini 已提交
659
    return virtio_pci_set_host_notifier_internal(proxy, n, assign, false);
660 661 662 663 664 665 666
}

static void virtio_pci_vmstate_change(void *opaque, bool running)
{
    VirtIOPCIProxy *proxy = opaque;

    if (running) {
667 668 669 670 671 672
        /* Try to find out if the guest has bus master disabled, but is
           in ready state. Then we have a buggy guest OS. */
        if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
        }
673
        virtio_pci_start_ioeventfd(proxy);
674
    } else {
675
        virtio_pci_stop_ioeventfd(proxy);
676 677 678
    }
}

P
Paul Brook 已提交
679
static const VirtIOBindings virtio_pci_bindings = {
680 681 682 683 684
    .notify = virtio_pci_notify,
    .save_config = virtio_pci_save_config,
    .load_config = virtio_pci_load_config,
    .save_queue = virtio_pci_save_queue,
    .load_queue = virtio_pci_load_queue,
685
    .get_features = virtio_pci_get_features,
686
    .query_guest_notifiers = virtio_pci_query_guest_notifiers,
687
    .set_host_notifier = virtio_pci_set_host_notifier,
688
    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
689
    .vmstate_change = virtio_pci_vmstate_change,
P
Paul Brook 已提交
690 691
};

692
void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
P
Paul Brook 已提交
693 694 695 696 697 698 699 700
{
    uint8_t *config;
    uint32_t size;

    proxy->vdev = vdev;

    config = proxy->pci_dev.config;

701 702 703
    if (proxy->class_code) {
        pci_config_set_class(config, proxy->class_code);
    }
H
Hui Kai Ran 已提交
704 705 706 707
    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
                 pci_get_word(config + PCI_VENDOR_ID));
    pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
    config[PCI_INTERRUPT_PIN] = 1;
P
Paul Brook 已提交
708

709 710
    if (vdev->nvectors &&
        msix_init_exclusive_bar(&proxy->pci_dev, vdev->nvectors, 1)) {
711
        vdev->nvectors = 0;
712
    }
713

714 715
    proxy->pci_dev.config_write = virtio_write_config;

716
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
P
Paul Brook 已提交
717 718 719
    if (size & (size-1))
        size = 1 << qemu_fls(size);

A
Avi Kivity 已提交
720 721
    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
                          "virtio-pci", size);
722 723
    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
                     &proxy->bar);
P
Paul Brook 已提交
724

725 726 727 728
    if (!kvm_has_many_ioeventfds()) {
        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
    }

P
Paul Brook 已提交
729
    virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
730 731 732
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
P
Paul Brook 已提交
733 734
}

735
static int virtio_blk_init_pci(PCIDevice *pci_dev)
P
Paul Brook 已提交
736 737 738 739
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
    VirtIODevice *vdev;

740 741 742
    if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
        proxy->class_code != PCI_CLASS_STORAGE_OTHER)
        proxy->class_code = PCI_CLASS_STORAGE_SCSI;
P
Paul Brook 已提交
743

P
Paolo Bonzini 已提交
744
    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->blk);
745 746 747
    if (!vdev) {
        return -1;
    }
G
Gerd Hoffmann 已提交
748
    vdev->nvectors = proxy->nvectors;
749
    virtio_init_pci(proxy, vdev);
G
Gerd Hoffmann 已提交
750 751
    /* make the actual value visible */
    proxy->nvectors = vdev->nvectors;
752
    return 0;
753 754
}

755
static void virtio_exit_pci(PCIDevice *pci_dev)
756
{
A
Avi Kivity 已提交
757 758 759
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

    memory_region_destroy(&proxy->bar);
760
    msix_uninit_exclusive_bar(pci_dev);
761 762
}

763
static void virtio_blk_exit_pci(PCIDevice *pci_dev)
G
Gerd Hoffmann 已提交
764 765 766
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

767
    virtio_pci_stop_ioeventfd(proxy);
768
    virtio_blk_exit(proxy->vdev);
769
    virtio_exit_pci(pci_dev);
G
Gerd Hoffmann 已提交
770 771
}

772
static int virtio_serial_init_pci(PCIDevice *pci_dev)
773
{
774
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
775 776
    VirtIODevice *vdev;

777 778 779 780 781
    if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
        proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
        proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
        proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;

782
    vdev = virtio_serial_init(&pci_dev->qdev, &proxy->serial);
783 784 785
    if (!vdev) {
        return -1;
    }
786
    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
787
                                        ? proxy->serial.max_virtserial_ports + 1
788
                                        : proxy->nvectors;
789
    virtio_init_pci(proxy, vdev);
790
    proxy->nvectors = vdev->nvectors;
791
    return 0;
P
Paul Brook 已提交
792 793
}

794
static void virtio_serial_exit_pci(PCIDevice *pci_dev)
795 796 797
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

A
Amit Shah 已提交
798
    virtio_pci_stop_ioeventfd(proxy);
799
    virtio_serial_exit(proxy->vdev);
800
    virtio_exit_pci(pci_dev);
801 802
}

803
static int virtio_net_init_pci(PCIDevice *pci_dev)
P
Paul Brook 已提交
804 805 806 807
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
    VirtIODevice *vdev;

808
    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
809

810
    vdev->nvectors = proxy->nvectors;
811
    virtio_init_pci(proxy, vdev);
812 813 814

    /* make the actual value visible */
    proxy->nvectors = vdev->nvectors;
815
    return 0;
P
Paul Brook 已提交
816 817
}

818
static void virtio_net_exit_pci(PCIDevice *pci_dev)
819 820 821
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

822
    virtio_pci_stop_ioeventfd(proxy);
823
    virtio_net_exit(proxy->vdev);
824
    virtio_exit_pci(pci_dev);
825 826
}

827
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
P
Paul Brook 已提交
828 829 830 831
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
    VirtIODevice *vdev;

832 833 834 835 836
    if (proxy->class_code != PCI_CLASS_OTHERS &&
        proxy->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
        proxy->class_code = PCI_CLASS_OTHERS;
    }

P
Paul Brook 已提交
837
    vdev = virtio_balloon_init(&pci_dev->qdev);
838 839 840
    if (!vdev) {
        return -1;
    }
841
    virtio_init_pci(proxy, vdev);
842
    return 0;
P
Paul Brook 已提交
843 844
}

845
static void virtio_balloon_exit_pci(PCIDevice *pci_dev)
846 847 848 849 850
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

    virtio_pci_stop_ioeventfd(proxy);
    virtio_balloon_exit(proxy->vdev);
851
    virtio_exit_pci(pci_dev);
852 853
}

854 855 856 857 858
static int virtio_rng_init_pci(PCIDevice *pci_dev)
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
    VirtIODevice *vdev;

859 860 861 862 863 864 865 866 867 868 869 870 871
    if (proxy->rng.rng == NULL) {
        proxy->rng.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));

        object_property_add_child(OBJECT(pci_dev),
                                  "default-backend",
                                  OBJECT(proxy->rng.default_backend),
                                  NULL);

        object_property_set_link(OBJECT(pci_dev),
                                 OBJECT(proxy->rng.default_backend),
                                 "rng", NULL);
    }

872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
    vdev = virtio_rng_init(&pci_dev->qdev, &proxy->rng);
    if (!vdev) {
        return -1;
    }
    virtio_init_pci(proxy, vdev);
    return 0;
}

static void virtio_rng_exit_pci(PCIDevice *pci_dev)
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

    virtio_pci_stop_ioeventfd(proxy);
    virtio_rng_exit(proxy->vdev);
    virtio_exit_pci(pci_dev);
}

889 890
static Property virtio_blk_properties[] = {
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
P
Paolo Bonzini 已提交
891
    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
892
    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOPCIProxy, blk.conf),
P
Paolo Bonzini 已提交
893
    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
894 895 896
#ifdef __linux__
    DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
#endif
897 898 899 900
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
    DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
    DEFINE_PROP_END_OF_LIST(),
901 902
};

903 904
static void virtio_blk_class_init(ObjectClass *klass, void *data)
{
905
    DeviceClass *dc = DEVICE_CLASS(klass);
906 907 908 909 910 911 912 913
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = virtio_blk_init_pci;
    k->exit = virtio_blk_exit_pci;
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
    k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
    k->revision = VIRTIO_PCI_ABI_VERSION;
    k->class_id = PCI_CLASS_STORAGE_SCSI;
914 915
    dc->reset = virtio_pci_reset;
    dc->props = virtio_blk_properties;
916 917
}

918 919 920 921 922
static TypeInfo virtio_blk_info = {
    .name          = "virtio-blk-pci",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(VirtIOPCIProxy),
    .class_init    = virtio_blk_class_init,
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
};

static Property virtio_net_properties[] = {
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
    DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
    DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
    DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy, net.txtimer, TX_TIMER_INTERVAL),
    DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy, net.txburst, TX_BURST),
    DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
    DEFINE_PROP_END_OF_LIST(),
};

static void virtio_net_class_init(ObjectClass *klass, void *data)
{
938
    DeviceClass *dc = DEVICE_CLASS(klass);
939 940 941 942 943 944 945 946 947
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = virtio_net_init_pci;
    k->exit = virtio_net_exit_pci;
    k->romfile = "pxe-virtio.rom";
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
    k->revision = VIRTIO_PCI_ABI_VERSION;
    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
948 949
    dc->reset = virtio_pci_reset;
    dc->props = virtio_net_properties;
950 951
}

952 953 954 955 956
static TypeInfo virtio_net_info = {
    .name          = "virtio-net-pci",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(VirtIOPCIProxy),
    .class_init    = virtio_net_class_init,
957 958
};

959 960 961 962 963 964 965
static Property virtio_serial_properties[] = {
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
    DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31),
    DEFINE_PROP_END_OF_LIST(),
966 967
};

968 969
static void virtio_serial_class_init(ObjectClass *klass, void *data)
{
970
    DeviceClass *dc = DEVICE_CLASS(klass);
971 972 973 974 975 976 977 978
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = virtio_serial_init_pci;
    k->exit = virtio_serial_exit_pci;
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
    k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
    k->revision = VIRTIO_PCI_ABI_VERSION;
    k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
979 980
    dc->reset = virtio_pci_reset;
    dc->props = virtio_serial_properties;
981 982
}

983 984 985 986 987
static TypeInfo virtio_serial_info = {
    .name          = "virtio-serial-pci",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(VirtIOPCIProxy),
    .class_init    = virtio_serial_class_init,
988 989 990 991
};

static Property virtio_balloon_properties[] = {
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
992
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
993 994 995 996 997
    DEFINE_PROP_END_OF_LIST(),
};

static void virtio_balloon_class_init(ObjectClass *klass, void *data)
{
998
    DeviceClass *dc = DEVICE_CLASS(klass);
999 1000 1001 1002 1003 1004 1005
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = virtio_balloon_init_pci;
    k->exit = virtio_balloon_exit_pci;
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
    k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
    k->revision = VIRTIO_PCI_ABI_VERSION;
1006
    k->class_id = PCI_CLASS_OTHERS;
1007 1008
    dc->reset = virtio_pci_reset;
    dc->props = virtio_balloon_properties;
1009 1010
}

1011 1012 1013 1014 1015
static TypeInfo virtio_balloon_info = {
    .name          = "virtio-balloon-pci",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(VirtIOPCIProxy),
    .class_init    = virtio_balloon_class_init,
1016 1017
};

1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
static void virtio_rng_initfn(Object *obj)
{
    PCIDevice *pci_dev = PCI_DEVICE(obj);
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
                             (Object **)&proxy->rng.rng, NULL);
}

static Property virtio_rng_properties[] = {
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
1029 1030 1031 1032 1033 1034 1035
    /* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s.  If
       you have an entropy source capable of generating more entropy than this
       and you can pass it through via virtio-rng, then hats off to you.  Until
       then, this is unlimited for all practical purposes.
    */
    DEFINE_PROP_UINT64("max-bytes", VirtIOPCIProxy, rng.max_bytes, INT64_MAX),
    DEFINE_PROP_UINT32("period", VirtIOPCIProxy, rng.period_ms, 1 << 16),
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
    DEFINE_PROP_END_OF_LIST(),
};

static void virtio_rng_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = virtio_rng_init_pci;
    k->exit = virtio_rng_exit_pci;
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
    k->device_id = PCI_DEVICE_ID_VIRTIO_RNG;
    k->revision = VIRTIO_PCI_ABI_VERSION;
    k->class_id = PCI_CLASS_OTHERS;
    dc->reset = virtio_pci_reset;
    dc->props = virtio_rng_properties;
}

static TypeInfo virtio_rng_info = {
    .name          = "virtio-rng-pci",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(VirtIOPCIProxy),
    .instance_init = virtio_rng_initfn,
    .class_init    = virtio_rng_class_init,
};

1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
static int virtio_scsi_init_pci(PCIDevice *pci_dev)
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
    VirtIODevice *vdev;

    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
    if (!vdev) {
        return -EINVAL;
    }

1072 1073 1074
    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
                                        ? proxy->scsi.num_queues + 3
                                        : proxy->nvectors;
1075 1076 1077 1078 1079 1080 1081
    virtio_init_pci(proxy, vdev);

    /* make the actual value visible */
    proxy->nvectors = vdev->nvectors;
    return 0;
}

1082
static void virtio_scsi_exit_pci(PCIDevice *pci_dev)
1083 1084 1085 1086
{
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);

    virtio_scsi_exit(proxy->vdev);
1087
    virtio_exit_pci(pci_dev);
1088 1089 1090
}

static Property virtio_scsi_properties[] = {
1091
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
1092
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
    DEFINE_PROP_END_OF_LIST(),
};

static void virtio_scsi_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = virtio_scsi_init_pci;
    k->exit = virtio_scsi_exit_pci;
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
    k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
    k->revision = 0x00;
    k->class_id = PCI_CLASS_STORAGE_SCSI;
    dc->reset = virtio_pci_reset;
    dc->props = virtio_scsi_properties;
}

static TypeInfo virtio_scsi_info = {
    .name          = "virtio-scsi-pci",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(VirtIOPCIProxy),
    .class_init    = virtio_scsi_class_init,
};

A
Andreas Färber 已提交
1119
static void virtio_pci_register_types(void)
P
Paul Brook 已提交
1120
{
1121 1122 1123 1124
    type_register_static(&virtio_blk_info);
    type_register_static(&virtio_net_info);
    type_register_static(&virtio_serial_info);
    type_register_static(&virtio_balloon_info);
1125
    type_register_static(&virtio_scsi_info);
1126
    type_register_static(&virtio_rng_info);
P
Paul Brook 已提交
1127 1128
}

A
Andreas Färber 已提交
1129
type_init(virtio_pci_register_types)