Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ 59369b08

History | View | Annotate | Download (29.2 kB)

1 53c25cea Paul Brook
/*
2 53c25cea Paul Brook
 * Virtio PCI Bindings
3 53c25cea Paul Brook
 *
4 53c25cea Paul Brook
 * Copyright IBM, Corp. 2007
5 53c25cea Paul Brook
 * Copyright (c) 2009 CodeSourcery
6 53c25cea Paul Brook
 *
7 53c25cea Paul Brook
 * Authors:
8 53c25cea Paul Brook
 *  Anthony Liguori   <aliguori@us.ibm.com>
9 53c25cea Paul Brook
 *  Paul Brook        <paul@codesourcery.com>
10 53c25cea Paul Brook
 *
11 53c25cea Paul Brook
 * This work is licensed under the terms of the GNU GPL, version 2.  See
12 53c25cea Paul Brook
 * the COPYING file in the top-level directory.
13 53c25cea Paul Brook
 *
14 53c25cea Paul Brook
 */
15 53c25cea Paul Brook
16 53c25cea Paul Brook
#include <inttypes.h>
17 53c25cea Paul Brook
18 53c25cea Paul Brook
#include "virtio.h"
19 8172539d Michael S. Tsirkin
#include "virtio-blk.h"
20 8172539d Michael S. Tsirkin
#include "virtio-net.h"
21 53c25cea Paul Brook
#include "pci.h"
22 2f792016 Markus Armbruster
#include "qemu-error.h"
23 aba800a3 Michael S. Tsirkin
#include "msix.h"
24 a1e0fea5 Gerd Hoffmann
#include "net.h"
25 97b15621 Gerd Hoffmann
#include "loader.h"
26 ade80dc8 Michael S. Tsirkin
#include "kvm.h"
27 2446333c Blue Swirl
#include "blockdev.h"
28 53c25cea Paul Brook
29 53c25cea Paul Brook
/* from Linux's linux/virtio_pci.h */
30 53c25cea Paul Brook
31 53c25cea Paul Brook
/* A 32-bit r/o bitmask of the features supported by the host */
32 53c25cea Paul Brook
#define VIRTIO_PCI_HOST_FEATURES        0
33 53c25cea Paul Brook
34 53c25cea Paul Brook
/* A 32-bit r/w bitmask of features activated by the guest */
35 53c25cea Paul Brook
#define VIRTIO_PCI_GUEST_FEATURES       4
36 53c25cea Paul Brook
37 53c25cea Paul Brook
/* A 32-bit r/w PFN for the currently selected queue */
38 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_PFN            8
39 53c25cea Paul Brook
40 53c25cea Paul Brook
/* A 16-bit r/o queue size for the currently selected queue */
41 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NUM            12
42 53c25cea Paul Brook
43 53c25cea Paul Brook
/* A 16-bit r/w queue selector */
44 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_SEL            14
45 53c25cea Paul Brook
46 53c25cea Paul Brook
/* A 16-bit r/w queue notifier */
47 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NOTIFY         16
48 53c25cea Paul Brook
49 53c25cea Paul Brook
/* An 8-bit device status register.  */
50 53c25cea Paul Brook
#define VIRTIO_PCI_STATUS               18
51 53c25cea Paul Brook
52 53c25cea Paul Brook
/* An 8-bit r/o interrupt status register.  Reading the value will return the
53 53c25cea Paul Brook
 * current contents of the ISR and will also clear it.  This is effectively
54 53c25cea Paul Brook
 * a read-and-acknowledge. */
55 53c25cea Paul Brook
#define VIRTIO_PCI_ISR                  19
56 53c25cea Paul Brook
57 aba800a3 Michael S. Tsirkin
/* MSI-X registers: only enabled if MSI-X is enabled. */
58 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for configuration changes. */
59 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_CONFIG_VECTOR        20
60 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for selected queue notifications. */
61 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_QUEUE_VECTOR         22
62 aba800a3 Michael S. Tsirkin
63 aba800a3 Michael S. Tsirkin
/* Config space size */
64 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_NOMSI         20
65 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_MSI           24
66 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
67 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
68 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
69 aba800a3 Michael S. Tsirkin
70 aba800a3 Michael S. Tsirkin
/* The remaining space is defined by each driver as the per-driver
71 aba800a3 Michael S. Tsirkin
 * configuration space */
72 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
73 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
74 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
75 53c25cea Paul Brook
76 53c25cea Paul Brook
/* Virtio ABI version, if we increment this, we break the guest driver. */
77 53c25cea Paul Brook
#define VIRTIO_PCI_ABI_VERSION          0
78 53c25cea Paul Brook
79 53c25cea Paul Brook
/* How many bits to shift physical queue address written to QUEUE_PFN.
80 53c25cea Paul Brook
 * 12 is historical, and due to x86 page size. */
81 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
82 53c25cea Paul Brook
83 3dbca8e6 Stefan Hajnoczi
/* Flags track per-device state like workarounds for quirks in older guests. */
84 3dbca8e6 Stefan Hajnoczi
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG  (1 << 0)
85 c81131db Alexander Graf
86 25db9ebe Stefan Hajnoczi
/* Performance improves when virtqueue kick processing is decoupled from the
87 25db9ebe Stefan Hajnoczi
 * vcpu thread using ioeventfd for some devices. */
