Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ 4b8f1c88

History | View | Annotate | Download (30.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 aba800a3 Michael S. Tsirkin
#include "msix.h"
28 a1e0fea5 Gerd Hoffmann
#include "net.h"
29 97b15621 Gerd Hoffmann
#include "loader.h"
30 ade80dc8 Michael S. Tsirkin
#include "kvm.h"
31 2446333c Blue Swirl
#include "blockdev.h"
32 9fe1ebeb Aneesh Kumar K.V
#include "virtio-pci.h"
33 1129714f Michael S. Tsirkin
#include "range.h"
34 53c25cea Paul Brook
35 53c25cea Paul Brook
/* from Linux's linux/virtio_pci.h */
36 53c25cea Paul Brook
37 53c25cea Paul Brook
/* A 32-bit r/o bitmask of the features supported by the host */
38 53c25cea Paul Brook
#define VIRTIO_PCI_HOST_FEATURES        0
39 53c25cea Paul Brook
40 53c25cea Paul Brook
/* A 32-bit r/w bitmask of features activated by the guest */
41 53c25cea Paul Brook
#define VIRTIO_PCI_GUEST_FEATURES       4
42 53c25cea Paul Brook
43 53c25cea Paul Brook
/* A 32-bit r/w PFN for the currently selected queue */
44 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_PFN            8
45 53c25cea Paul Brook
46 53c25cea Paul Brook
/* A 16-bit r/o queue size for the currently selected queue */
47 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NUM            12
48 53c25cea Paul Brook
49 53c25cea Paul Brook
/* A 16-bit r/w queue selector */
50 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_SEL            14
51 53c25cea Paul Brook
52 53c25cea Paul Brook
/* A 16-bit r/w queue notifier */
53 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NOTIFY         16
54 53c25cea Paul Brook
55 53c25cea Paul Brook
/* An 8-bit device status register.  */
56 53c25cea Paul Brook
#define VIRTIO_PCI_STATUS               18
57 53c25cea Paul Brook
58 53c25cea Paul Brook
/* An 8-bit r/o interrupt status register.  Reading the value will return the
59 53c25cea Paul Brook
 * current contents of the ISR and will also clear it.  This is effectively
60 53c25cea Paul Brook
 * a read-and-acknowledge. */
61 53c25cea Paul Brook
#define VIRTIO_PCI_ISR                  19
62 53c25cea Paul Brook
63 aba800a3 Michael S. Tsirkin
/* MSI-X registers: only enabled if MSI-X is enabled. */
64 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for configuration changes. */
65 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_CONFIG_VECTOR        20
66 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for selected queue notifications. */
67 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_QUEUE_VECTOR         22
68 aba800a3 Michael S. Tsirkin
69 aba800a3 Michael S. Tsirkin
/* Config space size */
70 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_NOMSI         20
71 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_MSI           24
72 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
73 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
74 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
75 aba800a3 Michael S. Tsirkin
76 aba800a3 Michael S. Tsirkin
/* The remaining space is defined by each driver as the per-driver
77 aba800a3 Michael S. Tsirkin
 * configuration space */
78 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
79 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
80 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
81 53c25cea Paul Brook
82 53c25cea Paul Brook
/* How many bits to shift physical queue address written to QUEUE_PFN.
83 53c25cea Paul Brook
 * 12 is historical, and due to x86 page size. */
84 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
85 53c25cea Paul Brook
86 3dbca8e6 Stefan Hajnoczi
/* Flags track per-device state like workarounds for quirks in older guests. */
87 3dbca8e6 Stefan Hajnoczi
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG  (1 << 0)
88 c81131db Alexander Graf
89 53c25cea Paul Brook
/* QEMU doesn't strictly need write barriers since everything runs in
90 53c25cea Paul Brook
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
91 53c25cea Paul Brook
 * KVM or if kqemu gets SMP support.
92 53c25cea Paul Brook
 */
93 53c25cea Paul Brook
#define wmb() do { } while (0)
94 53c25cea Paul Brook
95 82afa586 Benjamin Herrenschmidt
/* HACK for virtio to determine if it's running a big endian guest */
96 82afa586 Benjamin Herrenschmidt
bool virtio_is_big_endian(void);
97 82afa586 Benjamin Herrenschmidt
98 53c25cea Paul Brook
/* virtio device */
99 53c25cea Paul Brook
100 7055e687 Michael S. Tsirkin
static void virtio_pci_notify(void *opaque, uint16_t vector)
101 53c25cea Paul Brook
{
102 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
103 aba800a3 Michael S. Tsirkin
    if (msix_enabled(&proxy->pci_dev))
104 aba800a3 Michael S. Tsirkin
        msix_notify(&proxy->pci_dev, vector);
105 aba800a3 Michael S. Tsirkin
    else
106 aba800a3 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
107 53c25cea Paul Brook
}
108 53c25cea Paul Brook
109 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_config(void * opaque, QEMUFile *f)
110 ff24bd58 Michael S. Tsirkin
{
111 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
112 ff24bd58 Michael S. Tsirkin
    pci_device_save(&proxy->pci_dev, f);
113 ff24bd58 Michael S. Tsirkin
    msix_save(&proxy->pci_dev, f);
114 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
115 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, proxy->vdev->config_vector);
116 ff24bd58 Michael S. Tsirkin
}
117 ff24bd58 Michael S. Tsirkin
118 ff24bd58 Michael S. Tsirkin
static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f)
119 ff24bd58 Michael S. Tsirkin
{
120 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
121 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
122 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
123 ff24bd58 Michael S. Tsirkin
}
124 ff24bd58 Michael S. Tsirkin
125 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_config(void * opaque, QEMUFile *f)
126 ff24bd58 Michael S. Tsirkin
{
127 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
128 ff24bd58 Michael S. Tsirkin
    int ret;
129 ff24bd58 Michael S. Tsirkin
    ret = pci_device_load(&proxy->pci_dev, f);
130 e6da7680 Michael S. Tsirkin
    if (ret) {
131 ff24bd58 Michael S. Tsirkin
        return ret;
132 e6da7680 Michael S. Tsirkin
    }
133 ff24bd58 Michael S. Tsirkin
    msix_load(&proxy->pci_dev, f);
134 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
135 ff24bd58 Michael S. Tsirkin
        qemu_get_be16s(f, &proxy->vdev->config_vector);
136 e6da7680 Michael S. Tsirkin
    } else {
137 e6da7680 Michael S. Tsirkin
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
138 e6da7680 Michael S. Tsirkin
    }
