Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ c48c6522

History | View | Annotate | Download (34.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 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
15 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
16 53c25cea Paul Brook
 */
17 53c25cea Paul Brook
18 53c25cea Paul Brook
#include <inttypes.h>
19 53c25cea Paul Brook
20 53c25cea Paul Brook
#include "virtio.h"
21 8172539d Michael S. Tsirkin
#include "virtio-blk.h"
22 8172539d Michael S. Tsirkin
#include "virtio-net.h"
23 6b331efb Amit Shah
#include "virtio-serial.h"
24 973abc7f Stefan Hajnoczi
#include "virtio-scsi.h"
25 53c25cea Paul Brook
#include "pci.h"
26 2f792016 Markus Armbruster
#include "qemu-error.h"
27 7d37d351 Jan Kiszka
#include "msi.h"
28 aba800a3 Michael S. Tsirkin
#include "msix.h"
29 a1e0fea5 Gerd Hoffmann
#include "net.h"
30 97b15621 Gerd Hoffmann
#include "loader.h"
31 ade80dc8 Michael S. Tsirkin
#include "kvm.h"
32 2446333c Blue Swirl
#include "blockdev.h"
33 9fe1ebeb Aneesh Kumar K.V
#include "virtio-pci.h"
34 1129714f Michael S. Tsirkin
#include "range.h"
35 53c25cea Paul Brook
36 53c25cea Paul Brook
/* from Linux's linux/virtio_pci.h */
37 53c25cea Paul Brook
38 53c25cea Paul Brook
/* A 32-bit r/o bitmask of the features supported by the host */
39 53c25cea Paul Brook
#define VIRTIO_PCI_HOST_FEATURES        0
40 53c25cea Paul Brook
41 53c25cea Paul Brook
/* A 32-bit r/w bitmask of features activated by the guest */
42 53c25cea Paul Brook
#define VIRTIO_PCI_GUEST_FEATURES       4
43 53c25cea Paul Brook
44 53c25cea Paul Brook
/* A 32-bit r/w PFN for the currently selected queue */
45 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_PFN            8
46 53c25cea Paul Brook
47 53c25cea Paul Brook
/* A 16-bit r/o queue size for the currently selected queue */
48 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NUM            12
49 53c25cea Paul Brook
50 53c25cea Paul Brook
/* A 16-bit r/w queue selector */
51 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_SEL            14
52 53c25cea Paul Brook
53 53c25cea Paul Brook
/* A 16-bit r/w queue notifier */
54 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NOTIFY         16
55 53c25cea Paul Brook
56 53c25cea Paul Brook
/* An 8-bit device status register.  */
57 53c25cea Paul Brook
#define VIRTIO_PCI_STATUS               18
58 53c25cea Paul Brook
59 53c25cea Paul Brook
/* An 8-bit r/o interrupt status register.  Reading the value will return the
60 53c25cea Paul Brook
 * current contents of the ISR and will also clear it.  This is effectively
61 53c25cea Paul Brook
 * a read-and-acknowledge. */
62 53c25cea Paul Brook
#define VIRTIO_PCI_ISR                  19
63 53c25cea Paul Brook
64 aba800a3 Michael S. Tsirkin
/* MSI-X registers: only enabled if MSI-X is enabled. */
65 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for configuration changes. */
66 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_CONFIG_VECTOR        20
67 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for selected queue notifications. */
68 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_QUEUE_VECTOR         22
69 aba800a3 Michael S. Tsirkin
70 aba800a3 Michael S. Tsirkin
/* Config space size */
71 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_NOMSI         20
72 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_MSI           24
73 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
74 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
75 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
76 aba800a3 Michael S. Tsirkin
77 aba800a3 Michael S. Tsirkin
/* The remaining space is defined by each driver as the per-driver
78 aba800a3 Michael S. Tsirkin
 * configuration space */
79 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
80 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
81 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
82 53c25cea Paul Brook
83 53c25cea Paul Brook
/* How many bits to shift physical queue address written to QUEUE_PFN.
84 53c25cea Paul Brook
 * 12 is historical, and due to x86 page size. */
85 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
86 53c25cea Paul Brook
87 3dbca8e6 Stefan Hajnoczi
/* Flags track per-device state like workarounds for quirks in older guests. */
88 3dbca8e6 Stefan Hajnoczi
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG  (1 << 0)
89 c81131db Alexander Graf
90 53c25cea Paul Brook
/* QEMU doesn't strictly need write barriers since everything runs in
91 53c25cea Paul Brook
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
92 53c25cea Paul Brook
 * KVM or if kqemu gets SMP support.
93 53c25cea Paul Brook
 */
94 53c25cea Paul Brook
#define wmb() do { } while (0)
95 53c25cea Paul Brook
96 82afa586 Benjamin Herrenschmidt
/* HACK for virtio to determine if it's running a big endian guest */
97 82afa586 Benjamin Herrenschmidt
bool virtio_is_big_endian(void);
98 82afa586 Benjamin Herrenschmidt
99 53c25cea Paul Brook
/* virtio device */
100 53c25cea Paul Brook
101 7055e687 Michael S. Tsirkin
static void virtio_pci_notify(void *opaque, uint16_t vector)
102 53c25cea Paul Brook
{
103 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
104 aba800a3 Michael S. Tsirkin
    if (msix_enabled(&proxy->pci_dev))
105 aba800a3 Michael S. Tsirkin
        msix_notify(&proxy->pci_dev, vector);
106 aba800a3 Michael S. Tsirkin
    else
107 aba800a3 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
108 53c25cea Paul Brook
}
109 53c25cea Paul Brook
110 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_config(void * opaque, QEMUFile *f)
111 ff24bd58 Michael S. Tsirkin
{
112 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
113 ff24bd58 Michael S. Tsirkin
    pci_device_save(&proxy->pci_dev, f);
114 ff24bd58 Michael S. Tsirkin
    msix_save(&proxy->pci_dev, f);
115 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
116 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, proxy->vdev->config_vector);
117 ff24bd58 Michael S. Tsirkin
}
118 ff24bd58 Michael S. Tsirkin
119 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
120 ff24bd58 Michael S. Tsirkin
{
121 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
122 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
123 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
124 ff24bd58 Michael S. Tsirkin
}
125 ff24bd58 Michael S. Tsirkin
126 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_config(void * opaque, QEMUFile *f)
127 ff24bd58 Michael S. Tsirkin
{
128 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
129 ff24bd58 Michael S. Tsirkin
    int ret;
130 ff24bd58 Michael S. Tsirkin
    ret = pci_device_load(&proxy->pci_dev, f);
131 e6da7680 Michael S. Tsirkin
    if (ret) {
132 ff24bd58 Michael S. Tsirkin
        return ret;
133 e6da7680 Michael S. Tsirkin
    }
134 ff24bd58 Michael S. Tsirkin
    msix_load(&proxy->pci_dev, f);
135 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
136 ff24bd58 Michael S. Tsirkin
        qemu_get_be16s(f, &proxy->vdev->config_vector);
137 e6da7680 Michael S. Tsirkin
    } else {
138 e6da7680 Michael S. Tsirkin
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
139 e6da7680 Michael S. Tsirkin
    }
140 e6da7680 Michael S. Tsirkin
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
141 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
142 e6da7680 Michael S. Tsirkin
    }
143 ff24bd58 Michael S. Tsirkin
    return 0;
144 ff24bd58 Michael S. Tsirkin
}
145 ff24bd58 Michael S. Tsirkin
146 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
147 ff24bd58 Michael S. Tsirkin
{
148 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
149 ff24bd58 Michael S. Tsirkin
    uint16_t vector;
150 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
151 e6da7680 Michael S. Tsirkin
        qemu_get_be16s(f, &vector);
152 e6da7680 Michael S. Tsirkin
    } else {
153 e6da7680 Michael S. Tsirkin
        vector = VIRTIO_NO_VECTOR;
154 e6da7680 Michael S. Tsirkin
    }
155 ff24bd58 Michael S. Tsirkin
    virtio_queue_set_vector(proxy->vdev, n, vector);
156 e6da7680 Michael S. Tsirkin
    if (vector != VIRTIO_NO_VECTOR) {
157 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, vector);
158 e6da7680 Michael S. Tsirkin
    }
