Statistics
| Branch: | Revision:

root / hw / virtio-pci.c @ 13ef70f6

History | View | Annotate | Download (33.1 kB)

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