139 e6da7680 Michael S. Tsirkin
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
140 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
141 e6da7680 Michael S. Tsirkin
    }
142 ff24bd58 Michael S. Tsirkin
    return 0;
143 ff24bd58 Michael S. Tsirkin
}
144 ff24bd58 Michael S. Tsirkin
145 ff24bd58 Michael S. Tsirkin
static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
146 ff24bd58 Michael S. Tsirkin
{
147 ff24bd58 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
148 ff24bd58 Michael S. Tsirkin
    uint16_t vector;
149 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
150 e6da7680 Michael S. Tsirkin
        qemu_get_be16s(f, &vector);
151 e6da7680 Michael S. Tsirkin
    } else {
152 e6da7680 Michael S. Tsirkin
        vector = VIRTIO_NO_VECTOR;
153 e6da7680 Michael S. Tsirkin
    }
154 ff24bd58 Michael S. Tsirkin
    virtio_queue_set_vector(proxy->vdev, n, vector);
155 e6da7680 Michael S. Tsirkin
    if (vector != VIRTIO_NO_VECTOR) {
156 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, vector);
157 e6da7680 Michael S. Tsirkin
    }
158 ff24bd58 Michael S. Tsirkin
    return 0;
159 ff24bd58 Michael S. Tsirkin
}
160 ff24bd58 Michael S. Tsirkin
161 25db9ebe Stefan Hajnoczi
static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
162 25db9ebe Stefan Hajnoczi
                                                 int n, bool assign)
163 25db9ebe Stefan Hajnoczi
{
164 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
165 25db9ebe Stefan Hajnoczi
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
166 da146d0a Avi Kivity
    int r = 0;
167 da146d0a Avi Kivity
168 25db9ebe Stefan Hajnoczi
    if (assign) {
169 25db9ebe Stefan Hajnoczi
        r = event_notifier_init(notifier, 1);
170 25db9ebe Stefan Hajnoczi
        if (r < 0) {
171 b36e3914 Michael S. Tsirkin
            error_report("%s: unable to init event notifier: %d",
172 b36e3914 Michael S. Tsirkin
                         __func__, r);
173 25db9ebe Stefan Hajnoczi
            return r;
174 25db9ebe Stefan Hajnoczi
        }
175 da146d0a Avi Kivity
        memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
176 da146d0a Avi Kivity
                                  true, n, event_notifier_get_fd(notifier));
177 25db9ebe Stefan Hajnoczi
    } else {
178 da146d0a Avi Kivity
        memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
179 da146d0a Avi Kivity
                                  true, n, event_notifier_get_fd(notifier));
180 25db9ebe Stefan Hajnoczi
        /* Handle the race condition where the guest kicked and we deassigned
181 25db9ebe Stefan Hajnoczi
         * before we got around to handling the kick.
182 25db9ebe Stefan Hajnoczi
         */
183 25db9ebe Stefan Hajnoczi
        if (event_notifier_test_and_clear(notifier)) {
184 25db9ebe Stefan Hajnoczi
            virtio_queue_notify_vq(vq);
185 25db9ebe Stefan Hajnoczi
        }
186 25db9ebe Stefan Hajnoczi
187 25db9ebe Stefan Hajnoczi
        event_notifier_cleanup(notifier);
188 25db9ebe Stefan Hajnoczi
    }
189 25db9ebe Stefan Hajnoczi
    return r;
190 25db9ebe Stefan Hajnoczi
}
191 25db9ebe Stefan Hajnoczi
192 25db9ebe Stefan Hajnoczi
static void virtio_pci_host_notifier_read(void *opaque)
193 25db9ebe Stefan Hajnoczi
{
194 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = opaque;
195 25db9ebe Stefan Hajnoczi
    EventNotifier *n = virtio_queue_get_host_notifier(vq);
196 25db9ebe Stefan Hajnoczi
    if (event_notifier_test_and_clear(n)) {
197 25db9ebe Stefan Hajnoczi
        virtio_queue_notify_vq(vq);
198 25db9ebe Stefan Hajnoczi
    }
199 25db9ebe Stefan Hajnoczi
}
200 25db9ebe Stefan Hajnoczi
201 25db9ebe Stefan Hajnoczi
static void virtio_pci_set_host_notifier_fd_handler(VirtIOPCIProxy *proxy,
202 25db9ebe Stefan Hajnoczi
                                                    int n, bool assign)