88 25db9ebe Stefan Hajnoczi
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1
89 25db9ebe Stefan Hajnoczi
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD   (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
90 25db9ebe Stefan Hajnoczi
91 53c25cea Paul Brook
/* QEMU doesn't strictly need write barriers since everything runs in
92 53c25cea Paul Brook
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
93 53c25cea Paul Brook
 * KVM or if kqemu gets SMP support.
94 53c25cea Paul Brook
 */
95 53c25cea Paul Brook
#define wmb() do { } while (0)
96 53c25cea Paul Brook
97 53c25cea Paul Brook
/* PCI bindings.  */
98 53c25cea Paul Brook
99 53c25cea Paul Brook
typedef struct {
100 53c25cea Paul Brook
    PCIDevice pci_dev;
101 53c25cea Paul Brook
    VirtIODevice *vdev;
102 3dbca8e6 Stefan Hajnoczi
    uint32_t flags;
103 53c25cea Paul Brook
    uint32_t addr;
104 ab73ff29 Gerd Hoffmann
    uint32_t class_code;
105 a1e0fea5 Gerd Hoffmann
    uint32_t nvectors;
106 428c149b Christoph Hellwig
    BlockConf block;
107 97b15621 Gerd Hoffmann
    NICConf nic;
108 8172539d Michael S. Tsirkin
    uint32_t host_features;
109 9f107513 Anthony Liguori
#ifdef CONFIG_LINUX
110 9f107513 Anthony Liguori
    V9fsConf fsconf;
111 9f107513 Anthony Liguori
#endif
112 98b19252 Amit Shah
    /* Max. number of ports we can have for a the virtio-serial device */
113 98b19252 Amit Shah
    uint32_t max_virtserial_ports;
114 f0c07c7c Alex Williamson
    virtio_net_conf net;
115 25db9ebe Stefan Hajnoczi
    bool ioeventfd_disabled;
116 25db9ebe Stefan Hajnoczi
    bool ioeventfd_started;
117 53c25cea Paul Brook
} VirtIOPCIProxy;
118 53c25cea Paul Brook
119 53c25cea Paul Brook
/* virtio device */
120 53c25cea Paul Brook
121 7055e687 Michael S. Tsirkin
static void virtio_pci_notify(void *opaque, uint16_t vector)
122 53c25cea Paul Brook
{
123 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
124 aba800a3 Michael S. Tsirkin
    if (msix_enabled(&proxy->pci_dev))
125 aba800a3 Michael S. Tsirkin
        msix_notify(&proxy->pci_dev, vector);
126 aba800a3 Michael S. Tsirkin
    else
127 aba800a3 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
128 53c25cea Paul Brook
}
129 53c25cea Paul Brook
130 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_config(void * opaque, QEMUFile *f)
131 ff24bd58 Michael S. Tsirkin
{
132 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
133 ff24bd58 Michael S. Tsirkin
    pci_device_save(&proxy->pci_dev, f);
134 ff24bd58 Michael S. Tsirkin
    msix_save(&proxy->pci_dev, f);
135 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
136 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, proxy->vdev->config_vector);
137 ff24bd58 Michael S. Tsirkin
}
138 ff24bd58 Michael S. Tsirkin
139 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
140 ff24bd58 Michael S. Tsirkin
{
141 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
142 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
143 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
144 ff24bd58 Michael S. Tsirkin
}
145 ff24bd58 Michael S. Tsirkin
146 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_config(void * opaque, QEMUFile *f)
147 ff24bd58 Michael S. Tsirkin
{
148 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
149 ff24bd58 Michael S. Tsirkin
    int ret;
150 ff24bd58 Michael S. Tsirkin
    ret = pci_device_load(&proxy->pci_dev, f);
151 e6da7680 Michael S. Tsirkin
    if (ret) {
152 ff24bd58 Michael S. Tsirkin
        return ret;
153 e6da7680 Michael S. Tsirkin
    }
154 ff24bd58 Michael S. Tsirkin
    msix_load(&proxy->pci_dev, f);
155 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
156 ff24bd58 Michael S. Tsirkin
        qemu_get_be16s(f, &proxy->vdev->config_vector);
157 e6da7680 Michael S. Tsirkin
    } else {
158 e6da7680 Michael S. Tsirkin
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
159 e6da7680 Michael S. Tsirkin
    }
160 e6da7680 Michael S. Tsirkin
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
161 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
162 e6da7680 Michael S. Tsirkin
    }
163 c81131db Alexander Graf
164 c81131db Alexander Graf
    /* Try to find out if the guest has bus master disabled, but is
165 c81131db Alexander Graf
       in ready state. Then we have a buggy guest OS. */
166 8a911107 Alex Williamson
    if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
167 c81131db Alexander Graf
        !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
168 3dbca8e6 Stefan Hajnoczi
        proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
169 c81131db Alexander Graf
    }
170 ff24bd58 Michael S. Tsirkin
    return 0;
171 ff24bd58 Michael S. Tsirkin
}
172 ff24bd58 Michael S. Tsirkin
173 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
174 ff24bd58 Michael S. Tsirkin
{
175 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
176 ff24bd58 Michael S. Tsirkin
    uint16_t vector;
177 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
178 e6da7680 Michael S. Tsirkin
        qemu_get_be16s(f, &vector);
179 e6da7680 Michael S. Tsirkin
    } else {
180 e6da7680 Michael S. Tsirkin
        vector = VIRTIO_NO_VECTOR;
181 e6da7680 Michael S. Tsirkin
    }
182 ff24bd58 Michael S. Tsirkin
    virtio_queue_set_vector(proxy->vdev, n, vector);
183 e6da7680 Michael S. Tsirkin
    if (vector != VIRTIO_NO_VECTOR) {
184 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, vector);
185 e6da7680 Michael S. Tsirkin
    }
186 ff24bd58 Michael S. Tsirkin
    return 0;
187 ff24bd58 Michael S. Tsirkin
}
188 ff24bd58 Michael S. Tsirkin
189 25db9ebe Stefan Hajnoczi
static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
190 25db9ebe Stefan Hajnoczi
                                                 int n, bool assign)
191 25db9ebe Stefan Hajnoczi
{
192 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
193 25db9ebe Stefan Hajnoczi
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
194 25db9ebe Stefan Hajnoczi
    int r;
195 25db9ebe Stefan Hajnoczi
    if (assign) {
196 25db9ebe Stefan Hajnoczi
        r = event_notifier_init(notifier, 1);
197 25db9ebe Stefan Hajnoczi
        if (r < 0) {
198 b36e3914 Michael S. Tsirkin
            error_report("%s: unable to init event notifier: %d",
199 b36e3914 Michael S. Tsirkin
                         __func__, r);
200 25db9ebe Stefan Hajnoczi
            return r;
201 25db9ebe Stefan Hajnoczi
        }
202 25db9ebe Stefan Hajnoczi
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
203 25db9ebe Stefan Hajnoczi
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
204 25db9ebe Stefan Hajnoczi
                                       n, assign);
205 25db9ebe Stefan Hajnoczi
        if (r < 0) {
206 b36e3914 Michael S. Tsirkin
            error_report("%s: unable to map ioeventfd: %d",
207 b36e3914 Michael S. Tsirkin
                         __func__, r);
208 25db9ebe Stefan Hajnoczi
            event_notifier_cleanup(notifier);
209 25db9ebe Stefan Hajnoczi
        }
210 25db9ebe Stefan Hajnoczi
    } else {
211 25db9ebe Stefan Hajnoczi
        r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
212 25db9ebe Stefan Hajnoczi
                                       proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
213 25db9ebe Stefan Hajnoczi
                                       n, assign);
214 25db9ebe Stefan Hajnoczi
        if (r < 0) {
215 b36e3914 Michael S. Tsirkin
            error_report("%s: unable to unmap ioeventfd: %d",
216 b36e3914 Michael S. Tsirkin
                         __func__, r);
217 25db9ebe Stefan Hajnoczi
            return r;
218 25db9ebe Stefan Hajnoczi
        }
219 25db9ebe Stefan Hajnoczi
220 25db9ebe Stefan Hajnoczi
        /* Handle the race condition where the guest kicked and we deassigned
221 25db9ebe Stefan Hajnoczi
         * before we got around to handling the kick.
222 25db9ebe Stefan Hajnoczi
         */