159 ff24bd58 Michael S. Tsirkin
    return 0;
160 ff24bd58 Michael S. Tsirkin
}
161 ff24bd58 Michael S. Tsirkin
162 25db9ebe Stefan Hajnoczi
static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
163 25db9ebe Stefan Hajnoczi
                                                 int n, bool assign)
164 25db9ebe Stefan Hajnoczi
{
165 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
166 25db9ebe Stefan Hajnoczi
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
167 da146d0a Avi Kivity
    int r = 0;
168 da146d0a Avi Kivity
169 25db9ebe Stefan Hajnoczi
    if (assign) {
170 25db9ebe Stefan Hajnoczi
        r = event_notifier_init(notifier, 1);
171 25db9ebe Stefan Hajnoczi
        if (r < 0) {
172 b36e3914 Michael S. Tsirkin
            error_report("%s: unable to init event notifier: %d",
173 b36e3914 Michael S. Tsirkin
                         __func__, r);
174 25db9ebe Stefan Hajnoczi
            return r;
175 25db9ebe Stefan Hajnoczi
        }
176 da146d0a Avi Kivity
        memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
177 da146d0a Avi Kivity
                                  true, n, event_notifier_get_fd(notifier));
178 25db9ebe Stefan Hajnoczi
    } else {
179 da146d0a Avi Kivity
        memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
180 da146d0a Avi Kivity
                                  true, n, event_notifier_get_fd(notifier));
181 25db9ebe Stefan Hajnoczi
        /* Handle the race condition where the guest kicked and we deassigned
182 25db9ebe Stefan Hajnoczi
         * before we got around to handling the kick.
183 25db9ebe Stefan Hajnoczi
         */
184 25db9ebe Stefan Hajnoczi
        if (event_notifier_test_and_clear(notifier)) {
185 25db9ebe Stefan Hajnoczi
            virtio_queue_notify_vq(vq);
186 25db9ebe Stefan Hajnoczi
        }
187 25db9ebe Stefan Hajnoczi
188 25db9ebe Stefan Hajnoczi
        event_notifier_cleanup(notifier);
189 25db9ebe Stefan Hajnoczi
    }
190 25db9ebe Stefan Hajnoczi
    return r;
191 25db9ebe Stefan Hajnoczi
}
192 25db9ebe Stefan Hajnoczi
193 25db9ebe Stefan Hajnoczi
static void virtio_pci_host_notifier_read(void *opaque)
194 25db9ebe Stefan Hajnoczi
{
195 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = opaque;
196 25db9ebe Stefan Hajnoczi
    EventNotifier *n = virtio_queue_get_host_notifier(vq);
197 25db9ebe Stefan Hajnoczi
    if (event_notifier_test_and_clear(n)) {
198 25db9ebe Stefan Hajnoczi
        virtio_queue_notify_vq(vq);
199 25db9ebe Stefan Hajnoczi
    }
200 25db9ebe Stefan Hajnoczi
}
201 25db9ebe Stefan Hajnoczi
202 25db9ebe Stefan Hajnoczi
static void virtio_pci_set_host_notifier_fd_handler(VirtIOPCIProxy *proxy,
203 25db9ebe Stefan Hajnoczi
                                                    int n, bool assign)
204 25db9ebe Stefan Hajnoczi
{
205 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
206 25db9ebe Stefan Hajnoczi
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
207 25db9ebe Stefan Hajnoczi
    if (assign) {
208 25db9ebe Stefan Hajnoczi
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
209 25db9ebe Stefan Hajnoczi
                            virtio_pci_host_notifier_read, NULL, vq);
210 25db9ebe Stefan Hajnoczi
    } else {
211 25db9ebe Stefan Hajnoczi
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
212 25db9ebe Stefan Hajnoczi
                            NULL, NULL, NULL);
213 25db9ebe Stefan Hajnoczi
    }
214 25db9ebe Stefan Hajnoczi
}
215 25db9ebe Stefan Hajnoczi
216 b36e3914 Michael S. Tsirkin
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
217 25db9ebe Stefan Hajnoczi
{
218 25db9ebe Stefan Hajnoczi
    int n, r;
219 25db9ebe Stefan Hajnoczi
220 25db9ebe Stefan Hajnoczi
    if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
221 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_disabled ||
222 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_started) {
223 b36e3914 Michael S. Tsirkin
        return;
224 25db9ebe Stefan Hajnoczi
    }
225 25db9ebe Stefan Hajnoczi
226 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
227 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
228 25db9ebe Stefan Hajnoczi
            continue;
229 25db9ebe Stefan Hajnoczi
        }
230 25db9ebe Stefan Hajnoczi
231 25db9ebe Stefan Hajnoczi
        r = virtio_pci_set_host_notifier_internal(proxy, n, true);
232 25db9ebe Stefan Hajnoczi
        if (r < 0) {
233 25db9ebe Stefan Hajnoczi
            goto assign_error;
234 25db9ebe Stefan Hajnoczi
        }
235 25db9ebe Stefan Hajnoczi
236 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, true);
237 25db9ebe Stefan Hajnoczi
    }
238 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = true;
239 b36e3914 Michael S. Tsirkin
    return;
240 25db9ebe Stefan Hajnoczi
241 25db9ebe Stefan Hajnoczi
assign_error:
242 25db9ebe Stefan Hajnoczi
    while (--n >= 0) {
243 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
244 25db9ebe Stefan Hajnoczi
            continue;
245 25db9ebe Stefan Hajnoczi
        }
246 25db9ebe Stefan Hajnoczi
247 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
248 b36e3914 Michael S. Tsirkin
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
249 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
250 25db9ebe Stefan Hajnoczi
    }
251 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
252 b36e3914 Michael S. Tsirkin
    error_report("%s: failed. Fallback to a userspace (slower).", __func__);
253 25db9ebe Stefan Hajnoczi
}
254 25db9ebe Stefan Hajnoczi
255 b36e3914 Michael S. Tsirkin
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
256 25db9ebe Stefan Hajnoczi
{
257 b36e3914 Michael S. Tsirkin
    int r;
258 25db9ebe Stefan Hajnoczi
    int n;
259 25db9ebe Stefan Hajnoczi
260 25db9ebe Stefan Hajnoczi
    if (!proxy->ioeventfd_started) {
261 b36e3914 Michael S. Tsirkin
        return;
262 25db9ebe Stefan Hajnoczi
    }
263 25db9ebe Stefan Hajnoczi
264 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
265 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
266 25db9ebe Stefan Hajnoczi
            continue;
267 25db9ebe Stefan Hajnoczi
        }
268 25db9ebe Stefan Hajnoczi
269 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
270 b36e3914 Michael S. Tsirkin
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
271 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
272 25db9ebe Stefan Hajnoczi
    }
273 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
274 25db9ebe Stefan Hajnoczi
}
275 25db9ebe Stefan Hajnoczi
276 8798d6c9 Aneesh Kumar K.V
void virtio_pci_reset(DeviceState *d)
277 7055e687 Michael S. Tsirkin
{
278 e489030d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
279 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
280 7055e687 Michael S. Tsirkin
    virtio_reset(proxy->vdev);
281 25db9ebe Stefan Hajnoczi
    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
282 7055e687 Michael S. Tsirkin
}
283 7055e687 Michael S. Tsirkin
284 53c25cea Paul Brook
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
285 53c25cea Paul Brook
{
286 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
287 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
288 c227f099 Anthony Liguori
    target_phys_addr_t pa;
289 53c25cea Paul Brook
290 53c25cea Paul Brook
    switch (addr) {
291 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
292 53c25cea Paul Brook
        /* Guest does not negotiate properly?  We have to assume nothing. */
293 53c25cea Paul Brook
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
294 ad0c9332 Paolo Bonzini
            val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
295 53c25cea Paul Brook
        }
296 ad0c9332 Paolo Bonzini
        virtio_set_features(vdev, val);
297 53c25cea Paul Brook
        break;
298 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
299 c227f099 Anthony Liguori
        pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
300 1b8e9b27 Michael S. Tsirkin
        if (pa == 0) {
301 25db9ebe Stefan Hajnoczi
            virtio_pci_stop_ioeventfd(proxy);
302 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
303 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
304 1b8e9b27 Michael S. Tsirkin
        }
305 7055e687 Michael S. Tsirkin
        else
306 7055e687 Michael S. Tsirkin
            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
307 53c25cea Paul Brook
        break;
308 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
309 53c25cea Paul Brook
        if (val < VIRTIO_PCI_QUEUE_MAX)
310 53c25cea Paul Brook
            vdev->queue_sel = val;
311 53c25cea Paul Brook
        break;
312 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NOTIFY:
313 7157e2e2 Stefan Hajnoczi
        if (val < VIRTIO_PCI_QUEUE_MAX) {
314 7157e2e2 Stefan Hajnoczi
            virtio_queue_notify(vdev, val);
315 7157e2e2 Stefan Hajnoczi
        }
316 53c25cea Paul Brook
        break;
317 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
318 25db9ebe Stefan Hajnoczi
        if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
319 25db9ebe Stefan Hajnoczi
            virtio_pci_stop_ioeventfd(proxy);
320 25db9ebe Stefan Hajnoczi
        }