203 25db9ebe Stefan Hajnoczi
{
204 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
205 25db9ebe Stefan Hajnoczi
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
206 25db9ebe Stefan Hajnoczi
    if (assign) {
207 25db9ebe Stefan Hajnoczi
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
208 25db9ebe Stefan Hajnoczi
                            virtio_pci_host_notifier_read, NULL, vq);
209 25db9ebe Stefan Hajnoczi
    } else {
210 25db9ebe Stefan Hajnoczi
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
211 25db9ebe Stefan Hajnoczi
                            NULL, NULL, NULL);
212 25db9ebe Stefan Hajnoczi
    }
213 25db9ebe Stefan Hajnoczi
}
214 25db9ebe Stefan Hajnoczi
215 b36e3914 Michael S. Tsirkin
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
216 25db9ebe Stefan Hajnoczi
{
217 25db9ebe Stefan Hajnoczi
    int n, r;
218 25db9ebe Stefan Hajnoczi
219 25db9ebe Stefan Hajnoczi
    if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
220 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_disabled ||
221 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_started) {
222 b36e3914 Michael S. Tsirkin
        return;
223 25db9ebe Stefan Hajnoczi
    }
224 25db9ebe Stefan Hajnoczi
225 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
226 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
227 25db9ebe Stefan Hajnoczi
            continue;
228 25db9ebe Stefan Hajnoczi
        }
229 25db9ebe Stefan Hajnoczi
230 25db9ebe Stefan Hajnoczi
        r = virtio_pci_set_host_notifier_internal(proxy, n, true);
231 25db9ebe Stefan Hajnoczi
        if (r < 0) {
232 25db9ebe Stefan Hajnoczi
            goto assign_error;
233 25db9ebe Stefan Hajnoczi
        }
234 25db9ebe Stefan Hajnoczi
235 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, true);
236 25db9ebe Stefan Hajnoczi
    }
237 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = true;
238 b36e3914 Michael S. Tsirkin
    return;
239 25db9ebe Stefan Hajnoczi
240 25db9ebe Stefan Hajnoczi
assign_error:
241 25db9ebe Stefan Hajnoczi
    while (--n >= 0) {
242 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
243 25db9ebe Stefan Hajnoczi
            continue;
244 25db9ebe Stefan Hajnoczi
        }
245 25db9ebe Stefan Hajnoczi
246 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
247 b36e3914 Michael S. Tsirkin
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
248 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
249 25db9ebe Stefan Hajnoczi
    }
250 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
251 b36e3914 Michael S. Tsirkin
    error_report("%s: failed. Fallback to a userspace (slower).", __func__);
252 25db9ebe Stefan Hajnoczi
}
253 25db9ebe Stefan Hajnoczi
254 b36e3914 Michael S. Tsirkin
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
255 25db9ebe Stefan Hajnoczi
{
256 b36e3914 Michael S. Tsirkin
    int r;
257 25db9ebe Stefan Hajnoczi
    int n;
258 25db9ebe Stefan Hajnoczi
259 25db9ebe Stefan Hajnoczi
    if (!proxy->ioeventfd_started) {
260 b36e3914 Michael S. Tsirkin
        return;
261 25db9ebe Stefan Hajnoczi
    }
262 25db9ebe Stefan Hajnoczi
263 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
264 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
265 25db9ebe Stefan Hajnoczi
            continue;
266 25db9ebe Stefan Hajnoczi
        }
267 25db9ebe Stefan Hajnoczi
268 25db9ebe Stefan Hajnoczi
        virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
269 b36e3914 Michael S. Tsirkin
        r = virtio_pci_set_host_notifier_internal(proxy, n, false);
270 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
271 25db9ebe Stefan Hajnoczi
    }
272 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
273 25db9ebe Stefan Hajnoczi
}
274 25db9ebe Stefan Hajnoczi
275 8798d6c9 Aneesh Kumar K.V
void virtio_pci_reset(DeviceState *d)
276 7055e687 Michael S. Tsirkin
{
277 e489030d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
278 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
279 7055e687 Michael S. Tsirkin
    virtio_reset(proxy->vdev);
280 aba800a3 Michael S. Tsirkin
    msix_reset(&proxy->pci_dev);
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 da146d0a Avi Kivity
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 ed757e14 Yan Vugenfirer
524 85352471 Michael S. Tsirkin
    msix_write_config(pci_dev, address, val, len);
525 53c25cea Paul Brook
}
526 53c25cea Paul Brook
527 6d74ca5a Michael S. Tsirkin
static unsigned virtio_pci_get_features(void *opaque)
528 6d74ca5a Michael S. Tsirkin
{
529 8172539d Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
530 8172539d Michael S. Tsirkin
    return proxy->host_features;
531 6d74ca5a Michael S. Tsirkin
}
532 6d74ca5a Michael S. Tsirkin
533 ade80dc8 Michael S. Tsirkin
static void virtio_pci_guest_notifier_read(void *opaque)
534 ade80dc8 Michael S. Tsirkin
{
535 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = opaque;
536 ade80dc8 Michael S. Tsirkin
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
537 ade80dc8 Michael S. Tsirkin
    if (event_notifier_test_and_clear(n)) {
538 ade80dc8 Michael S. Tsirkin
        virtio_irq(vq);
539 ade80dc8 Michael S. Tsirkin
    }
540 ade80dc8 Michael S. Tsirkin
}
541 ade80dc8 Michael S. Tsirkin
542 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
543 ade80dc8 Michael S. Tsirkin
{
544 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
545 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
546 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
547 ade80dc8 Michael S. Tsirkin
548 ade80dc8 Michael S. Tsirkin
    if (assign) {
549 ade80dc8 Michael S. Tsirkin
        int r = event_notifier_init(notifier, 0);
550 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
551 ade80dc8 Michael S. Tsirkin
            return r;
552 ade80dc8 Michael S. Tsirkin
        }
553 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
554 ade80dc8 Michael S. Tsirkin
                            virtio_pci_guest_notifier_read, NULL, vq);