223 25db9ebe Stefan Hajnoczi
        if (event_notifier_test_and_clear(notifier)) {
224 25db9ebe Stefan Hajnoczi
            virtio_queue_notify_vq(vq);
225 25db9ebe Stefan Hajnoczi
        }
226 25db9ebe Stefan Hajnoczi
227 25db9ebe Stefan Hajnoczi
        event_notifier_cleanup(notifier);
228 25db9ebe Stefan Hajnoczi
    }
229 25db9ebe Stefan Hajnoczi
    return r;
230 25db9ebe Stefan Hajnoczi
}
231 25db9ebe Stefan Hajnoczi
232 25db9ebe Stefan Hajnoczi
static void virtio_pci_host_notifier_read(void *opaque)
233 25db9ebe Stefan Hajnoczi
{
234 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = opaque;
235 25db9ebe Stefan Hajnoczi
    EventNotifier *n = virtio_queue_get_host_notifier(vq);
236 25db9ebe Stefan Hajnoczi
    if (event_notifier_test_and_clear(n)) {
237 25db9ebe Stefan Hajnoczi
        virtio_queue_notify_vq(vq);
238 25db9ebe Stefan Hajnoczi
    }
239 25db9ebe Stefan Hajnoczi
}
240 25db9ebe Stefan Hajnoczi
241 25db9ebe Stefan Hajnoczi
static void virtio_pci_set_host_notifier_fd_handler(VirtIOPCIProxy *proxy,
242 25db9ebe Stefan Hajnoczi
                                                    int n, bool assign)
243 25db9ebe Stefan Hajnoczi
{
244 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
245 25db9ebe Stefan Hajnoczi
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
246 25db9ebe Stefan Hajnoczi
    if (assign) {
247 25db9ebe Stefan Hajnoczi
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
248 25db9ebe Stefan Hajnoczi
                            virtio_pci_host_notifier_read, NULL, vq);
249 25db9ebe Stefan Hajnoczi
    } else {
250 25db9ebe Stefan Hajnoczi
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
251 25db9ebe Stefan Hajnoczi
                            NULL, NULL, NULL);
252 25db9ebe Stefan Hajnoczi
    }
253 25db9ebe Stefan Hajnoczi
}
254 25db9ebe Stefan Hajnoczi
255 b36e3914 Michael S. Tsirkin
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
256 25db9ebe Stefan Hajnoczi
{
257 25db9ebe Stefan Hajnoczi
    int n, r;
258 25db9ebe Stefan Hajnoczi
259 25db9ebe Stefan Hajnoczi
    if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
260 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_disabled ||
261 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_started) {
262 b36e3914 Michael S. Tsirkin
        return;
263 25db9ebe Stefan Hajnoczi
    }
264 25db9ebe Stefan Hajnoczi
265 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
266 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
267 25db9ebe Stefan Hajnoczi
            continue;
268 25db9ebe Stefan Hajnoczi
        }
269 25db9ebe Stefan Hajnoczi
270 25db9ebe Stefan Hajnoczi
        r = virtio_pci_set_host_notifier_internal(proxy, n, true);
271 25db9ebe Stefan Hajnoczi
        if (r < 0) {
272 25db9ebe Stefan Hajnoczi
            goto assign_error;
273 25db9ebe Stefan Hajnoczi
        }
274 25db9ebe Stefan Hajnoczi
275 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, true);
276 25db9ebe Stefan Hajnoczi
    }
277 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = true;
278 b36e3914 Michael S. Tsirkin
    return;
279 25db9ebe Stefan Hajnoczi
280 25db9ebe Stefan Hajnoczi
assign_error:
281 25db9ebe Stefan Hajnoczi
    while (--n >= 0) {
282 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
283 25db9ebe Stefan Hajnoczi
            continue;
284 25db9ebe Stefan Hajnoczi
        }
285 25db9ebe Stefan Hajnoczi
286 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
287 b36e3914 Michael S. Tsirkin
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
288 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
289 25db9ebe Stefan Hajnoczi
    }
290 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
291 b36e3914 Michael S. Tsirkin
    error_report("%s: failed. Fallback to a userspace (slower).", __func__);
292 25db9ebe Stefan Hajnoczi
}
293 25db9ebe Stefan Hajnoczi
294 b36e3914 Michael S. Tsirkin
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
295 25db9ebe Stefan Hajnoczi
{
296 b36e3914 Michael S. Tsirkin
    int r;
297 25db9ebe Stefan Hajnoczi
    int n;
298 25db9ebe Stefan Hajnoczi
299 25db9ebe Stefan Hajnoczi
    if (!proxy->ioeventfd_started) {
300 b36e3914 Michael S. Tsirkin
        return;
301 25db9ebe Stefan Hajnoczi
    }
302 25db9ebe Stefan Hajnoczi
303 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
304 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
305 25db9ebe Stefan Hajnoczi
            continue;
306 25db9ebe Stefan Hajnoczi
        }
307 25db9ebe Stefan Hajnoczi
308 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
309 b36e3914 Michael S. Tsirkin
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
310 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
311 25db9ebe Stefan Hajnoczi
    }
312 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
313 25db9ebe Stefan Hajnoczi
}
314 25db9ebe Stefan Hajnoczi
315 e489030d Michael S. Tsirkin
static void virtio_pci_reset(DeviceState *d)
316 7055e687 Michael S. Tsirkin
{
317 e489030d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
318 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
319 7055e687 Michael S. Tsirkin
    virtio_reset(proxy->vdev);
320 aba800a3 Michael S. Tsirkin
    msix_reset(&proxy->pci_dev);
321 25db9ebe Stefan Hajnoczi
    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
322 7055e687 Michael S. Tsirkin
}
323 7055e687 Michael S. Tsirkin
324 53c25cea Paul Brook
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
325 53c25cea Paul Brook
{
326 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
327 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
328 c227f099 Anthony Liguori
    target_phys_addr_t pa;
329 53c25cea Paul Brook
330 53c25cea Paul Brook
    switch (addr) {
331 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
332 53c25cea Paul Brook
        /* Guest does not negotiate properly?  We have to assume nothing. */
333 53c25cea Paul Brook
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
334 53c25cea Paul Brook
            if (vdev->bad_features)
335 8172539d Michael S. Tsirkin
                val = proxy->host_features & vdev->bad_features(vdev);
336 53c25cea Paul Brook
            else
337 53c25cea Paul Brook
                val = 0;
338 53c25cea Paul Brook
        }
339 53c25cea Paul Brook
        if (vdev->set_features)
340 53c25cea Paul Brook
            vdev->set_features(vdev, val);
341 704a76fc Michael S. Tsirkin
        vdev->guest_features = val;
342 53c25cea Paul Brook
        break;
343 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
344 c227f099 Anthony Liguori
        pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
345 1b8e9b27 Michael S. Tsirkin
        if (pa == 0) {
346 25db9ebe Stefan Hajnoczi
            virtio_pci_stop_ioeventfd(proxy);
347 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
348 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
349 1b8e9b27 Michael S. Tsirkin
        }
350 7055e687 Michael S. Tsirkin
        else
351 7055e687 Michael S. Tsirkin
            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
352 53c25cea Paul Brook
        break;
353 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
354 53c25cea Paul Brook
        if (val < VIRTIO_PCI_QUEUE_MAX)
355 53c25cea Paul Brook
            vdev->queue_sel = val;
356 53c25cea Paul Brook
        break;
357 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NOTIFY:
358 53c25cea Paul Brook
        virtio_queue_notify(vdev, val);
359 53c25cea Paul Brook
        break;
360 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
361 25db9ebe Stefan Hajnoczi
        if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
362 25db9ebe Stefan Hajnoczi
            virtio_pci_stop_ioeventfd(proxy);
363 25db9ebe Stefan Hajnoczi
        }