321 25db9ebe Stefan Hajnoczi
322 3e607cb5 Michael S. Tsirkin
        virtio_set_status(vdev, val & 0xFF);
323 25db9ebe Stefan Hajnoczi
324 25db9ebe Stefan Hajnoczi
        if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
325 25db9ebe Stefan Hajnoczi
            virtio_pci_start_ioeventfd(proxy);
326 25db9ebe Stefan Hajnoczi
        }
327 25db9ebe Stefan Hajnoczi
328 1b8e9b27 Michael S. Tsirkin
        if (vdev->status == 0) {
329 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
330 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
331 1b8e9b27 Michael S. Tsirkin
        }
332 c81131db Alexander Graf
333 c81131db Alexander Graf
        /* Linux before 2.6.34 sets the device as OK without enabling
334 c81131db Alexander Graf
           the PCI device bus master bit. In this case we need to disable
335 c81131db Alexander Graf
           some safety checks. */
336 c81131db Alexander Graf
        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
337 c81131db Alexander Graf
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
338 3dbca8e6 Stefan Hajnoczi
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
339 c81131db Alexander Graf
        }
340 53c25cea Paul Brook
        break;
341 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
342 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
343 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
344 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
345 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
346 aba800a3 Michael S. Tsirkin
        vdev->config_vector = val;
347 aba800a3 Michael S. Tsirkin
        break;
348 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
349 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev,
350 aba800a3 Michael S. Tsirkin
                          virtio_queue_vector(vdev, vdev->queue_sel));
351 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
352 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
353 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
354 aba800a3 Michael S. Tsirkin
        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
355 aba800a3 Michael S. Tsirkin
        break;
356 aba800a3 Michael S. Tsirkin
    default:
357 4e02d460 Stefan Hajnoczi
        error_report("%s: unexpected address 0x%x value 0x%x",
358 4e02d460 Stefan Hajnoczi
                     __func__, addr, val);
359 aba800a3 Michael S. Tsirkin
        break;
360 53c25cea Paul Brook
    }
361 53c25cea Paul Brook
}
362 53c25cea Paul Brook
363 aba800a3 Michael S. Tsirkin
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
364 53c25cea Paul Brook
{
365 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
366 53c25cea Paul Brook
    uint32_t ret = 0xFFFFFFFF;
367 53c25cea Paul Brook
368 53c25cea Paul Brook
    switch (addr) {
369 53c25cea Paul Brook
    case VIRTIO_PCI_HOST_FEATURES:
370 8172539d Michael S. Tsirkin
        ret = proxy->host_features;
371 53c25cea Paul Brook
        break;
372 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
373 704a76fc Michael S. Tsirkin
        ret = vdev->guest_features;
374 53c25cea Paul Brook
        break;
375 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
376 53c25cea Paul Brook
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
377 53c25cea Paul Brook
              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
378 53c25cea Paul Brook
        break;
379 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NUM:
380 53c25cea Paul Brook
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
381 53c25cea Paul Brook
        break;
382 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
383 53c25cea Paul Brook
        ret = vdev->queue_sel;
384 53c25cea Paul Brook
        break;
385 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
386 53c25cea Paul Brook
        ret = vdev->status;
387 53c25cea Paul Brook
        break;
388 53c25cea Paul Brook
    case VIRTIO_PCI_ISR:
389 53c25cea Paul Brook
        /* reading from the ISR also clears it. */
390 53c25cea Paul Brook
        ret = vdev->isr;
391 53c25cea Paul Brook
        vdev->isr = 0;
392 7055e687 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], 0);
393 53c25cea Paul Brook
        break;
394 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
395 aba800a3 Michael S. Tsirkin
        ret = vdev->config_vector;
396 aba800a3 Michael S. Tsirkin
        break;
397 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
398 aba800a3 Michael S. Tsirkin
        ret = virtio_queue_vector(vdev, vdev->queue_sel);
399 aba800a3 Michael S. Tsirkin
        break;
400 53c25cea Paul Brook
    default:
401 53c25cea Paul Brook
        break;
402 53c25cea Paul Brook
    }
403 53c25cea Paul Brook
404 53c25cea Paul Brook
    return ret;