555 ade80dc8 Michael S. Tsirkin
    } else {
556 ade80dc8 Michael S. Tsirkin
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
557 ade80dc8 Michael S. Tsirkin
                            NULL, NULL, NULL);
558 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
559 ade80dc8 Michael S. Tsirkin
    }
560 ade80dc8 Michael S. Tsirkin
561 ade80dc8 Michael S. Tsirkin
    return 0;
562 ade80dc8 Michael S. Tsirkin
}
563 ade80dc8 Michael S. Tsirkin
564 5430a28f mst@redhat.com
static bool virtio_pci_query_guest_notifiers(void *opaque)
565 5430a28f mst@redhat.com
{
566 5430a28f mst@redhat.com
    VirtIOPCIProxy *proxy = opaque;
567 5430a28f mst@redhat.com
    return msix_enabled(&proxy->pci_dev);
568 5430a28f mst@redhat.com
}
569 5430a28f mst@redhat.com
570 54dd9321 Michael S. Tsirkin
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
571 54dd9321 Michael S. Tsirkin
{
572 54dd9321 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
573 54dd9321 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
574 54dd9321 Michael S. Tsirkin
    int r, n;
575 54dd9321 Michael S. Tsirkin
576 54dd9321 Michael S. Tsirkin
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
577 54dd9321 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, n)) {
578 54dd9321 Michael S. Tsirkin
            break;
579 54dd9321 Michael S. Tsirkin
        }
580 54dd9321 Michael S. Tsirkin
581 54dd9321 Michael S. Tsirkin
        r = virtio_pci_set_guest_notifier(opaque, n, assign);
582 54dd9321 Michael S. Tsirkin
        if (r < 0) {
583 54dd9321 Michael S. Tsirkin
            goto assign_error;
584 54dd9321 Michael S. Tsirkin
        }
585 54dd9321 Michael S. Tsirkin
    }
586 54dd9321 Michael S. Tsirkin
587 54dd9321 Michael S. Tsirkin
    return 0;
588 54dd9321 Michael S. Tsirkin
589 54dd9321 Michael S. Tsirkin
assign_error:
590 54dd9321 Michael S. Tsirkin
    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
591 54dd9321 Michael S. Tsirkin
    while (--n >= 0) {
592 54dd9321 Michael S. Tsirkin
        virtio_pci_set_guest_notifier(opaque, n, !assign);
593 54dd9321 Michael S. Tsirkin
    }
594 54dd9321 Michael S. Tsirkin
    return r;
595 54dd9321 Michael S. Tsirkin
}
596 54dd9321 Michael S. Tsirkin
597 ade80dc8 Michael S. Tsirkin
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
598 ade80dc8 Michael S. Tsirkin
{
599 ade80dc8 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = opaque;
600 25db9ebe Stefan Hajnoczi
601 25db9ebe Stefan Hajnoczi
    /* Stop using ioeventfd for virtqueue kick if the device starts using host
602 25db9ebe Stefan Hajnoczi
     * notifiers.  This makes it easy to avoid stepping on each others' toes.
603 25db9ebe Stefan Hajnoczi
     */
604 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_disabled = assign;
605 ade80dc8 Michael S. Tsirkin
    if (assign) {
606 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
607 25db9ebe Stefan Hajnoczi
    }
608 25db9ebe Stefan Hajnoczi
    /* We don't need to start here: it's not needed because backend
609 25db9ebe Stefan Hajnoczi
     * currently only stops on status change away from ok,
610 25db9ebe Stefan Hajnoczi
     * reset, vmstop and such. If we do add code to start here,
611 25db9ebe Stefan Hajnoczi
     * need to check vmstate, device state etc. */
612 25db9ebe Stefan Hajnoczi
    return virtio_pci_set_host_notifier_internal(proxy, n, assign);
613 25db9ebe Stefan Hajnoczi
}
614 25db9ebe Stefan Hajnoczi
615 25db9ebe Stefan Hajnoczi
static void virtio_pci_vmstate_change(void *opaque, bool running)
616 25db9ebe Stefan Hajnoczi
{
617 25db9ebe Stefan Hajnoczi
    VirtIOPCIProxy *proxy = opaque;
618 25db9ebe Stefan Hajnoczi
619 25db9ebe Stefan Hajnoczi
    if (running) {
620 89c473fd Michael S. Tsirkin
        /* Try to find out if the guest has bus master disabled, but is
621 89c473fd Michael S. Tsirkin
           in ready state. Then we have a buggy guest OS. */
622 89c473fd Michael S. Tsirkin
        if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
623 89c473fd Michael S. Tsirkin
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
624 89c473fd Michael S. Tsirkin
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
625 89c473fd Michael S. Tsirkin
        }
626 25db9ebe Stefan Hajnoczi
        virtio_pci_start_ioeventfd(proxy);
627 ade80dc8 Michael S. Tsirkin
    } else {
628 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
629 ade80dc8 Michael S. Tsirkin
    }