364 25db9ebe Stefan Hajnoczi
365 3e607cb5 Michael S. Tsirkin
        virtio_set_status(vdev, val & 0xFF);
366 25db9ebe Stefan Hajnoczi
367 25db9ebe Stefan Hajnoczi
        if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
368 25db9ebe Stefan Hajnoczi
            virtio_pci_start_ioeventfd(proxy);
369 25db9ebe Stefan Hajnoczi
        }
370 25db9ebe Stefan Hajnoczi
371 1b8e9b27 Michael S. Tsirkin
        if (vdev->status == 0) {
372 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
373 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
374 1b8e9b27 Michael S. Tsirkin
        }
375 c81131db Alexander Graf
376 c81131db Alexander Graf
        /* Linux before 2.6.34 sets the device as OK without enabling
377 c81131db Alexander Graf
           the PCI device bus master bit. In this case we need to disable
378 c81131db Alexander Graf
           some safety checks. */
379 c81131db Alexander Graf
        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
380 c81131db Alexander Graf
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
381 3dbca8e6 Stefan Hajnoczi
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
382 c81131db Alexander Graf
        }
383 53c25cea Paul Brook
        break;
384 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
385 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
386 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
387 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
388 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
389 aba800a3 Michael S. Tsirkin
        vdev->config_vector = val;
390 aba800a3 Michael S. Tsirkin
        break;
391 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
392 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev,
393 aba800a3 Michael S. Tsirkin
                          virtio_queue_vector(vdev, vdev->queue_sel));
394 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
395 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
396 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
397 aba800a3 Michael S. Tsirkin
        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
398 aba800a3 Michael S. Tsirkin
        break;
399 aba800a3 Michael S. Tsirkin
    default:
400 4e02d460 Stefan Hajnoczi
        error_report("%s: unexpected address 0x%x value 0x%x",
401 4e02d460 Stefan Hajnoczi
                     __func__, addr, val);
402 aba800a3 Michael S. Tsirkin
        break;
403 53c25cea Paul Brook
    }
404 53c25cea Paul Brook
}
405 53c25cea Paul Brook
406 aba800a3 Michael S. Tsirkin
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
407 53c25cea Paul Brook
{
408 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
409 53c25cea Paul Brook
    uint32_t ret = 0xFFFFFFFF;
410 53c25cea Paul Brook
411 53c25cea Paul Brook
    switch (addr) {
412 53c25cea Paul Brook
    case VIRTIO_PCI_HOST_FEATURES:
413 8172539d Michael S. Tsirkin
        ret = proxy->host_features;
414 53c25cea Paul Brook
        break;
415 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
416 704a76fc Michael S. Tsirkin
        ret = vdev->guest_features;
417 53c25cea Paul Brook
        break;
418 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
419 53c25cea Paul Brook
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
420 53c25cea Paul Brook
              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
421 53c25cea Paul Brook
        break;
422 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NUM:
423 53c25cea Paul Brook
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
424 53c25cea Paul Brook
        break;
425 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
426 53c25cea Paul Brook
        ret = vdev->queue_sel;
427 53c25cea Paul Brook
        break;
428 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
429 53c25cea Paul Brook
        ret = vdev->status;
430 53c25cea Paul Brook
        break;
431 53c25cea Paul Brook
    case VIRTIO_PCI_ISR:
432 53c25cea Paul Brook
        /* reading from the ISR also clears it. */
433 53c25cea Paul Brook
        ret = vdev->isr;
434 53c25cea Paul Brook
        vdev->isr = 0;
435 7055e687 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], 0);
436 53c25cea Paul Brook
        break;
437 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
438 aba800a3 Michael S. Tsirkin
        ret = vdev->config_vector;
439 aba800a3 Michael S. Tsirkin
        break;
440 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
441 aba800a3 Michael S. Tsirkin
        ret = virtio_queue_vector(vdev, vdev->queue_sel);
442 aba800a3 Michael S. Tsirkin
        break;
443 53c25cea Paul Brook
    default:
444 53c25cea Paul Brook
        break;
445 53c25cea Paul Brook
    }
446 53c25cea Paul Brook
447 53c25cea Paul Brook
    return ret;