405 53c25cea Paul Brook
}
406 53c25cea Paul Brook
407 53c25cea Paul Brook
static uint32_t virtio_pci_config_readb(void *opaque, uint32_t addr)
408 53c25cea Paul Brook
{
409 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
410 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
411 aba800a3 Michael S. Tsirkin
    if (addr < config)
412 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
413 aba800a3 Michael S. Tsirkin
    addr -= config;
414 53c25cea Paul Brook
    return virtio_config_readb(proxy->vdev, addr);
415 53c25cea Paul Brook
}
416 53c25cea Paul Brook
417 53c25cea Paul Brook
static uint32_t virtio_pci_config_readw(void *opaque, uint32_t addr)
418 53c25cea Paul Brook
{
419 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
420 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
421 82afa586 Benjamin Herrenschmidt
    uint16_t val;
422 aba800a3 Michael S. Tsirkin
    if (addr < config)
423 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
424 aba800a3 Michael S. Tsirkin
    addr -= config;
425 82afa586 Benjamin Herrenschmidt
    val = virtio_config_readw(proxy->vdev, addr);
426 82afa586 Benjamin Herrenschmidt
    if (virtio_is_big_endian()) {
427 82afa586 Benjamin Herrenschmidt
        /*
428 82afa586 Benjamin Herrenschmidt
         * virtio is odd, ioports are LE but config space is target native
429 82afa586 Benjamin Herrenschmidt
         * endian. However, in qemu, all PIO is LE, so we need to re-swap
430 82afa586 Benjamin Herrenschmidt
         * on BE targets
431 82afa586 Benjamin Herrenschmidt
         */
432 82afa586 Benjamin Herrenschmidt
        val = bswap16(val);
433 82afa586 Benjamin Herrenschmidt
    }
434 82afa586 Benjamin Herrenschmidt
    return val;
435 53c25cea Paul Brook
}
436 53c25cea Paul Brook
437 53c25cea Paul Brook
static uint32_t virtio_pci_config_readl(void *opaque, uint32_t addr)
438 53c25cea Paul Brook
{
439 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
440 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
441 82afa586 Benjamin Herrenschmidt
    uint32_t val;
442 aba800a3 Michael S. Tsirkin
    if (addr < config)
443 aba800a3 Michael S. Tsirkin
        return virtio_ioport_read(proxy, addr);
444 aba800a3 Michael S. Tsirkin
    addr -= config;
445 82afa586 Benjamin Herrenschmidt
    val = virtio_config_readl(proxy->vdev, addr);
446 82afa586 Benjamin Herrenschmidt
    if (virtio_is_big_endian()) {
447 82afa586 Benjamin Herrenschmidt
        val = bswap32(val);
448 82afa586 Benjamin Herrenschmidt
    }
449 82afa586 Benjamin Herrenschmidt
    return val;
450 53c25cea Paul Brook
}
451 53c25cea Paul Brook
452 53c25cea Paul Brook
static void virtio_pci_config_writeb(void *opaque, uint32_t addr, uint32_t val)
453 53c25cea Paul Brook
{
454 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
455 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
456 aba800a3 Michael S. Tsirkin
    if (addr < config) {
457 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
458 aba800a3 Michael S. Tsirkin
        return;
459 aba800a3 Michael S. Tsirkin
    }
460 aba800a3 Michael S. Tsirkin
    addr -= config;
461 53c25cea Paul Brook
    virtio_config_writeb(proxy->vdev, addr, val);
462 53c25cea Paul Brook
}
463 53c25cea Paul Brook
464 53c25cea Paul Brook
static void virtio_pci_config_writew(void *opaque, uint32_t addr, uint32_t val)
465 53c25cea Paul Brook
{
466 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
467 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
468 aba800a3 Michael S. Tsirkin
    if (addr < config) {
469 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
470 aba800a3 Michael S. Tsirkin
        return;
471 aba800a3 Michael S. Tsirkin
    }
472 aba800a3 Michael S. Tsirkin
    addr -= config;
473 82afa586 Benjamin Herrenschmidt
    if (virtio_is_big_endian()) {
474 82afa586 Benjamin Herrenschmidt
        val = bswap16(val);
475 82afa586 Benjamin Herrenschmidt
    }
476 53c25cea Paul Brook
    virtio_config_writew(proxy->vdev, addr, val);
477 53c25cea Paul Brook
}
478 53c25cea Paul Brook
479 53c25cea Paul Brook
static void virtio_pci_config_writel(void *opaque, uint32_t addr, uint32_t val)
480 53c25cea Paul Brook
{
481 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
482 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
483 aba800a3 Michael S. Tsirkin
    if (addr < config) {
484 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
485 aba800a3 Michael S. Tsirkin
        return;
486 aba800a3 Michael S. Tsirkin
    }
487 aba800a3 Michael S. Tsirkin
    addr -= config;
488 82afa586 Benjamin Herrenschmidt
    if (virtio_is_big_endian()) {
489 82afa586 Benjamin Herrenschmidt
        val = bswap32(val);
490 82afa586 Benjamin Herrenschmidt
    }
491 53c25cea Paul Brook
    virtio_config_writel(proxy->vdev, addr, val);
492 53c25cea Paul Brook
}
493 53c25cea Paul Brook
494 4636b9d1 Blue Swirl
static const MemoryRegionPortio virtio_portio[] = {
495 da146d0a Avi Kivity
    { 0, 0x10000, 1, .write = virtio_pci_config_writeb, },
496 da146d0a Avi Kivity
    { 0, 0x10000, 2, .write = virtio_pci_config_writew, },
497 da146d0a Avi Kivity
    { 0, 0x10000, 4, .write = virtio_pci_config_writel, },
498 da146d0a Avi Kivity
    { 0, 0x10000, 1, .read = virtio_pci_config_readb, },
499 da146d0a Avi Kivity
    { 0, 0x10000, 2, .read = virtio_pci_config_readw, },
500 da146d0a Avi Kivity
    { 0, 0x10000, 4, .read = virtio_pci_config_readl, },
501 da146d0a Avi Kivity
    PORTIO_END_OF_LIST()
502 da146d0a Avi Kivity
};
503 53c25cea Paul Brook
504 da146d0a Avi Kivity
static const MemoryRegionOps virtio_pci_config_ops = {
505 da146d0a Avi Kivity
    .old_portio = virtio_portio,
506 da146d0a Avi Kivity
    .endianness = DEVICE_LITTLE_ENDIAN,
507 da146d0a Avi Kivity
};
508 aba800a3 Michael S. Tsirkin
509 aba800a3 Michael S. Tsirkin
static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
510 aba800a3 Michael S. Tsirkin
                                uint32_t val, int len)
511 aba800a3 Michael S. Tsirkin
{
512 ed757e14 Yan Vugenfirer
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
513 ed757e14 Yan Vugenfirer
514 1129714f Michael S. Tsirkin
    pci_default_write_config(pci_dev, address, val, len);
515 1129714f Michael S. Tsirkin
516 1129714f Michael S. Tsirkin
    if (range_covers_byte(address, len, PCI_COMMAND) &&
517 1129714f Michael S. Tsirkin
        !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
518 1129714f Michael S. Tsirkin
        !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
519 1129714f Michael S. Tsirkin
        virtio_pci_stop_ioeventfd(proxy);
520 1129714f Michael S. Tsirkin
        virtio_set_status(proxy->vdev,
521 1129714f Michael S. Tsirkin
                          proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
522 ed757e14 Yan Vugenfirer
    }
523 53c25cea Paul Brook
}
524 53c25cea Paul Brook
525 6d74ca5a Michael S. Tsirkin
static unsigned virtio_pci_get_features(void *opaque)
526 6d74ca5a Michael S. Tsirkin
{
527 8172539d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
528 8172539d Michael S. Tsirkin
    return proxy->host_features;
529 6d74ca5a Michael S. Tsirkin
}
530 6d74ca5a Michael S. Tsirkin
531 ade80dc8 Michael S. Tsirkin
static void virtio_pci_guest_notifier_read(void *opaque)
532 ade80dc8 Michael S. Tsirkin
{
533 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = opaque;
534 ade80dc8 Michael S. Tsirkin
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
535 ade80dc8 Michael S. Tsirkin
    if (event_notifier_test_and_clear(n)) {
536 ade80dc8 Michael S. Tsirkin
        virtio_irq(vq);
537 ade80dc8 Michael S. Tsirkin
    }
538 ade80dc8 Michael S. Tsirkin
}
539 ade80dc8 Michael S. Tsirkin
540 7d37d351 Jan Kiszka
static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
541 7d37d351 Jan Kiszka
                                        unsigned int queue_no,
542 7d37d351 Jan Kiszka
                                        unsigned int vector,
543 7d37d351 Jan Kiszka
                                        MSIMessage msg)
544 7d37d351 Jan Kiszka
{
545 7d37d351 Jan Kiszka
    VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
546 7d37d351 Jan Kiszka
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
547 7d37d351 Jan Kiszka
    int fd, ret;
548 7d37d351 Jan Kiszka
549 7d37d351 Jan Kiszka
    fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vq));
550 7d37d351 Jan Kiszka
551 7d37d351 Jan Kiszka
    if (irqfd->users == 0) {
552 7d37d351 Jan Kiszka
        ret = kvm_irqchip_add_msi_route(kvm_state, msg);
553 7d37d351 Jan Kiszka
        if (ret < 0) {
554 7d37d351 Jan Kiszka
            return ret;
555 7d37d351 Jan Kiszka
        }
556 7d37d351 Jan Kiszka
        irqfd->virq = ret;
557 7d37d351 Jan Kiszka
    }
558 7d37d351 Jan Kiszka
    irqfd->users++;
559 7d37d351 Jan Kiszka
560 7d37d351 Jan Kiszka
    ret = kvm_irqchip_add_irqfd(kvm_state, fd, irqfd->virq);
561 7d37d351 Jan Kiszka
    if (ret < 0) {
562 7d37d351 Jan Kiszka
        if (--irqfd->users == 0) {
563 7d37d351 Jan Kiszka
            kvm_irqchip_release_virq(kvm_state, irqfd->virq);
564 7d37d351 Jan Kiszka
        }
565 7d37d351 Jan Kiszka
        return ret;
566 7d37d351 Jan Kiszka
    }
567 7d37d351 Jan Kiszka
568 7d37d351 Jan Kiszka
    qemu_set_fd_handler(fd, NULL, NULL, NULL);
569 7d37d351 Jan Kiszka
570 7d37d351 Jan Kiszka
    return 0;
571 7d37d351 Jan Kiszka
}
572 7d37d351 Jan Kiszka
573 7d37d351 Jan Kiszka
static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
574 7d37d351 Jan Kiszka
                                             unsigned int queue_no,
575 7d37d351 Jan Kiszka
                                             unsigned int vector)
576 7d37d351 Jan Kiszka
{
577 7d37d351 Jan Kiszka
    VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
578 7d37d351 Jan Kiszka
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
579 7d37d351 Jan Kiszka
    int fd, ret;
580 7d37d351 Jan Kiszka
581 7d37d351 Jan Kiszka
    fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vq));