630 ade80dc8 Michael S. Tsirkin
}
631 ade80dc8 Michael S. Tsirkin
632 53c25cea Paul Brook
static const VirtIOBindings virtio_pci_bindings = {
633 ff24bd58 Michael S. Tsirkin
    .notify = virtio_pci_notify,
634 ff24bd58 Michael S. Tsirkin
    .save_config = virtio_pci_save_config,
635 ff24bd58 Michael S. Tsirkin
    .load_config = virtio_pci_load_config,
636 ff24bd58 Michael S. Tsirkin
    .save_queue = virtio_pci_save_queue,
637 ff24bd58 Michael S. Tsirkin
    .load_queue = virtio_pci_load_queue,
638 6d74ca5a Michael S. Tsirkin
    .get_features = virtio_pci_get_features,
639 5430a28f mst@redhat.com
    .query_guest_notifiers = virtio_pci_query_guest_notifiers,
640 ade80dc8 Michael S. Tsirkin
    .set_host_notifier = virtio_pci_set_host_notifier,
641 54dd9321 Michael S. Tsirkin
    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
642 25db9ebe Stefan Hajnoczi
    .vmstate_change = virtio_pci_vmstate_change,
643 53c25cea Paul Brook
};
644 53c25cea Paul Brook
645 befeac45 Michael S. Tsirkin
void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
646 53c25cea Paul Brook
{
647 53c25cea Paul Brook
    uint8_t *config;
648 53c25cea Paul Brook
    uint32_t size;
649 53c25cea Paul Brook
650 53c25cea Paul Brook
    proxy->vdev = vdev;
651 53c25cea Paul Brook
652 53c25cea Paul Brook
    config = proxy->pci_dev.config;
653 53c25cea Paul Brook
654 e75ccf2c Isaku Yamahata
    if (proxy->class_code) {
655 e75ccf2c Isaku Yamahata
        pci_config_set_class(config, proxy->class_code);
656 e75ccf2c Isaku Yamahata
    }
657 ad3d11e6 Hui Kai Ran
    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
658 ad3d11e6 Hui Kai Ran
                 pci_get_word(config + PCI_VENDOR_ID));
659 ad3d11e6 Hui Kai Ran
    pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
660 ad3d11e6 Hui Kai Ran
    config[PCI_INTERRUPT_PIN] = 1;
661 53c25cea Paul Brook
662 95524ae8 Avi Kivity
    memory_region_init(&proxy->msix_bar, "virtio-msix", 4096);
663 95524ae8 Avi Kivity
    if (vdev->nvectors && !msix_init(&proxy->pci_dev, vdev->nvectors,
664 95524ae8 Avi Kivity
                                     &proxy->msix_bar, 1, 0)) {
665 e824b2cc Avi Kivity
        pci_register_bar(&proxy->pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY,
666 e824b2cc Avi Kivity
                         &proxy->msix_bar);
667 aba800a3 Michael S. Tsirkin
    } else
668 aba800a3 Michael S. Tsirkin
        vdev->nvectors = 0;
669 aba800a3 Michael S. Tsirkin
670 ed757e14 Yan Vugenfirer
    proxy->pci_dev.config_write = virtio_write_config;
671 ed757e14 Yan Vugenfirer
672 aba800a3 Michael S. Tsirkin
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
673 53c25cea Paul Brook
    if (size & (size-1))
674 53c25cea Paul Brook
        size = 1 << qemu_fls(size);
675 53c25cea Paul Brook
676 da146d0a Avi Kivity
    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
677 da146d0a Avi Kivity
                          "virtio-pci", size);
678 e824b2cc Avi Kivity
    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
679 e824b2cc Avi Kivity
                     &proxy->bar);
680 53c25cea Paul Brook
681 25db9ebe Stefan Hajnoczi
    if (!kvm_has_many_ioeventfds()) {
682 25db9ebe Stefan Hajnoczi
        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
683 25db9ebe Stefan Hajnoczi
    }
684 25db9ebe Stefan Hajnoczi
685 53c25cea Paul Brook
    virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
686 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
687 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
688 8172539d Michael S. Tsirkin
    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
689 53c25cea Paul Brook
}
690 53c25cea Paul Brook
691 81a322d4 Gerd Hoffmann
static int virtio_blk_init_pci(PCIDevice *pci_dev)
692 53c25cea Paul Brook
{
693 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
694 53c25cea Paul Brook
    VirtIODevice *vdev;
695 53c25cea Paul Brook
696 ab73ff29 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_STORAGE_SCSI &&
697 ab73ff29 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_STORAGE_OTHER)
698 ab73ff29 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_STORAGE_SCSI;
699 53c25cea Paul Brook
700 a8686a9b Markus Armbruster
    vdev = virtio_blk_init(&pci_dev->qdev, &proxy->block,
701 a8686a9b Markus Armbruster
                           &proxy->block_serial);
702 ac0c14d7 Markus Armbruster
    if (!vdev) {
703 ac0c14d7 Markus Armbruster
        return -1;
704 ac0c14d7 Markus Armbruster
    }
705 177539e0 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
706 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
707 177539e0 Gerd Hoffmann
    /* make the actual value visible */
708 177539e0 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
709 81a322d4 Gerd Hoffmann
    return 0;
