Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ f5654039

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