582 7d37d351 Jan Kiszka
583 7d37d351 Jan Kiszka
    ret = kvm_irqchip_remove_irqfd(kvm_state, fd, irqfd->virq);
584 7d37d351 Jan Kiszka
    assert(ret == 0);
585 7d37d351 Jan Kiszka
586 7d37d351 Jan Kiszka
    if (--irqfd->users == 0) {
587 7d37d351 Jan Kiszka
        kvm_irqchip_release_virq(kvm_state, irqfd->virq);
588 7d37d351 Jan Kiszka
    }
589 7d37d351 Jan Kiszka
590 7d37d351 Jan Kiszka
    qemu_set_fd_handler(fd, virtio_pci_guest_notifier_read, NULL, vq);
591 7d37d351 Jan Kiszka
}
592 7d37d351 Jan Kiszka
593 7d37d351 Jan Kiszka
static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector,
594 7d37d351 Jan Kiszka
                                     MSIMessage msg)
595 7d37d351 Jan Kiszka
{
596 7d37d351 Jan Kiszka
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
597 7d37d351 Jan Kiszka
    VirtIODevice *vdev = proxy->vdev;
598 7d37d351 Jan Kiszka
    int ret, queue_no;
599 7d37d351 Jan Kiszka
600 7d37d351 Jan Kiszka
    for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
601 7d37d351 Jan Kiszka
        if (!virtio_queue_get_num(vdev, queue_no)) {
602 7d37d351 Jan Kiszka
            break;
603 7d37d351 Jan Kiszka
        }
604 7d37d351 Jan Kiszka
        if (virtio_queue_vector(vdev, queue_no) != vector) {
605 7d37d351 Jan Kiszka
            continue;
606 7d37d351 Jan Kiszka
        }
607 7d37d351 Jan Kiszka
        ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector, msg);
608 7d37d351 Jan Kiszka
        if (ret < 0) {
609 7d37d351 Jan Kiszka
            goto undo;
610 7d37d351 Jan Kiszka
        }
611 7d37d351 Jan Kiszka
    }
612 7d37d351 Jan Kiszka
    return 0;
613 7d37d351 Jan Kiszka
614 7d37d351 Jan Kiszka
undo:
615 7d37d351 Jan Kiszka
    while (--queue_no >= 0) {
616 7d37d351 Jan Kiszka
        if (virtio_queue_vector(vdev, queue_no) != vector) {
617 7d37d351 Jan Kiszka
            continue;
618 7d37d351 Jan Kiszka
        }
619 7d37d351 Jan Kiszka
        kvm_virtio_pci_vq_vector_release(proxy, queue_no, vector);
620 7d37d351 Jan Kiszka
    }
621 7d37d351 Jan Kiszka
    return ret;
622 7d37d351 Jan Kiszka
}
623 7d37d351 Jan Kiszka
624 7d37d351 Jan Kiszka
static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector)
625 7d37d351 Jan Kiszka
{
626 7d37d351 Jan Kiszka
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
627 7d37d351 Jan Kiszka
    VirtIODevice *vdev = proxy->vdev;
628 7d37d351 Jan Kiszka
    int queue_no;
629 7d37d351 Jan Kiszka
630 7d37d351 Jan Kiszka
    for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
631 7d37d351 Jan Kiszka
        if (!virtio_queue_get_num(vdev, queue_no)) {
632 7d37d351 Jan Kiszka
            break;
633 7d37d351 Jan Kiszka
        }
634 7d37d351 Jan Kiszka
        if (virtio_queue_vector(vdev, queue_no) != vector) {
635 7d37d351 Jan Kiszka
            continue;
636 7d37d351 Jan Kiszka
        }
637 7d37d351 Jan Kiszka
        kvm_virtio_pci_vq_vector_release(proxy, queue_no, vector);
638 7d37d351 Jan Kiszka
    }
639 7d37d351 Jan Kiszka
}
640 7d37d351 Jan Kiszka
641 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
642 ade80dc8 Michael S. Tsirkin
{
643 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
644 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
645 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
646 ade80dc8 Michael S. Tsirkin
647 ade80dc8 Michael S. Tsirkin
    if (assign) {
648 ade80dc8 Michael S. Tsirkin
        int r = event_notifier_init(notifier, 0);
649 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
650 ade80dc8 Michael S. Tsirkin
            return r;
651 ade80dc8 Michael S. Tsirkin
        }
652 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
653 ade80dc8 Michael S. Tsirkin
                            virtio_pci_guest_notifier_read, NULL, vq);
654 ade80dc8 Michael S. Tsirkin
    } else {
655 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
656 ade80dc8 Michael S. Tsirkin
                            NULL, NULL, NULL);
657 7d37d351 Jan Kiszka
        /* Test and clear notifier before closing it,
658 7d37d351 Jan Kiszka
         * in case poll callback didn't have time to run. */
659 7d37d351 Jan Kiszka
        virtio_pci_guest_notifier_read(vq);
660 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
661 ade80dc8 Michael S. Tsirkin
    }
662 ade80dc8 Michael S. Tsirkin
663 ade80dc8 Michael S. Tsirkin
    return 0;
664 ade80dc8 Michael S. Tsirkin
}
665 ade80dc8 Michael S. Tsirkin
666 5430a28f mst@redhat.com
static bool virtio_pci_query_guest_notifiers(void *opaque)
667 5430a28f mst@redhat.com
{
668 5430a28f mst@redhat.com
    VirtIOPCIProxy *proxy = opaque;
669 5430a28f mst@redhat.com
    return msix_enabled(&proxy->pci_dev);
670 5430a28f mst@redhat.com
}
671 5430a28f mst@redhat.com
672 54dd9321 Michael S. Tsirkin
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
673 54dd9321 Michael S. Tsirkin
{
674 54dd9321 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
675 54dd9321 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
676 54dd9321 Michael S. Tsirkin
    int r, n;
677 54dd9321 Michael S. Tsirkin
678 7d37d351 Jan Kiszka
    /* Must unset vector notifier while guest notifier is still assigned */
679 7d37d351 Jan Kiszka
    if (kvm_irqchip_in_kernel() && !assign) {
680 7d37d351 Jan Kiszka
        msix_unset_vector_notifiers(&proxy->pci_dev);
681 7d37d351 Jan Kiszka
        g_free(proxy->vector_irqfd);
682 7d37d351 Jan Kiszka
        proxy->vector_irqfd = NULL;
683 7d37d351 Jan Kiszka
    }
684 7d37d351 Jan Kiszka
685 54dd9321 Michael S. Tsirkin
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
686 54dd9321 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, n)) {
687 54dd9321 Michael S. Tsirkin
            break;
688 54dd9321 Michael S. Tsirkin
        }
689 54dd9321 Michael S. Tsirkin
690 54dd9321 Michael S. Tsirkin
        r = virtio_pci_set_guest_notifier(opaque, n, assign);
691 54dd9321 Michael S. Tsirkin
        if (r < 0) {
692 54dd9321 Michael S. Tsirkin
            goto assign_error;
693 54dd9321 Michael S. Tsirkin
        }
694 54dd9321 Michael S. Tsirkin
    }
695 54dd9321 Michael S. Tsirkin
696 7d37d351 Jan Kiszka
    /* Must set vector notifier after guest notifier has been assigned */
697 7d37d351 Jan Kiszka
    if (kvm_irqchip_in_kernel() && assign) {
698 7d37d351 Jan Kiszka
        proxy->vector_irqfd =
699 7d37d351 Jan Kiszka
            g_malloc0(sizeof(*proxy->vector_irqfd) *
700 7d37d351 Jan Kiszka
                      msix_nr_vectors_allocated(&proxy->pci_dev));
701 7d37d351 Jan Kiszka
        r = msix_set_vector_notifiers(&proxy->pci_dev,
702 7d37d351 Jan Kiszka
                                      kvm_virtio_pci_vector_use,
703 7d37d351 Jan Kiszka
                                      kvm_virtio_pci_vector_release);
704 7d37d351 Jan Kiszka
        if (r < 0) {
705 7d37d351 Jan Kiszka
            goto assign_error;
706 7d37d351 Jan Kiszka
        }
707 7d37d351 Jan Kiszka
    }
