Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ 89c473fd

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