710 21d58b57 Mark McLoughlin
}
711 21d58b57 Mark McLoughlin
712 0f457d91 Michael S. Tsirkin
static int virtio_exit_pci(PCIDevice *pci_dev)
713 0f457d91 Michael S. Tsirkin
{
714 da146d0a Avi Kivity
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
715 95524ae8 Avi Kivity
    int r;
716 da146d0a Avi Kivity
717 da146d0a Avi Kivity
    memory_region_destroy(&proxy->bar);
718 95524ae8 Avi Kivity
    r = msix_uninit(pci_dev, &proxy->msix_bar);
719 95524ae8 Avi Kivity
    memory_region_destroy(&proxy->msix_bar);
720 95524ae8 Avi Kivity
    return r;
721 0f457d91 Michael S. Tsirkin
}
722 0f457d91 Michael S. Tsirkin
723 56a14938 Gerd Hoffmann
static int virtio_blk_exit_pci(PCIDevice *pci_dev)
724 56a14938 Gerd Hoffmann
{
725 56a14938 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
726 56a14938 Gerd Hoffmann
727 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
728 9d0d3138 Alex Williamson
    virtio_blk_exit(proxy->vdev);
729 f8b6cc00 Markus Armbruster
    blockdev_mark_auto_del(proxy->block.bs);
730 0f457d91 Michael S. Tsirkin
    return virtio_exit_pci(pci_dev);
731 56a14938 Gerd Hoffmann
}
732 56a14938 Gerd Hoffmann
733 98b19252 Amit Shah
static int virtio_serial_init_pci(PCIDevice *pci_dev)
734 21d58b57 Mark McLoughlin
{
735 d6beee99 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
736 85c2c735 Mark McLoughlin
    VirtIODevice *vdev;
737 85c2c735 Mark McLoughlin
738 d6beee99 Gerd Hoffmann
    if (proxy->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
739 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
740 d6beee99 Gerd Hoffmann
        proxy->class_code != PCI_CLASS_OTHERS)          /* qemu-kvm  */
741 d6beee99 Gerd Hoffmann
        proxy->class_code = PCI_CLASS_COMMUNICATION_OTHER;
742 d6beee99 Gerd Hoffmann
743 6b331efb Amit Shah
    vdev = virtio_serial_init(&pci_dev->qdev, &proxy->serial);
744 25fe3654 Amit Shah
    if (!vdev) {
745 25fe3654 Amit Shah
        return -1;
746 25fe3654 Amit Shah
    }
747 573fb60c Amit Shah
    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
748 6b331efb Amit Shah
                                        ? proxy->serial.max_virtserial_ports + 1
749 573fb60c Amit Shah
                                        : proxy->nvectors;
750 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
751 a1829205 Amit Shah
    proxy->nvectors = vdev->nvectors;
752 81a322d4 Gerd Hoffmann
    return 0;
753 53c25cea Paul Brook
}
754 53c25cea Paul Brook
755 8b53a865 Amit Shah
static int virtio_serial_exit_pci(PCIDevice *pci_dev)
756 8b53a865 Amit Shah
{
757 8b53a865 Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
758 8b53a865 Amit Shah
759 32059220 Amit Shah
    virtio_pci_stop_ioeventfd(proxy);
760 8b53a865 Amit Shah
    virtio_serial_exit(proxy->vdev);
761 8b53a865 Amit Shah
    return virtio_exit_pci(pci_dev);
762 8b53a865 Amit Shah
}
763 8b53a865 Amit Shah
764 81a322d4 Gerd Hoffmann
static int virtio_net_init_pci(PCIDevice *pci_dev)
765 53c25cea Paul Brook
{
766 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
767 53c25cea Paul Brook
    VirtIODevice *vdev;
768 53c25cea Paul Brook
769 f0c07c7c Alex Williamson
    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
770 a1e0fea5 Gerd Hoffmann
771 97b15621 Gerd Hoffmann
    vdev->nvectors = proxy->nvectors;
772 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
773 a1e0fea5 Gerd Hoffmann
774 a1e0fea5 Gerd Hoffmann
    /* make the actual value visible */
775 a1e0fea5 Gerd Hoffmann
    proxy->nvectors = vdev->nvectors;
776 81a322d4 Gerd Hoffmann
    return 0;
777 53c25cea Paul Brook
}
778 53c25cea Paul Brook
779 97b15621 Gerd Hoffmann
static int virtio_net_exit_pci(PCIDevice *pci_dev)
780 97b15621 Gerd Hoffmann
{
781 97b15621 Gerd Hoffmann
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
782 97b15621 Gerd Hoffmann
783 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
784 97b15621 Gerd Hoffmann
    virtio_net_exit(proxy->vdev);
785 97b15621 Gerd Hoffmann
    return virtio_exit_pci(pci_dev);
786 97b15621 Gerd Hoffmann
}
787 97b15621 Gerd Hoffmann
788 81a322d4 Gerd Hoffmann
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
789 53c25cea Paul Brook
{
790 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
791 53c25cea Paul Brook
    VirtIODevice *vdev;
792 53c25cea Paul Brook
793 53c25cea Paul Brook
    vdev = virtio_balloon_init(&pci_dev->qdev);
794 f76f6655 Amit Shah
    if (!vdev) {
795 f76f6655 Amit Shah
        return -1;
796 f76f6655 Amit Shah
    }
797 e75ccf2c Isaku Yamahata
    virtio_init_pci(proxy, vdev);
798 81a322d4 Gerd Hoffmann
    return 0;
799 53c25cea Paul Brook
}
800 53c25cea Paul Brook
801 855d7e25 Amit Shah
static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
802 855d7e25 Amit Shah
{
803 855d7e25 Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
804 855d7e25 Amit Shah
805 855d7e25 Amit Shah
    virtio_pci_stop_ioeventfd(proxy);
806 855d7e25 Amit Shah
    virtio_balloon_exit(proxy->vdev);
807 855d7e25 Amit Shah
    return virtio_exit_pci(pci_dev);
808 855d7e25 Amit Shah
}
809 855d7e25 Amit Shah
810 40021f08 Anthony Liguori
static Property virtio_blk_properties[] = {
811 40021f08 Anthony Liguori
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
812 40021f08 Anthony Liguori
    DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
813 40021f08 Anthony Liguori
    DEFINE_PROP_STRING("serial", VirtIOPCIProxy, block_serial),
814 40021f08 Anthony Liguori
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
815 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
816 40021f08 Anthony Liguori
    DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
817 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
818 e855761c Anthony Liguori
};
819 e855761c Anthony Liguori
820 40021f08 Anthony Liguori
static void virtio_blk_class_init(ObjectClass *klass, void *data)
821 40021f08 Anthony Liguori
{
822 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
823 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
824 40021f08 Anthony Liguori
825 40021f08 Anthony Liguori
    k->init = virtio_blk_init_pci;
826 40021f08 Anthony Liguori
    k->exit = virtio_blk_exit_pci;
827 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
828 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
829 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
830 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_STORAGE_SCSI;
831 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
832 39bffca2 Anthony Liguori
    dc->props = virtio_blk_properties;
833 40021f08 Anthony Liguori
}
834 40021f08 Anthony Liguori
835 39bffca2 Anthony Liguori
static TypeInfo virtio_blk_info = {
836 39bffca2 Anthony Liguori
    .name          = "virtio-blk-pci",
837 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
838 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
839 39bffca2 Anthony Liguori
    .class_init    = virtio_blk_class_init,
840 40021f08 Anthony Liguori
};
841 40021f08 Anthony Liguori
842 40021f08 Anthony Liguori
static Property virtio_net_properties[] = {
843 40021f08 Anthony Liguori
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
844 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
845 40021f08 Anthony Liguori
    DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
846 40021f08 Anthony Liguori
    DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
847 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy, net.txtimer, TX_TIMER_INTERVAL),
848 40021f08 Anthony Liguori
    DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy, net.txburst, TX_BURST),