708 7d37d351 Jan Kiszka
709 54dd9321 Michael S. Tsirkin
    return 0;
710 54dd9321 Michael S. Tsirkin
711 54dd9321 Michael S. Tsirkin
assign_error:
712 54dd9321 Michael S. Tsirkin
    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
713 7d37d351 Jan Kiszka
    assert(assign);
714 54dd9321 Michael S. Tsirkin
    while (--n >= 0) {
715 54dd9321 Michael S. Tsirkin
        virtio_pci_set_guest_notifier(opaque, n, !assign);
716 54dd9321 Michael S. Tsirkin
    }
717 54dd9321 Michael S. Tsirkin
    return r;
718 54dd9321 Michael S. Tsirkin
}
719 54dd9321 Michael S. Tsirkin
720 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
721 ade80dc8 Michael S. Tsirkin
{
722 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
723 25db9ebe Stefan Hajnoczi
724 25db9ebe Stefan Hajnoczi
    /* Stop using ioeventfd for virtqueue kick if the device starts using host
725 25db9ebe Stefan Hajnoczi
     * notifiers.  This makes it easy to avoid stepping on each others' toes.
726 25db9ebe Stefan Hajnoczi
     */
727 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_disabled = assign;
728 ade80dc8 Michael S. Tsirkin
    if (assign) {
729 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
730 25db9ebe Stefan Hajnoczi
    }
731 25db9ebe Stefan Hajnoczi
    /* We don't need to start here: it's not needed because backend
732 25db9ebe Stefan Hajnoczi
     * currently only stops on status change away from ok,
733 25db9ebe Stefan Hajnoczi
     * reset, vmstop and such. If we do add code to start here,
734 25db9ebe Stefan Hajnoczi
     * need to check vmstate, device state etc. */
735 25db9ebe Stefan Hajnoczi
    return virtio_pci_set_host_notifier_internal(proxy, n, assign);
736 25db9ebe Stefan Hajnoczi
}
737 25db9ebe Stefan Hajnoczi
738 25db9ebe Stefan Hajnoczi
static void virtio_pci_vmstate_change(void *opaque, bool running)
739 25db9ebe Stefan Hajnoczi
{
740 25db9ebe Stefan Hajnoczi
    VirtIOPCIProxy *proxy = opaque;
741 25db9ebe Stefan Hajnoczi
742 25db9ebe Stefan Hajnoczi
    if (running) {
743 89c473fd Michael S. Tsirkin
        /* Try to find out if the guest has bus master disabled, but is
744 89c473fd Michael S. Tsirkin
           in ready state. Then we have a buggy guest OS. */
745 89c473fd Michael S. Tsirkin
        if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
746 89c473fd Michael S. Tsirkin
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
747 89c473fd Michael S. Tsirkin
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
748 89c473fd Michael S. Tsirkin
        }
749 25db9ebe Stefan Hajnoczi
        virtio_pci_start_ioeventfd(proxy);
750 ade80dc8 Michael S. Tsirkin
    } else {
751 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
752 ade80dc8 Michael S. Tsirkin
    }
753 ade80dc8 Michael S. Tsirkin
}
754 ade80dc8 Michael S. Tsirkin
755 53c25cea Paul Brook
static const VirtIOBindings virtio_pci_bindings = {
756 ff24bd58 Michael S. Tsirkin
    .notify = virtio_pci_notify,
757 ff24bd58 Michael S. Tsirkin
    .save_config = virtio_pci_save_config,
758 ff24bd58 Michael S. Tsirkin
    .load_config = virtio_pci_load_config,
759 ff24bd58 Michael S. Tsirkin
    .save_queue = virtio_pci_save_queue,
760 ff24bd58 Michael S. Tsirkin
    .load_queue = virtio_pci_load_queue,
761 6d74ca5a Michael S. Tsirkin
    .get_features = virtio_pci_get_features,
762 5430a28f mst@redhat.com
    .query_guest_notifiers = virtio_pci_query_guest_notifiers,
763 ade80dc8 Michael S. Tsirkin
    .set_host_notifier = virtio_pci_set_host_notifier,
764 54dd9321 Michael S. Tsirkin
    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
765 25db9ebe Stefan Hajnoczi
    .vmstate_change = virtio_pci_vmstate_change,
766 53c25cea Paul Brook
};
767 53c25cea Paul Brook
768 befeac45 Michael S. Tsirkin
void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
769 53c25cea Paul Brook
{
770 53c25cea Paul Brook
    uint8_t *config;
771 53c25cea Paul Brook
    uint32_t size;
772 53c25cea Paul Brook
773 53c25cea Paul Brook
    proxy->vdev = vdev;
774 53c25cea Paul Brook
775 53c25cea Paul Brook
    config = proxy->pci_dev.config;
776 53c25cea Paul Brook
777 e75ccf2c Isaku Yamahata
    if (proxy->class_code) {
778 e75ccf2c Isaku Yamahata
        pci_config_set_class(config, proxy->class_code);
779 e75ccf2c Isaku Yamahata
    }
780 ad3d11e6 Hui Kai Ran
    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
781 ad3d11e6 Hui Kai Ran
                 pci_get_word(config + PCI_VENDOR_ID));
782 ad3d11e6 Hui Kai Ran
    pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
783 ad3d11e6 Hui Kai Ran
    config[PCI_INTERRUPT_PIN] = 1;
784 53c25cea Paul Brook
785 95524ae8 Avi Kivity
    memory_region_init(&proxy->msix_bar, "virtio-msix", 4096);
786 95524ae8 Avi Kivity
    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors,
787 95524ae8 Avi Kivity
                                     &proxy->msix_bar, 1, 0)) {
788 e824b2cc Avi Kivity
        pci_register_bar(&proxy->pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
789 e824b2cc Avi Kivity
                         &proxy->msix_bar);
790 aba800a3 Michael S. Tsirkin
    } else
791 aba800a3 Michael S. Tsirkin
        vdev->nvectors = 0;
792 aba800a3 Michael S. Tsirkin
793 ed757e14 Yan Vugenfirer
    proxy->pci_dev.config_write = virtio_write_config;
794 ed757e14 Yan Vugenfirer
795 aba800a3 Michael S. Tsirkin
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
796 53c25cea Paul Brook
    if (size & (size-1))
797 53c25cea Paul Brook
        size = 1 << qemu_fls(size);
798 53c25cea Paul Brook
799 da146d0a Avi Kivity
    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
800 da146d0a Avi Kivity
                          "virtio-pci", size);
801 e824b2cc Avi Kivity
    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
802 e824b2cc Avi Kivity
                     &proxy->bar);
803 53c25cea Paul Brook
804 25db9ebe Stefan Hajnoczi
    if (!kvm_has_many_ioeventfds()) {
805 25db9ebe Stefan Hajnoczi
        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
806 25db9ebe Stefan Hajnoczi
    }
807 25db9ebe Stefan Hajnoczi
808 53c25cea Paul Brook
    virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
809 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
810 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
811 8172539d Michael S. Tsirkin
    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
812 53c25cea Paul Brook
}
813 53c25cea Paul Brook
814 81a322d4 Gerd Hoffmann
static int virtio_blk_init_pci(PCIDevice *pci_dev)
815 53c25cea Paul Brook
{
816 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
817 53c25cea Paul Brook
    VirtIODevice *vdev;
818 53c25cea Paul Brook
819 ab73ff29 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
820 ab73ff29 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_STORAGE_OTHER)
821 ab73ff29 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_STORAGE_SCSI;
822 53c25cea Paul Brook
823 12c5674b Paolo Bonzini
    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->blk);
824 ac0c14d7 Markus Armbruster
    if (!vdev) {
825 ac0c14d7 Markus Armbruster
        return -1;
826 ac0c14d7 Markus Armbruster
    }
827 177539e0 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
828 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
829 177539e0 Gerd Hoffmann
    /* make the actual value visible */
830 177539e0 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
831 81a322d4 Gerd Hoffmann
    return 0;