448 53c25cea Paul Brook
}
449 53c25cea Paul Brook
450 53c25cea Paul Brook
static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
451 53c25cea Paul Brook
{
452 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
453 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
454 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
455 aba800a3 Michael S. Tsirkin
    if (addr < config)
456 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
457 aba800a3 Michael S. Tsirkin
    addr -= config;
458 53c25cea Paul Brook
    return virtio_config_readb(proxy->vdev, addr);
459 53c25cea Paul Brook
}
460 53c25cea Paul Brook
461 53c25cea Paul Brook
static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
462 53c25cea Paul Brook
{
463 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
464 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
465 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
466 aba800a3 Michael S. Tsirkin
    if (addr < config)
467 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
468 aba800a3 Michael S. Tsirkin
    addr -= config;
469 53c25cea Paul Brook
    return virtio_config_readw(proxy->vdev, addr);
470 53c25cea Paul Brook
}
471 53c25cea Paul Brook
472 53c25cea Paul Brook
static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
473 53c25cea Paul Brook
{
474 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
475 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
476 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
477 aba800a3 Michael S. Tsirkin
    if (addr < config)
478 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
479 aba800a3 Michael S. Tsirkin
    addr -= config;
480 53c25cea Paul Brook
    return virtio_config_readl(proxy->vdev, addr);
481 53c25cea Paul Brook
}
482 53c25cea Paul Brook
483 53c25cea Paul Brook
static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
484 53c25cea Paul Brook
{
485 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
486 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
487 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
488 aba800a3 Michael S. Tsirkin
    if (addr < config) {
489 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
490 aba800a3 Michael S. Tsirkin
        return;
491 aba800a3 Michael S. Tsirkin
    }
492 aba800a3 Michael S. Tsirkin
    addr -= config;
493 53c25cea Paul Brook
    virtio_config_writeb(proxy->vdev, addr, val);
494 53c25cea Paul Brook
}
495 53c25cea Paul Brook
496 53c25cea Paul Brook
static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
497 53c25cea Paul Brook
{
498 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
499 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
500 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
501 aba800a3 Michael S. Tsirkin
    if (addr < config) {
502 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
503 aba800a3 Michael S. Tsirkin
        return;
504 aba800a3 Michael S. Tsirkin
    }
505 aba800a3 Michael S. Tsirkin
    addr -= config;
506 53c25cea Paul Brook
    virtio_config_writew(proxy->vdev, addr, val);
507 53c25cea Paul Brook
}
508 53c25cea Paul Brook
509 53c25cea Paul Brook
static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
510 53c25cea Paul Brook
{
511 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
512 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
513 aba800a3 Michael S. Tsirkin
    addr -= proxy->addr;
514 aba800a3 Michael S. Tsirkin
    if (addr < config) {
515 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
516 aba800a3 Michael S. Tsirkin
        return;
517 aba800a3 Michael S. Tsirkin
    }
518 aba800a3 Michael S. Tsirkin
    addr -= config;
519 53c25cea Paul Brook
    virtio_config_writel(proxy->vdev, addr, val);
520 53c25cea Paul Brook
}
521 53c25cea Paul Brook
522 53c25cea Paul Brook
static void virtio_map(PCIDevice *pci_dev, int region_num,
523 6e355d90 Isaku Yamahata
                       pcibus_t addr, pcibus_t size, int type)
524 53c25cea Paul Brook
{
525 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = container_of(pci_dev, VirtIOPCIProxy, pci_dev);
526 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
527 aba800a3 Michael S. Tsirkin
    unsigned config_len = VIRTIO_PCI_REGION_SIZE(pci_dev) + vdev->config_len;
528 53c25cea Paul Brook
529 53c25cea Paul Brook
    proxy->addr = addr;
530 53c25cea Paul Brook
531 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 1, virtio_pci_config_writeb, proxy);
532 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 2, virtio_pci_config_writew, proxy);
533 aba800a3 Michael S. Tsirkin
    register_ioport_write(addr, config_len, 4, virtio_pci_config_writel, proxy);
534 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 1, virtio_pci_config_readb, proxy);
535 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 2, virtio_pci_config_readw, proxy);
536 aba800a3 Michael S. Tsirkin
    register_ioport_read(addr, config_len, 4, virtio_pci_config_readl, proxy);
537 53c25cea Paul Brook
538 aba800a3 Michael S. Tsirkin
    if (vdev->config_len)
539 53c25cea Paul Brook
        vdev->get_config(vdev, vdev->config);
540 aba800a3 Michael S. Tsirkin
}
541 aba800a3 Michael S. Tsirkin
542 aba800a3 Michael S. Tsirkin
static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
543 aba800a3 Michael S. Tsirkin
                                uint32_t val, int len)
544 aba800a3 Michael S. Tsirkin
{
545 ed757e14 Yan Vugenfirer
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
546 ed757e14 Yan Vugenfirer
547 ed757e14 Yan Vugenfirer
    if (PCI_COMMAND == address) {
548 ed757e14 Yan Vugenfirer
        if (!(val & PCI_COMMAND_MASTER)) {
549 3dbca8e6 Stefan Hajnoczi
            if (!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
550 25db9ebe Stefan Hajnoczi
                virtio_pci_stop_ioeventfd(proxy);
551 3e607cb5 Michael S. Tsirkin
                virtio_set_status(proxy->vdev,
552 3e607cb5 Michael S. Tsirkin
                                  proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
553 c81131db Alexander Graf
            }
554 ed757e14 Yan Vugenfirer
        }
555 ed757e14 Yan Vugenfirer
    }
556 ed757e14 Yan Vugenfirer
557 aba800a3 Michael S. Tsirkin
    pci_default_write_config(pci_dev, address, val, len);
558 85352471 Michael S. Tsirkin
    msix_write_config(pci_dev, address, val, len);
559 53c25cea Paul Brook
}
560 53c25cea Paul Brook
561 6d74ca5a Michael S. Tsirkin
static unsigned virtio_pci_get_features(void *opaque)
562 6d74ca5a Michael S. Tsirkin
{
563 8172539d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
564 8172539d Michael S. Tsirkin
    return proxy->host_features;
565 6d74ca5a Michael S. Tsirkin
}
566 6d74ca5a Michael S. Tsirkin
567 ade80dc8 Michael S. Tsirkin
static void virtio_pci_guest_notifier_read(void *opaque)
568 ade80dc8 Michael S. Tsirkin
{
569 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = opaque;
570 ade80dc8 Michael S. Tsirkin
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
571 ade80dc8 Michael S. Tsirkin
    if (event_notifier_test_and_clear(n)) {
572 ade80dc8 Michael S. Tsirkin
        virtio_irq(vq);
573 ade80dc8 Michael S. Tsirkin
    }
574 ade80dc8 Michael S. Tsirkin
}
575 ade80dc8 Michael S. Tsirkin
576 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
577 ade80dc8 Michael S. Tsirkin
{
578 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
579 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
580 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
581 ade80dc8 Michael S. Tsirkin
582 ade80dc8 Michael S. Tsirkin
    if (assign) {
583 ade80dc8 Michael S. Tsirkin
        int r = event_notifier_init(notifier, 0);
584 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
585 ade80dc8 Michael S. Tsirkin
            return r;
586 ade80dc8 Michael S. Tsirkin
        }
587 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
588 ade80dc8 Michael S. Tsirkin
                            virtio_pci_guest_notifier_read, NULL, vq);
589 ade80dc8 Michael S. Tsirkin
    } else {
590 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
591 ade80dc8 Michael S. Tsirkin
                            NULL, NULL, NULL);
592 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
593 ade80dc8 Michael S. Tsirkin
    }
594 ade80dc8 Michael S. Tsirkin
595 ade80dc8 Michael S. Tsirkin
    return 0;
596 ade80dc8 Michael S. Tsirkin
}
597 ade80dc8 Michael S. Tsirkin
598 54dd9321 Michael S. Tsirkin
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
599 54dd9321 Michael S. Tsirkin
{
600 54dd9321 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
601 54dd9321 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
602 54dd9321 Michael S. Tsirkin
    int r, n;
603 54dd9321 Michael S. Tsirkin
604 54dd9321 Michael S. Tsirkin
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
605 54dd9321 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, n)) {
606 54dd9321 Michael S. Tsirkin
            break;
607 54dd9321 Michael S. Tsirkin
        }