849 40021f08 Anthony Liguori
    DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
850 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
851 40021f08 Anthony Liguori
};
852 40021f08 Anthony Liguori
853 40021f08 Anthony Liguori
static void virtio_net_class_init(ObjectClass *klass, void *data)
854 40021f08 Anthony Liguori
{
855 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
856 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
857 40021f08 Anthony Liguori
858 40021f08 Anthony Liguori
    k->init = virtio_net_init_pci;
859 40021f08 Anthony Liguori
    k->exit = virtio_net_exit_pci;
860 40021f08 Anthony Liguori
    k->romfile = "pxe-virtio.rom";
861 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
862 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
863 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
864 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
865 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
866 39bffca2 Anthony Liguori
    dc->props = virtio_net_properties;
867 40021f08 Anthony Liguori
}
868 40021f08 Anthony Liguori
869 39bffca2 Anthony Liguori
static TypeInfo virtio_net_info = {
870 39bffca2 Anthony Liguori
    .name          = "virtio-net-pci",
871 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
872 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
873 39bffca2 Anthony Liguori
    .class_init    = virtio_net_class_init,
874 e855761c Anthony Liguori
};
875 e855761c Anthony Liguori
876 40021f08 Anthony Liguori
static Property virtio_serial_properties[] = {
877 40021f08 Anthony Liguori
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
878 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
879 40021f08 Anthony Liguori
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
880 40021f08 Anthony Liguori
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
881 40021f08 Anthony Liguori
    DEFINE_PROP_UINT32("max_ports", VirtIOPCIProxy, serial.max_virtserial_ports, 31),
882 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
883 e855761c Anthony Liguori
};
884 e855761c Anthony Liguori
885 40021f08 Anthony Liguori
static void virtio_serial_class_init(ObjectClass *klass, void *data)
886 40021f08 Anthony Liguori
{
887 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
888 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
889 40021f08 Anthony Liguori
890 40021f08 Anthony Liguori
    k->init = virtio_serial_init_pci;
891 40021f08 Anthony Liguori
    k->exit = virtio_serial_exit_pci;
892 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
893 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
894 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
895 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
896 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
897 39bffca2 Anthony Liguori
    dc->props = virtio_serial_properties;
898 40021f08 Anthony Liguori
}
899 40021f08 Anthony Liguori
900 39bffca2 Anthony Liguori
static TypeInfo virtio_serial_info = {
901 39bffca2 Anthony Liguori
    .name          = "virtio-serial-pci",
902 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
903 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
904 39bffca2 Anthony Liguori
    .class_init    = virtio_serial_class_init,
905 40021f08 Anthony Liguori
};
906 40021f08 Anthony Liguori
907 40021f08 Anthony Liguori
static Property virtio_balloon_properties[] = {
908 40021f08 Anthony Liguori
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
909 40021f08 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
910 40021f08 Anthony Liguori
};
911 40021f08 Anthony Liguori
912 40021f08 Anthony Liguori
static void virtio_balloon_class_init(ObjectClass *klass, void *data)
913 40021f08 Anthony Liguori
{
914 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
915 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
916 40021f08 Anthony Liguori
917 40021f08 Anthony Liguori
    k->init = virtio_balloon_init_pci;
918 40021f08 Anthony Liguori
    k->exit = virtio_balloon_exit_pci;
919 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
920 40021f08 Anthony Liguori
    k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
921 40021f08 Anthony Liguori
    k->revision = VIRTIO_PCI_ABI_VERSION;
922 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_MEMORY_RAM;
923 39bffca2 Anthony Liguori
    dc->reset = virtio_pci_reset;
924 39bffca2 Anthony Liguori
    dc->props = virtio_balloon_properties;
925 40021f08 Anthony Liguori
}
926 40021f08 Anthony Liguori
927 39bffca2 Anthony Liguori
static TypeInfo virtio_balloon_info = {
928 39bffca2 Anthony Liguori
    .name          = "virtio-balloon-pci",
929 39bffca2 Anthony Liguori
    .parent        = TYPE_PCI_DEVICE,
930 39bffca2 Anthony Liguori
    .instance_size = sizeof(VirtIOPCIProxy),
931 39bffca2 Anthony Liguori
    .class_init    = virtio_balloon_class_init,
932 0aab0d3a Gerd Hoffmann
};
933 0aab0d3a Gerd Hoffmann
934 973abc7f Stefan Hajnoczi
static int virtio_scsi_init_pci(PCIDevice *pci_dev)
935 973abc7f Stefan Hajnoczi
{
936 973abc7f Stefan Hajnoczi
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
937 973abc7f Stefan Hajnoczi
    VirtIODevice *vdev;
938 973abc7f Stefan Hajnoczi
939 973abc7f Stefan Hajnoczi
    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
940 973abc7f Stefan Hajnoczi
    if (!vdev) {
941 973abc7f Stefan Hajnoczi
        return -EINVAL;
942 973abc7f Stefan Hajnoczi
    }
943 973abc7f Stefan Hajnoczi
944 973abc7f Stefan Hajnoczi
    vdev->nvectors = proxy->nvectors;
945 973abc7f Stefan Hajnoczi
    virtio_init_pci(proxy, vdev);
946 973abc7f Stefan Hajnoczi
947 973abc7f Stefan Hajnoczi
    /* make the actual value visible */
948 973abc7f Stefan Hajnoczi
    proxy->nvectors = vdev->nvectors;
949 973abc7f Stefan Hajnoczi
    return 0;
950 973abc7f Stefan Hajnoczi
}
951 973abc7f Stefan Hajnoczi
952 973abc7f Stefan Hajnoczi
static int virtio_scsi_exit_pci(PCIDevice *pci_dev)
953 973abc7f Stefan Hajnoczi
{
954 973abc7f Stefan Hajnoczi
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
955 973abc7f Stefan Hajnoczi
956 973abc7f Stefan Hajnoczi
    virtio_scsi_exit(proxy->vdev);
957 973abc7f Stefan Hajnoczi
    return virtio_exit_pci(pci_dev);
958 973abc7f Stefan Hajnoczi
}
959 973abc7f Stefan Hajnoczi
960 973abc7f Stefan Hajnoczi
static Property virtio_scsi_properties[] = {
961 973abc7f Stefan Hajnoczi
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
962 973abc7f Stefan Hajnoczi
    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
963 973abc7f Stefan Hajnoczi
    DEFINE_PROP_END_OF_LIST(),
964 973abc7f Stefan Hajnoczi
};
965 973abc7f Stefan Hajnoczi
966 973abc7f Stefan Hajnoczi
static void virtio_scsi_class_init(ObjectClass *klass, void *data)
967 973abc7f Stefan Hajnoczi
{
968 973abc7f Stefan Hajnoczi
    DeviceClass *dc = DEVICE_CLASS(klass);
969 973abc7f Stefan Hajnoczi
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
970 973abc7f Stefan Hajnoczi
971 973abc7f Stefan Hajnoczi
    k->init = virtio_scsi_init_pci;
972 973abc7f Stefan Hajnoczi
    k->exit = virtio_scsi_exit_pci;
973 973abc7f Stefan Hajnoczi
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
974 973abc7f Stefan Hajnoczi
    k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
975 973abc7f Stefan Hajnoczi
    k->revision = 0x00;
976 973abc7f Stefan Hajnoczi
    k->class_id = PCI_CLASS_STORAGE_SCSI;
977 973abc7f Stefan Hajnoczi
    dc->reset = virtio_pci_reset;
978 973abc7f Stefan Hajnoczi
    dc->props = virtio_scsi_properties;
979 973abc7f Stefan Hajnoczi
}
980 973abc7f Stefan Hajnoczi
981 973abc7f Stefan Hajnoczi
static TypeInfo virtio_scsi_info = {
982 973abc7f Stefan Hajnoczi
    .name          = "virtio-scsi-pci",
983 973abc7f Stefan Hajnoczi
    .parent        = TYPE_PCI_DEVICE,
984 973abc7f Stefan Hajnoczi
    .instance_size = sizeof(VirtIOPCIProxy),
985 973abc7f Stefan Hajnoczi
    .class_init    = virtio_scsi_class_init,
986 973abc7f Stefan Hajnoczi
};
987 973abc7f Stefan Hajnoczi
988 83f7d43a Andreas Färber
static void virtio_pci_register_types(void)
989 53c25cea Paul Brook
{
990 39bffca2 Anthony Liguori
    type_register_static(&virtio_blk_info);
991 39bffca2 Anthony Liguori
    type_register_static(&virtio_net_info);
992 39bffca2 Anthony Liguori
    type_register_static(&virtio_serial_info);
993 39bffca2 Anthony Liguori
    type_register_static(&virtio_balloon_info);
994 973abc7f Stefan Hajnoczi
    type_register_static(&virtio_scsi_info);
995 53c25cea Paul Brook
}
996 53c25cea Paul Brook
997 83f7d43a Andreas Färber
type_init(virtio_pci_register_types)