832 21d58b57 Mark McLoughlin
}
833 21d58b57 Mark McLoughlin
834 0f457d91 Michael S. Tsirkin
static int virtio_exit_pci(PCIDevice *pci_dev)
835 0f457d91 Michael S. Tsirkin
{
836 da146d0a Avi Kivity
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
837 95524ae8 Avi Kivity
    int r;
838 da146d0a Avi Kivity
839 da146d0a Avi Kivity
    memory_region_destroy(&proxy->bar);
840 95524ae8 Avi Kivity
    r = msix_uninit(pci_dev, &proxy->msix_bar);
841 95524ae8 Avi Kivity
    memory_region_destroy(&proxy->msix_bar);
842 95524ae8 Avi Kivity
    return r;
843 0f457d91 Michael S. Tsirkin
}
844 0f457d91 Michael S. Tsirkin
845 56a14938 Gerd Hoffmann
static int virtio_blk_exit_pci(PCIDevice *pci_dev)
846 56a14938 Gerd Hoffmann
{
847 56a14938 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
848 56a14938 Gerd Hoffmann
849 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
850 9d0d3138 Alex Williamson
    virtio_blk_exit(proxy->vdev);
851 0f457d91 Michael S. Tsirkin
    return virtio_exit_pci(pci_dev);
852 56a14938 Gerd Hoffmann
}
853 56a14938 Gerd Hoffmann
854 98b19252 Amit Shah
static int virtio_serial_init_pci(PCIDevice *pci_dev)
855 21d58b57 Mark McLoughlin
{
856 d6beee99 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
857 85c2c735 Mark McLoughlin
    VirtIODevice *vdev;
858 85c2c735 Mark McLoughlin
859 d6beee99 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
860 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
861 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
862 d6beee99 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
863 d6beee99 Gerd Hoffmann
864 6b331efb Amit Shah
    vdev = virtio_serial_init(&pci_dev->qdev, &proxy->serial);
865 25fe3654 Amit Shah
    if (!vdev) {
866 25fe3654 Amit Shah
        return -1;
867 25fe3654 Amit Shah
    }
868 573fb60c Amit Shah
    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
869 6b331efb Amit Shah
                                        ? proxy->serial.max_virtserial_ports + 1
870 573fb60c Amit Shah
                                        : proxy->nvectors;
871 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
872 a1829205 Amit Shah
    proxy->nvectors = vdev->nvectors;
873 81a322d4 Gerd Hoffmann
    return 0;
874 53c25cea Paul Brook
}
875 53c25cea Paul Brook
876 8b53a865 Amit Shah
static int virtio_serial_exit_pci(PCIDevice *pci_dev)
877 8b53a865 Amit Shah
{
878 8b53a865 Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
879 8b53a865 Amit Shah
880 32059220 Amit Shah
    virtio_pci_stop_ioeventfd(proxy);
881 8b53a865 Amit Shah
    virtio_serial_exit(proxy->vdev);
882 8b53a865 Amit Shah
    return virtio_exit_pci(pci_dev);
883 8b53a865 Amit Shah
}
884 8b53a865 Amit Shah
885 81a322d4 Gerd Hoffmann
static int virtio_net_init_pci(PCIDevice *pci_dev)
886 53c25cea Paul Brook
{
887 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
888 53c25cea Paul Brook
    VirtIODevice *vdev;
889 53c25cea Paul Brook
890 f0c07c7c Alex Williamson
    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
891 a1e0fea5 Gerd Hoffmann
892 97b15621 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
893 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
894 a1e0fea5 Gerd Hoffmann
895 a1e0fea5 Gerd Hoffmann
    /* make the actual value visible */
896 a1e0fea5 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
897 81a322d4 Gerd Hoffmann
    return 0;
898 53c25cea Paul Brook
}
899 53c25cea Paul Brook
900 97b15621 Gerd Hoffmann
static int virtio_net_exit_pci(PCIDevice *pci_dev)
901 97b15621 Gerd Hoffmann
{
902 97b15621 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
903 97b15621 Gerd Hoffmann
904 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
905 97b15621 Gerd Hoffmann
    virtio_net_exit(proxy->vdev);
906 97b15621 Gerd Hoffmann
    return virtio_exit_pci(pci_dev);
907 97b15621 Gerd Hoffmann
}
908 97b15621 Gerd Hoffmann
909 81a322d4 Gerd Hoffmann
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
910 53c25cea Paul Brook
{
911 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
912 53c25cea Paul Brook
    VirtIODevice *vdev;
913 53c25cea Paul Brook
914 2ba1d381 David Gibson
    if (proxy->class_code != PCI_CLASS_OTHERS &&
915 2ba1d381 David Gibson
        proxy->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
916 2ba1d381 David Gibson
        proxy->class_code = PCI_CLASS_OTHERS;
917 2ba1d381 David Gibson
    }
918 2ba1d381 David Gibson
919 53c25cea Paul Brook
    vdev = virtio_balloon_init(&pci_dev->qdev);
920 f76f6655 Amit Shah
    if (!vdev) {
921 f76f6655 Amit Shah
        return -1;
922 f76f6655 Amit Shah
    }
923 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
924 81a322d4 Gerd Hoffmann
    return 0;
925 53c25cea Paul Brook
}
926 53c25cea Paul Brook
927 855d7e25 Amit Shah
static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
928 855d7e25 Amit Shah
{
929 855d7e25 Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
930 855d7e25 Amit Shah
931 855d7e25 Amit Shah
    virtio_pci_stop_ioeventfd(proxy);
932 855d7e25 Amit Shah
    virtio_balloon_exit(proxy->vdev);
933 855d7e25 Amit Shah
    return virtio_exit_pci(pci_dev);
934 855d7e25 Amit Shah
}
935 855d7e25 Amit Shah
936 40021f08 Anthony Liguori
static Property virtio_blk_properties[] = {
937 40021f08 Anthony Liguori
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
938 12c5674b Paolo Bonzini
    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
939 12c5674b Paolo Bonzini
    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, blk.serial),
940 a6c5c84a Paolo Bonzini
#ifdef __linux__
941 a6c5c84a Paolo Bonzini
    DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
942 a6c5c84a Paolo Bonzini
#endif
943 40021f08 Anthony Liguori
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
944 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
945 40021f08 Anthony Liguori
    DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
946 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
947 e855761c Anthony Liguori
};
948 e855761c Anthony Liguori
949 40021f08 Anthony Liguori
static void virtio_blk_class_init(ObjectClass *klass, void *data)
950 40021f08 Anthony Liguori
{
951 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
952 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
953 40021f08 Anthony Liguori
954 40021f08 Anthony Liguori
    k->init = virtio_blk_init_pci;
955 40021f08 Anthony Liguori
    k->exit = virtio_blk_exit_pci;
956 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
957 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
958 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
959 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_STORAGE_SCSI;
960 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
961 39bffca2 Anthony Liguori
    dc->props = virtio_blk_properties;
962 40021f08 Anthony Liguori
}
963 40021f08 Anthony Liguori
964 39bffca2 Anthony Liguori
static TypeInfo virtio_blk_info = {
965 39bffca2 Anthony Liguori
    .name          = "virtio-blk-pci",
966 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
967 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
968 39bffca2 Anthony Liguori
    .class_init    = virtio_blk_class_init,
969 40021f08 Anthony Liguori
};
970 40021f08 Anthony Liguori
971 40021f08 Anthony Liguori
static Property virtio_net_properties[] = {
972 40021f08 Anthony Liguori
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
973 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
974 40021f08 Anthony Liguori
    DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
975 40021f08 Anthony Liguori
    DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
976 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy, net.txtimer, TX_TIMER_INTERVAL),
977 40021f08 Anthony Liguori
    DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy, net.txburst, TX_BURST),
978 40021f08 Anthony Liguori
    DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