608 54dd9321 Michael S. Tsirkin
609 54dd9321 Michael S. Tsirkin
        r = virtio_pci_set_guest_notifier(opaque, n, assign);
610 54dd9321 Michael S. Tsirkin
        if (r < 0) {
611 54dd9321 Michael S. Tsirkin
            goto assign_error;
612 54dd9321 Michael S. Tsirkin
        }
613 54dd9321 Michael S. Tsirkin
    }
614 54dd9321 Michael S. Tsirkin
615 54dd9321 Michael S. Tsirkin
    return 0;
616 54dd9321 Michael S. Tsirkin
617 54dd9321 Michael S. Tsirkin
assign_error:
618 54dd9321 Michael S. Tsirkin
    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
619 54dd9321 Michael S. Tsirkin
    while (--n >= 0) {
620 54dd9321 Michael S. Tsirkin
        virtio_pci_set_guest_notifier(opaque, n, !assign);
621 54dd9321 Michael S. Tsirkin
    }
622 54dd9321 Michael S. Tsirkin
    return r;
623 54dd9321 Michael S. Tsirkin
}
624 54dd9321 Michael S. Tsirkin
625 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
626 ade80dc8 Michael S. Tsirkin
{
627 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
628 25db9ebe Stefan Hajnoczi
629 25db9ebe Stefan Hajnoczi
    /* Stop using ioeventfd for virtqueue kick if the device starts using host
630 25db9ebe Stefan Hajnoczi
     * notifiers.  This makes it easy to avoid stepping on each others' toes.
631 25db9ebe Stefan Hajnoczi
     */
632 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_disabled = assign;
633 ade80dc8 Michael S. Tsirkin
    if (assign) {
634 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
635 25db9ebe Stefan Hajnoczi
    }
636 25db9ebe Stefan Hajnoczi
    /* We don't need to start here: it's not needed because backend
637 25db9ebe Stefan Hajnoczi
     * currently only stops on status change away from ok,
638 25db9ebe Stefan Hajnoczi
     * reset, vmstop and such. If we do add code to start here,
639 25db9ebe Stefan Hajnoczi
     * need to check vmstate, device state etc. */
640 25db9ebe Stefan Hajnoczi
    return virtio_pci_set_host_notifier_internal(proxy, n, assign);
641 25db9ebe Stefan Hajnoczi
}
642 25db9ebe Stefan Hajnoczi
643 25db9ebe Stefan Hajnoczi
static void virtio_pci_vmstate_change(void *opaque, bool running)
644 25db9ebe Stefan Hajnoczi
{
645 25db9ebe Stefan Hajnoczi
    VirtIOPCIProxy *proxy = opaque;
646 25db9ebe Stefan Hajnoczi
647 25db9ebe Stefan Hajnoczi
    if (running) {
648 25db9ebe Stefan Hajnoczi
        virtio_pci_start_ioeventfd(proxy);
649 ade80dc8 Michael S. Tsirkin
    } else {
650 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
651 ade80dc8 Michael S. Tsirkin
    }
652 ade80dc8 Michael S. Tsirkin
}
653 ade80dc8 Michael S. Tsirkin
654 53c25cea Paul Brook
static const VirtIOBindings virtio_pci_bindings = {
655 ff24bd58 Michael S. Tsirkin
    .notify = virtio_pci_notify,
656 ff24bd58 Michael S. Tsirkin
    .save_config = virtio_pci_save_config,
657 ff24bd58 Michael S. Tsirkin
    .load_config = virtio_pci_load_config,
658 ff24bd58 Michael S. Tsirkin
    .save_queue = virtio_pci_save_queue,
659 ff24bd58 Michael S. Tsirkin
    .load_queue = virtio_pci_load_queue,
660 6d74ca5a Michael S. Tsirkin
    .get_features = virtio_pci_get_features,
661 ade80dc8 Michael S. Tsirkin
    .set_host_notifier = virtio_pci_set_host_notifier,
662 54dd9321 Michael S. Tsirkin
    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
663 25db9ebe Stefan Hajnoczi
    .vmstate_change = virtio_pci_vmstate_change,
664 53c25cea Paul Brook
};
665 53c25cea Paul Brook
666 53c25cea Paul Brook
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
667 53c25cea Paul Brook
                            uint16_t vendor, uint16_t device,
668 53c25cea Paul Brook
                            uint16_t class_code, uint8_t pif)
669 53c25cea Paul Brook
{
670 53c25cea Paul Brook
    uint8_t *config;
671 53c25cea Paul Brook
    uint32_t size;
672 53c25cea Paul Brook
673 53c25cea Paul Brook
    proxy->vdev = vdev;
674 53c25cea Paul Brook
675 53c25cea Paul Brook
    config = proxy->pci_dev.config;
676 53c25cea Paul Brook
    pci_config_set_vendor_id(config, vendor);
677 53c25cea Paul Brook
    pci_config_set_device_id(config, device);
678 53c25cea Paul Brook
679 53c25cea Paul Brook
    config[0x08] = VIRTIO_PCI_ABI_VERSION;
680 53c25cea Paul Brook
681 53c25cea Paul Brook
    config[0x09] = pif;
682 53c25cea Paul Brook
    pci_config_set_class(config, class_code);
683 53c25cea Paul Brook
684 53c25cea Paul Brook
    config[0x2c] = vendor & 0xFF;
685 53c25cea Paul Brook
    config[0x2d] = (vendor >> 8) & 0xFF;
686 53c25cea Paul Brook
    config[0x2e] = vdev->device_id & 0xFF;
687 53c25cea Paul Brook
    config[0x2f] = (vdev->device_id >> 8) & 0xFF;
688 53c25cea Paul Brook
689 53c25cea Paul Brook
    config[0x3d] = 1;
690 53c25cea Paul Brook
691 5a1fc5e8 Michael S. Tsirkin
    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors, 1, 0)) {
692 aba800a3 Michael S. Tsirkin
        pci_register_bar(&proxy->pci_dev, 1,
693 aba800a3 Michael S. Tsirkin
                         msix_bar_size(&proxy->pci_dev),
694 0392a017 Isaku Yamahata
                         PCI_BASE_ADDRESS_SPACE_MEMORY,
695 aba800a3 Michael S. Tsirkin
                         msix_mmio_map);
696 aba800a3 Michael S. Tsirkin
    } else
697 aba800a3 Michael S. Tsirkin
        vdev->nvectors = 0;
698 aba800a3 Michael S. Tsirkin
699 ed757e14 Yan Vugenfirer
    proxy->pci_dev.config_write = virtio_write_config;
700 ed757e14 Yan Vugenfirer
701 aba800a3 Michael S. Tsirkin
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
702 53c25cea Paul Brook
    if (size & (size-1))
703 53c25cea Paul Brook
        size = 1 << qemu_fls(size);
704 53c25cea Paul Brook
705 0392a017 Isaku Yamahata
    pci_register_bar(&proxy->pci_dev, 0, size, PCI_BASE_ADDRESS_SPACE_IO,
706 53c25cea Paul Brook
                           virtio_map);
707 53c25cea Paul Brook
708 25db9ebe Stefan Hajnoczi
    if (!kvm_has_many_ioeventfds()) {
709 25db9ebe Stefan Hajnoczi
        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
710 25db9ebe Stefan Hajnoczi
    }
711 25db9ebe Stefan Hajnoczi
712 53c25cea Paul Brook
    virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
713 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
714 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
715 8172539d Michael S. Tsirkin
    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
716 53c25cea Paul Brook
}
717 53c25cea Paul Brook
718 81a322d4 Gerd Hoffmann
static int virtio_blk_init_pci(PCIDevice *pci_dev)
719 53c25cea Paul Brook
{
720 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
721 53c25cea Paul Brook
    VirtIODevice *vdev;
722 53c25cea Paul Brook
723 ab73ff29 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
724 ab73ff29 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_STORAGE_OTHER)
725 ab73ff29 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_STORAGE_SCSI;
726 53c25cea Paul Brook
727 428c149b Christoph Hellwig
    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block);
728 ac0c14d7 Markus Armbruster
    if (!vdev) {
729 ac0c14d7 Markus Armbruster
        return -1;
730 ac0c14d7 Markus Armbruster
    }
731 177539e0 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
732 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
733 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
734 85c2c735 Mark McLoughlin
                    PCI_DEVICE_ID_VIRTIO_BLOCK,
735 85c2c735 Mark McLoughlin
                    proxy->class_code, 0x00);
736 177539e0 Gerd Hoffmann
    /* make the actual value visible */
737 177539e0 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
738 81a322d4 Gerd Hoffmann
    return 0;
739 21d58b57 Mark McLoughlin
}
740 21d58b57 Mark McLoughlin
741 0f457d91 Michael S. Tsirkin
static int virtio_exit_pci(PCIDevice *pci_dev)
742 0f457d91 Michael S. Tsirkin
{
743 0f457d91 Michael S. Tsirkin
    return msix_uninit(pci_dev);
744 0f457d91 Michael S. Tsirkin
}
745 0f457d91 Michael S. Tsirkin
746 56a14938 Gerd Hoffmann
static int virtio_blk_exit_pci(PCIDevice *pci_dev)
747 56a14938 Gerd Hoffmann
{
748 56a14938 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
749 56a14938 Gerd Hoffmann
750 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
751 9d0d3138 Alex Williamson
    virtio_blk_exit(proxy->vdev);
752 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(proxy->block.bs);
753 0f457d91 Michael S. Tsirkin
    return virtio_exit_pci(pci_dev);
754 56a14938 Gerd Hoffmann
}
755 56a14938 Gerd Hoffmann
756 98b19252 Amit Shah
static int virtio_serial_init_pci(PCIDevice *pci_dev)
757 21d58b57 Mark McLoughlin
{
758 d6beee99 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
759 85c2c735 Mark McLoughlin
    VirtIODevice *vdev;
760 85c2c735 Mark McLoughlin
761 d6beee99 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
762 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
763 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
764 d6beee99 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
765 d6beee99 Gerd Hoffmann
766 98b19252 Amit Shah
    vdev = virtio_serial_init(&pci_dev->qdev, proxy->max_virtserial_ports);
767 25fe3654 Amit Shah
    if (!vdev) {
768 25fe3654 Amit Shah
        return -1;
769 25fe3654 Amit Shah
    }
770 573fb60c Amit Shah
    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
771 573fb60c Amit Shah
                                        ? proxy->max_virtserial_ports + 1
772 573fb60c Amit Shah
                                        : proxy->nvectors;
773 85c2c735 Mark McLoughlin
    virtio_init_pci(proxy, vdev,
774 85c2c735 Mark McLoughlin
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
775 85c2c735 Mark McLoughlin
                    PCI_DEVICE_ID_VIRTIO_CONSOLE,
776 85c2c735 Mark McLoughlin
                    proxy->class_code, 0x00);
777 a1829205 Amit Shah
    proxy->nvectors = vdev->nvectors;
778 81a322d4 Gerd Hoffmann
    return 0;
779 53c25cea Paul Brook
}
780 53c25cea Paul Brook
781 8b53a865 Amit Shah
static int virtio_serial_exit_pci(PCIDevice *pci_dev)
782 8b53a865 Amit Shah
{
783 8b53a865 Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
784 8b53a865 Amit Shah
785 8b53a865 Amit Shah
    virtio_serial_exit(proxy->vdev);
786 8b53a865 Amit Shah
    return virtio_exit_pci(pci_dev);
787 8b53a865 Amit Shah
}
788 8b53a865 Amit Shah
789 81a322d4 Gerd Hoffmann
static int virtio_net_init_pci(PCIDevice *pci_dev)
790 53c25cea Paul Brook
{
791 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
792 53c25cea Paul Brook
    VirtIODevice *vdev;
793 53c25cea Paul Brook
794 f0c07c7c Alex Williamson
    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
795 a1e0fea5 Gerd Hoffmann
796 97b15621 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
797 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
798 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
799 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_NET,
800 53c25cea Paul Brook
                    PCI_CLASS_NETWORK_ETHERNET,
801 53c25cea Paul Brook
                    0x00);
802 a1e0fea5 Gerd Hoffmann
803 a1e0fea5 Gerd Hoffmann
    /* make the actual value visible */
804 a1e0fea5 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
805 81a322d4 Gerd Hoffmann
    return 0;