979 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
980 40021f08 Anthony Liguori
};
981 40021f08 Anthony Liguori
982 40021f08 Anthony Liguori
static void virtio_net_class_init(ObjectClass *klass, void *data)
983 40021f08 Anthony Liguori
{
984 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
985 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
986 40021f08 Anthony Liguori
987 40021f08 Anthony Liguori
    k->init = virtio_net_init_pci;
988 40021f08 Anthony Liguori
    k->exit = virtio_net_exit_pci;
989 40021f08 Anthony Liguori
    k->romfile = "pxe-virtio.rom";
990 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
991 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
992 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
993 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
994 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
995 39bffca2 Anthony Liguori
    dc->props = virtio_net_properties;
996 40021f08 Anthony Liguori
}
997 40021f08 Anthony Liguori
998 39bffca2 Anthony Liguori
static TypeInfo virtio_net_info = {
999 39bffca2 Anthony Liguori
    .name          = "virtio-net-pci",
1000 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1001 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
1002 39bffca2 Anthony Liguori
    .class_init    = virtio_net_class_init,
1003 e855761c Anthony Liguori
};
1004 e855761c Anthony Liguori
1005 40021f08 Anthony Liguori
static Property virtio_serial_properties[] = {
1006 40021f08 Anthony Liguori
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
1007 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
1008 40021f08 Anthony Liguori
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
1009 40021f08 Anthony Liguori
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
1010 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31),
1011 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1012 e855761c Anthony Liguori
};
1013 e855761c Anthony Liguori
1014 40021f08 Anthony Liguori
static void virtio_serial_class_init(ObjectClass *klass, void *data)
1015 40021f08 Anthony Liguori
{
1016 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1017 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1018 40021f08 Anthony Liguori
1019 40021f08 Anthony Liguori
    k->init = virtio_serial_init_pci;
1020 40021f08 Anthony Liguori
    k->exit = virtio_serial_exit_pci;
1021 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1022 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
1023 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
1024 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
1025 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
1026 39bffca2 Anthony Liguori
    dc->props = virtio_serial_properties;
1027 40021f08 Anthony Liguori
}
1028 40021f08 Anthony Liguori
1029 39bffca2 Anthony Liguori
static TypeInfo virtio_serial_info = {
1030 39bffca2 Anthony Liguori
    .name          = "virtio-serial-pci",
1031 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1032 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
1033 39bffca2 Anthony Liguori
    .class_init    = virtio_serial_class_init,
1034 40021f08 Anthony Liguori
};
1035 40021f08 Anthony Liguori
1036 40021f08 Anthony Liguori
static Property virtio_balloon_properties[] = {
1037 40021f08 Anthony Liguori
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
1038 2ba1d381 David Gibson
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
1039 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1040 40021f08 Anthony Liguori
};
1041 40021f08 Anthony Liguori
1042 40021f08 Anthony Liguori
static void virtio_balloon_class_init(ObjectClass *klass, void *data)
1043 40021f08 Anthony Liguori
{
1044 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1045 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1046 40021f08 Anthony Liguori
1047 40021f08 Anthony Liguori
    k->init = virtio_balloon_init_pci;
1048 40021f08 Anthony Liguori
    k->exit = virtio_balloon_exit_pci;
1049 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1050 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
1051 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
1052 2ba1d381 David Gibson
    k->class_id = PCI_CLASS_OTHERS;
1053 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
1054 39bffca2 Anthony Liguori
    dc->props = virtio_balloon_properties;
1055 40021f08 Anthony Liguori
}
1056 40021f08 Anthony Liguori
1057 39bffca2 Anthony Liguori
static TypeInfo virtio_balloon_info = {
1058 39bffca2 Anthony Liguori
    .name          = "virtio-balloon-pci",
1059 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
1060 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
1061 39bffca2 Anthony Liguori
    .class_init    = virtio_balloon_class_init,
1062 0aab0d3a Gerd Hoffmann
};
1063 0aab0d3a Gerd Hoffmann
1064 973abc7f Stefan Hajnoczi
static int virtio_scsi_init_pci(PCIDevice *pci_dev)
1065 973abc7f Stefan Hajnoczi
{
1066 973abc7f Stefan Hajnoczi
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
1067 973abc7f Stefan Hajnoczi
    VirtIODevice *vdev;
1068 973abc7f Stefan Hajnoczi
1069 973abc7f Stefan Hajnoczi
    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
1070 973abc7f Stefan Hajnoczi
    if (!vdev) {
1071 973abc7f Stefan Hajnoczi
        return -EINVAL;
1072 973abc7f Stefan Hajnoczi
    }
1073 973abc7f Stefan Hajnoczi
1074 973abc7f Stefan Hajnoczi
    vdev->nvectors = proxy->nvectors;
1075 973abc7f Stefan Hajnoczi
    virtio_init_pci(proxy, vdev);
1076 973abc7f Stefan Hajnoczi
1077 973abc7f Stefan Hajnoczi
    /* make the actual value visible */
1078 973abc7f Stefan Hajnoczi
    proxy->nvectors = vdev->nvectors;
1079 973abc7f Stefan Hajnoczi
    return 0;
1080 973abc7f Stefan Hajnoczi
}
1081 973abc7f Stefan Hajnoczi
1082 973abc7f Stefan Hajnoczi
static int virtio_scsi_exit_pci(PCIDevice *pci_dev)
1083 973abc7f Stefan Hajnoczi
{
1084 973abc7f Stefan Hajnoczi
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
1085 973abc7f Stefan Hajnoczi
1086 973abc7f Stefan Hajnoczi
    virtio_scsi_exit(proxy->vdev);
1087 973abc7f Stefan Hajnoczi
    return virtio_exit_pci(pci_dev);
1088 973abc7f Stefan Hajnoczi
}
1089 973abc7f Stefan Hajnoczi
1090 973abc7f Stefan Hajnoczi
static Property virtio_scsi_properties[] = {
1091 973abc7f Stefan Hajnoczi
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
1092 973abc7f Stefan Hajnoczi
    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
1093 973abc7f Stefan Hajnoczi
    DEFINE_PROP_END_OF_LIST(),
1094 973abc7f Stefan Hajnoczi
};
1095 973abc7f Stefan Hajnoczi
1096 973abc7f Stefan Hajnoczi
static void virtio_scsi_class_init(ObjectClass *klass, void *data)
1097 973abc7f Stefan Hajnoczi
{
1098 973abc7f Stefan Hajnoczi
    DeviceClass *dc = DEVICE_CLASS(klass);
1099 973abc7f Stefan Hajnoczi
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1100 973abc7f Stefan Hajnoczi
1101 973abc7f Stefan Hajnoczi
    k->init = virtio_scsi_init_pci;
1102 973abc7f Stefan Hajnoczi
    k->exit = virtio_scsi_exit_pci;
1103 973abc7f Stefan Hajnoczi
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1104 973abc7f Stefan Hajnoczi
    k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
1105 973abc7f Stefan Hajnoczi
    k->revision = 0x00;
1106 973abc7f Stefan Hajnoczi
    k->class_id = PCI_CLASS_STORAGE_SCSI;
1107 973abc7f Stefan Hajnoczi
    dc->reset = virtio_pci_reset;
1108 973abc7f Stefan Hajnoczi
    dc->props = virtio_scsi_properties;
1109 973abc7f Stefan Hajnoczi
}
1110 973abc7f Stefan Hajnoczi
1111 973abc7f Stefan Hajnoczi
static TypeInfo virtio_scsi_info = {
1112 973abc7f Stefan Hajnoczi
    .name          = "virtio-scsi-pci",
1113 973abc7f Stefan Hajnoczi
    .parent        = TYPE_PCI_DEVICE,
1114 973abc7f Stefan Hajnoczi
    .instance_size = sizeof(VirtIOPCIProxy),
1115 973abc7f Stefan Hajnoczi
    .class_init    = virtio_scsi_class_init,
1116 973abc7f Stefan Hajnoczi
};
1117 973abc7f Stefan Hajnoczi
1118 83f7d43a Andreas Färber
static void virtio_pci_register_types(void)
1119 53c25cea Paul Brook
{
1120 39bffca2 Anthony Liguori
    type_register_static(&virtio_blk_info);
1121 39bffca2 Anthony Liguori
    type_register_static(&virtio_net_info);
1122 39bffca2 Anthony Liguori
    type_register_static(&virtio_serial_info);
1123 39bffca2 Anthony Liguori
    type_register_static(&virtio_balloon_info);
1124 973abc7f Stefan Hajnoczi
    type_register_static(&virtio_scsi_info);
1125 53c25cea Paul Brook
}
1126 53c25cea Paul Brook
1127 83f7d43a Andreas Färber
type_init(virtio_pci_register_types)