806 53c25cea Paul Brook
}
807 53c25cea Paul Brook
808 97b15621 Gerd Hoffmann
static int virtio_net_exit_pci(PCIDevice *pci_dev)
809 97b15621 Gerd Hoffmann
{
810 97b15621 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
811 97b15621 Gerd Hoffmann
812 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
813 97b15621 Gerd Hoffmann
    virtio_net_exit(proxy->vdev);
814 97b15621 Gerd Hoffmann
    return virtio_exit_pci(pci_dev);
815 97b15621 Gerd Hoffmann
}
816 97b15621 Gerd Hoffmann
817 81a322d4 Gerd Hoffmann
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
818 53c25cea Paul Brook
{
819 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
820 53c25cea Paul Brook
    VirtIODevice *vdev;
821 53c25cea Paul Brook
822 53c25cea Paul Brook
    vdev = virtio_balloon_init(&pci_dev->qdev);
823 53c25cea Paul Brook
    virtio_init_pci(proxy, vdev,
824 53c25cea Paul Brook
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
825 53c25cea Paul Brook
                    PCI_DEVICE_ID_VIRTIO_BALLOON,
826 53c25cea Paul Brook
                    PCI_CLASS_MEMORY_RAM,
827 53c25cea Paul Brook
                    0x00);
828 81a322d4 Gerd Hoffmann
    return 0;
829 53c25cea Paul Brook
}
830 53c25cea Paul Brook
831 758e8e38 Venkateswararao Jujjuri (JV)
#ifdef CONFIG_VIRTFS
832 9f107513 Anthony Liguori
static int virtio_9p_init_pci(PCIDevice *pci_dev)
833 9f107513 Anthony Liguori
{
834 9f107513 Anthony Liguori
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
835 9f107513 Anthony Liguori
    VirtIODevice *vdev;
836 9f107513 Anthony Liguori
837 9f107513 Anthony Liguori
    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
838 9dbcca5a Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
839 9f107513 Anthony Liguori
    virtio_init_pci(proxy, vdev,
840 9f107513 Anthony Liguori
                    PCI_VENDOR_ID_REDHAT_QUMRANET,
841 9f107513 Anthony Liguori
                    0x1009,
842 9f107513 Anthony Liguori
                    0x2,
843 9f107513 Anthony Liguori
                    0x00);
844 9dbcca5a Gerd Hoffmann
    /* make the actual value visible */
845 9dbcca5a Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
846 9f107513 Anthony Liguori
    return 0;
847 9f107513 Anthony Liguori
}
848 9f107513 Anthony Liguori
#endif
849 9f107513 Anthony Liguori
850 0aab0d3a Gerd Hoffmann
static PCIDeviceInfo virtio_info[] = {
851 0aab0d3a Gerd Hoffmann
    {
852 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-blk-pci",
853 779206de Gleb Natapov
        .qdev.alias = "virtio-blk",
854 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
855 0aab0d3a Gerd Hoffmann
        .init      = virtio_blk_init_pci,
856 56a14938 Gerd Hoffmann
        .exit      = virtio_blk_exit_pci,
857 ab73ff29 Gerd Hoffmann
        .qdev.props = (Property[]) {
858 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
859 428c149b Christoph Hellwig
            DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
860 25db9ebe Stefan Hajnoczi
            DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
861 25db9ebe Stefan Hajnoczi
                            VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
862 177539e0 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
863 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
864 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
865 ab73ff29 Gerd Hoffmann
        },
866 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
867 0aab0d3a Gerd Hoffmann
    },{
868 a1e0fea5 Gerd Hoffmann
        .qdev.name  = "virtio-net-pci",
869 a1e0fea5 Gerd Hoffmann
        .qdev.size  = sizeof(VirtIOPCIProxy),
870 a1e0fea5 Gerd Hoffmann
        .init       = virtio_net_init_pci,
871 97b15621 Gerd Hoffmann
        .exit       = virtio_net_exit_pci,
872 8c52c8f3 Gerd Hoffmann
        .romfile    = "pxe-virtio.bin",
873 a1e0fea5 Gerd Hoffmann
        .qdev.props = (Property[]) {
874 25db9ebe Stefan Hajnoczi
            DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
875 25db9ebe Stefan Hajnoczi
                            VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
876 97b15621 Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
877 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
878 97b15621 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
879 f0c07c7c Alex Williamson
            DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy,
880 f0c07c7c Alex Williamson
                               net.txtimer, TX_TIMER_INTERVAL),
881 e3f30488 Alex Williamson
            DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy,
882 e3f30488 Alex Williamson
                              net.txburst, TX_BURST),
883 a697a334 Alex Williamson
            DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
884 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
885 a1e0fea5 Gerd Hoffmann
        },
886 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
887 0aab0d3a Gerd Hoffmann
    },{
888 98b19252 Amit Shah
        .qdev.name = "virtio-serial-pci",
889 98b19252 Amit Shah
        .qdev.alias = "virtio-serial",
890 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
891 98b19252 Amit Shah
        .init      = virtio_serial_init_pci,
892 8b53a865 Amit Shah
        .exit      = virtio_serial_exit_pci,
893 d6beee99 Gerd Hoffmann
        .qdev.props = (Property[]) {
894 573fb60c Amit Shah
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
895 573fb60c Amit Shah
                               DEV_NVECTORS_UNSPECIFIED),
896 72c61d0b Gerd Hoffmann
            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
897 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
898 98b19252 Amit Shah
            DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, max_virtserial_ports,
899 98b19252 Amit Shah
                               31),
900 72c61d0b Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
901 d6beee99 Gerd Hoffmann
        },
902 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
903 0aab0d3a Gerd Hoffmann
    },{
904 0aab0d3a Gerd Hoffmann
        .qdev.name = "virtio-balloon-pci",
905 0aab0d3a Gerd Hoffmann
        .qdev.size = sizeof(VirtIOPCIProxy),
906 0aab0d3a Gerd Hoffmann
        .init      = virtio_balloon_init_pci,
907 0f457d91 Michael S. Tsirkin
        .exit      = virtio_exit_pci,
908 8172539d Michael S. Tsirkin
        .qdev.props = (Property[]) {
909 8172539d Michael S. Tsirkin
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
910 8172539d Michael S. Tsirkin
            DEFINE_PROP_END_OF_LIST(),
911 8172539d Michael S. Tsirkin
        },
912 e489030d Michael S. Tsirkin
        .qdev.reset = virtio_pci_reset,
913 0aab0d3a Gerd Hoffmann
    },{
914 758e8e38 Venkateswararao Jujjuri (JV)
#ifdef CONFIG_VIRTFS
915 9f107513 Anthony Liguori
        .qdev.name = "virtio-9p-pci",
916 9f107513 Anthony Liguori
        .qdev.size = sizeof(VirtIOPCIProxy),
917 9f107513 Anthony Liguori
        .init      = virtio_9p_init_pci,
918 9f107513 Anthony Liguori
        .qdev.props = (Property[]) {
919 9dbcca5a Gerd Hoffmann
            DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
920 9f107513 Anthony Liguori
            DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
921 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
922 9f107513 Anthony Liguori
            DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
923 9f107513 Anthony Liguori
            DEFINE_PROP_END_OF_LIST(),
924 9f107513 Anthony Liguori
        },
925 9f107513 Anthony Liguori
    }, {
926 9f107513 Anthony Liguori
#endif
927 0aab0d3a Gerd Hoffmann
        /* end of list */
928 0aab0d3a Gerd Hoffmann
    }
929 0aab0d3a Gerd Hoffmann
};
930 0aab0d3a Gerd Hoffmann
931 53c25cea Paul Brook
static void virtio_pci_register_devices(void)
932 53c25cea Paul Brook
{
933 0aab0d3a Gerd Hoffmann
    pci_qdev_register_many(virtio_info);
934 53c25cea Paul Brook
}
935 53c25cea Paul Brook
936 53c25cea Paul Brook
device_init(virtio_pci_register_devices)