Statistics
| Branch: | Revision:

root / hw / virtio / virtio-pci.c @ 881d588a

History | View | Annotate | Download (49 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 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio.h"
21 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio-blk.h"
22 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio-net.h"
23 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio-serial.h"
24 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio-scsi.h"
25 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio-balloon.h"
26 83c9f4ca Paolo Bonzini
#include "hw/pci/pci.h"
27 1de7afc9 Paolo Bonzini
#include "qemu/error-report.h"
28 83c9f4ca Paolo Bonzini
#include "hw/pci/msi.h"
29 83c9f4ca Paolo Bonzini
#include "hw/pci/msix.h"
30 83c9f4ca Paolo Bonzini
#include "hw/loader.h"
31 9c17d615 Paolo Bonzini
#include "sysemu/kvm.h"
32 9c17d615 Paolo Bonzini
#include "sysemu/blockdev.h"
33 47b43a1f Paolo Bonzini
#include "virtio-pci.h"
34 1de7afc9 Paolo Bonzini
#include "qemu/range.h"
35 0d09e41a Paolo Bonzini
#include "hw/virtio/virtio-bus.h"
36 24a6e7f4 KONRAD Frederic
#include "qapi/visitor.h"
37 53c25cea Paul Brook
38 53c25cea Paul Brook
/* from Linux's linux/virtio_pci.h */
39 53c25cea Paul Brook
40 53c25cea Paul Brook
/* A 32-bit r/o bitmask of the features supported by the host */
41 53c25cea Paul Brook
#define VIRTIO_PCI_HOST_FEATURES        0
42 53c25cea Paul Brook
43 53c25cea Paul Brook
/* A 32-bit r/w bitmask of features activated by the guest */
44 53c25cea Paul Brook
#define VIRTIO_PCI_GUEST_FEATURES       4
45 53c25cea Paul Brook
46 53c25cea Paul Brook
/* A 32-bit r/w PFN for the currently selected queue */
47 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_PFN            8
48 53c25cea Paul Brook
49 53c25cea Paul Brook
/* A 16-bit r/o queue size for the currently selected queue */
50 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NUM            12
51 53c25cea Paul Brook
52 53c25cea Paul Brook
/* A 16-bit r/w queue selector */
53 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_SEL            14
54 53c25cea Paul Brook
55 53c25cea Paul Brook
/* A 16-bit r/w queue notifier */
56 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_NOTIFY         16
57 53c25cea Paul Brook
58 53c25cea Paul Brook
/* An 8-bit device status register.  */
59 53c25cea Paul Brook
#define VIRTIO_PCI_STATUS               18
60 53c25cea Paul Brook
61 53c25cea Paul Brook
/* An 8-bit r/o interrupt status register.  Reading the value will return the
62 53c25cea Paul Brook
 * current contents of the ISR and will also clear it.  This is effectively
63 53c25cea Paul Brook
 * a read-and-acknowledge. */
64 53c25cea Paul Brook
#define VIRTIO_PCI_ISR                  19
65 53c25cea Paul Brook
66 aba800a3 Michael S. Tsirkin
/* MSI-X registers: only enabled if MSI-X is enabled. */
67 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for configuration changes. */
68 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_CONFIG_VECTOR        20
69 aba800a3 Michael S. Tsirkin
/* A 16-bit vector for selected queue notifications. */
70 aba800a3 Michael S. Tsirkin
#define VIRTIO_MSI_QUEUE_VECTOR         22
71 aba800a3 Michael S. Tsirkin
72 aba800a3 Michael S. Tsirkin
/* Config space size */
73 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_NOMSI         20
74 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG_MSI           24
75 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_REGION_SIZE(dev)     (msix_present(dev) ? \
76 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
77 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
78 aba800a3 Michael S. Tsirkin
79 aba800a3 Michael S. Tsirkin
/* The remaining space is defined by each driver as the per-driver
80 aba800a3 Michael S. Tsirkin
 * configuration space */
81 aba800a3 Michael S. Tsirkin
#define VIRTIO_PCI_CONFIG(dev)          (msix_enabled(dev) ? \
82 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_MSI : \
83 aba800a3 Michael S. Tsirkin
                                         VIRTIO_PCI_CONFIG_NOMSI)
84 53c25cea Paul Brook
85 53c25cea Paul Brook
/* How many bits to shift physical queue address written to QUEUE_PFN.
86 53c25cea Paul Brook
 * 12 is historical, and due to x86 page size. */
87 53c25cea Paul Brook
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT    12
88 53c25cea Paul Brook
89 3dbca8e6 Stefan Hajnoczi
/* Flags track per-device state like workarounds for quirks in older guests. */
90 3dbca8e6 Stefan Hajnoczi
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG  (1 << 0)
91 c81131db Alexander Graf
92 53c25cea Paul Brook
/* QEMU doesn't strictly need write barriers since everything runs in
93 53c25cea Paul Brook
 * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
94 53c25cea Paul Brook
 * KVM or if kqemu gets SMP support.
95 53c25cea Paul Brook
 */
96 53c25cea Paul Brook
#define wmb() do { } while (0)
97 53c25cea Paul Brook
98 8e4a424b Blue Swirl
/* HACK for virtio to determine if it's running a big endian guest */
99 8e4a424b Blue Swirl
bool virtio_is_big_endian(void);
100 8e4a424b Blue Swirl
101 53c25cea Paul Brook
/* virtio device */
102 d2a0ccc6 Michael S. Tsirkin
/* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
103 d2a0ccc6 Michael S. Tsirkin
static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d)
104 d2a0ccc6 Michael S. Tsirkin
{
105 d2a0ccc6 Michael S. Tsirkin
    return container_of(d, VirtIOPCIProxy, pci_dev.qdev);
106 d2a0ccc6 Michael S. Tsirkin
}
107 53c25cea Paul Brook
108 d2a0ccc6 Michael S. Tsirkin
/* DeviceState to VirtIOPCIProxy. Note: used on datapath,
109 d2a0ccc6 Michael S. Tsirkin
 * be careful and test performance if you change this.
110 d2a0ccc6 Michael S. Tsirkin
 */
111 d2a0ccc6 Michael S. Tsirkin
static inline VirtIOPCIProxy *to_virtio_pci_proxy_fast(DeviceState *d)
112 53c25cea Paul Brook
{
113 d2a0ccc6 Michael S. Tsirkin
    return container_of(d, VirtIOPCIProxy, pci_dev.qdev);
114 d2a0ccc6 Michael S. Tsirkin
}
115 d2a0ccc6 Michael S. Tsirkin
116 d2a0ccc6 Michael S. Tsirkin
static void virtio_pci_notify(DeviceState *d, uint16_t vector)
117 d2a0ccc6 Michael S. Tsirkin
{
118 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy_fast(d);
119 aba800a3 Michael S. Tsirkin
    if (msix_enabled(&proxy->pci_dev))
120 aba800a3 Michael S. Tsirkin
        msix_notify(&proxy->pci_dev, vector);
121 aba800a3 Michael S. Tsirkin
    else
122 aba800a3 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
123 53c25cea Paul Brook
}
124 53c25cea Paul Brook
125 d2a0ccc6 Michael S. Tsirkin
static void virtio_pci_save_config(DeviceState *d, QEMUFile *f)
126 ff24bd58 Michael S. Tsirkin
{
127 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
128 ff24bd58 Michael S. Tsirkin
    pci_device_save(&proxy->pci_dev, f);
129 ff24bd58 Michael S. Tsirkin
    msix_save(&proxy->pci_dev, f);
130 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
131 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, proxy->vdev->config_vector);
132 ff24bd58 Michael S. Tsirkin
}
133 ff24bd58 Michael S. Tsirkin
134 d2a0ccc6 Michael S. Tsirkin
static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f)
135 ff24bd58 Michael S. Tsirkin
{
136 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
137 ff24bd58 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev))
138 ff24bd58 Michael S. Tsirkin
        qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
139 ff24bd58 Michael S. Tsirkin
}
140 ff24bd58 Michael S. Tsirkin
141 d2a0ccc6 Michael S. Tsirkin
static int virtio_pci_load_config(DeviceState *d, QEMUFile *f)
142 ff24bd58 Michael S. Tsirkin
{
143 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
144 ff24bd58 Michael S. Tsirkin
    int ret;
145 ff24bd58 Michael S. Tsirkin
    ret = pci_device_load(&proxy->pci_dev, f);
146 e6da7680 Michael S. Tsirkin
    if (ret) {
147 ff24bd58 Michael S. Tsirkin
        return ret;
148 e6da7680 Michael S. Tsirkin
    }
149 3cac001e Michael S. Tsirkin
    msix_unuse_all_vectors(&proxy->pci_dev);
150 ff24bd58 Michael S. Tsirkin
    msix_load(&proxy->pci_dev, f);
151 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
152 ff24bd58 Michael S. Tsirkin
        qemu_get_be16s(f, &proxy->vdev->config_vector);
153 e6da7680 Michael S. Tsirkin
    } else {
154 e6da7680 Michael S. Tsirkin
        proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
155 e6da7680 Michael S. Tsirkin
    }
156 e6da7680 Michael S. Tsirkin
    if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
157 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
158 e6da7680 Michael S. Tsirkin
    }
159 ff24bd58 Michael S. Tsirkin
    return 0;
160 ff24bd58 Michael S. Tsirkin
}
161 ff24bd58 Michael S. Tsirkin
162 d2a0ccc6 Michael S. Tsirkin
static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
163 ff24bd58 Michael S. Tsirkin
{
164 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
165 ff24bd58 Michael S. Tsirkin
    uint16_t vector;
166 e6da7680 Michael S. Tsirkin
    if (msix_present(&proxy->pci_dev)) {
167 e6da7680 Michael S. Tsirkin
        qemu_get_be16s(f, &vector);
168 e6da7680 Michael S. Tsirkin
    } else {
169 e6da7680 Michael S. Tsirkin
        vector = VIRTIO_NO_VECTOR;
170 e6da7680 Michael S. Tsirkin
    }
171 ff24bd58 Michael S. Tsirkin
    virtio_queue_set_vector(proxy->vdev, n, vector);
172 e6da7680 Michael S. Tsirkin
    if (vector != VIRTIO_NO_VECTOR) {
173 e6da7680 Michael S. Tsirkin
        return msix_vector_use(&proxy->pci_dev, vector);
174 e6da7680 Michael S. Tsirkin
    }
175 ff24bd58 Michael S. Tsirkin
    return 0;
176 ff24bd58 Michael S. Tsirkin
}
177 ff24bd58 Michael S. Tsirkin
178 25db9ebe Stefan Hajnoczi
static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
179 26b9b5fe Paolo Bonzini
                                                 int n, bool assign, bool set_handler)
180 25db9ebe Stefan Hajnoczi
{
181 25db9ebe Stefan Hajnoczi
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
182 25db9ebe Stefan Hajnoczi
    EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
183 da146d0a Avi Kivity
    int r = 0;
184 da146d0a Avi Kivity
185 25db9ebe Stefan Hajnoczi
    if (assign) {
186 25db9ebe Stefan Hajnoczi
        r = event_notifier_init(notifier, 1);
187 25db9ebe Stefan Hajnoczi
        if (r < 0) {
188 b36e3914 Michael S. Tsirkin
            error_report("%s: unable to init event notifier: %d",
189 b36e3914 Michael S. Tsirkin
                         __func__, r);
190 25db9ebe Stefan Hajnoczi
            return r;
191 25db9ebe Stefan Hajnoczi
        }
192 26b9b5fe Paolo Bonzini
        virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
193 da146d0a Avi Kivity
        memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
194 753d5e14 Paolo Bonzini
                                  true, n, notifier);
195 25db9ebe Stefan Hajnoczi
    } else {
196 da146d0a Avi Kivity
        memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2,
197 753d5e14 Paolo Bonzini
                                  true, n, notifier);
198 26b9b5fe Paolo Bonzini
        virtio_queue_set_host_notifier_fd_handler(vq, false, false);
199 25db9ebe Stefan Hajnoczi
        event_notifier_cleanup(notifier);
200 25db9ebe Stefan Hajnoczi
    }
201 25db9ebe Stefan Hajnoczi
    return r;
202 25db9ebe Stefan Hajnoczi
}
203 25db9ebe Stefan Hajnoczi
204 b36e3914 Michael S. Tsirkin
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
205 25db9ebe Stefan Hajnoczi
{
206 25db9ebe Stefan Hajnoczi
    int n, r;
207 25db9ebe Stefan Hajnoczi
208 25db9ebe Stefan Hajnoczi
    if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
209 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_disabled ||
210 25db9ebe Stefan Hajnoczi
        proxy->ioeventfd_started) {
211 b36e3914 Michael S. Tsirkin
        return;
212 25db9ebe Stefan Hajnoczi
    }
213 25db9ebe Stefan Hajnoczi
214 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
215 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
216 25db9ebe Stefan Hajnoczi
            continue;
217 25db9ebe Stefan Hajnoczi
        }
218 25db9ebe Stefan Hajnoczi
219 26b9b5fe Paolo Bonzini
        r = virtio_pci_set_host_notifier_internal(proxy, n, true, true);
220 25db9ebe Stefan Hajnoczi
        if (r < 0) {
221 25db9ebe Stefan Hajnoczi
            goto assign_error;
222 25db9ebe Stefan Hajnoczi
        }
223 25db9ebe Stefan Hajnoczi
    }
224 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = true;
225 b36e3914 Michael S. Tsirkin
    return;
226 25db9ebe Stefan Hajnoczi
227 25db9ebe Stefan Hajnoczi
assign_error:
228 25db9ebe Stefan Hajnoczi
    while (--n >= 0) {
229 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
230 25db9ebe Stefan Hajnoczi
            continue;
231 25db9ebe Stefan Hajnoczi
        }
232 25db9ebe Stefan Hajnoczi
233 26b9b5fe Paolo Bonzini
        r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
234 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
235 25db9ebe Stefan Hajnoczi
    }
236 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
237 b36e3914 Michael S. Tsirkin
    error_report("%s: failed. Fallback to a userspace (slower).", __func__);
238 25db9ebe Stefan Hajnoczi
}
239 25db9ebe Stefan Hajnoczi
240 b36e3914 Michael S. Tsirkin
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
241 25db9ebe Stefan Hajnoczi
{
242 b36e3914 Michael S. Tsirkin
    int r;
243 25db9ebe Stefan Hajnoczi
    int n;
244 25db9ebe Stefan Hajnoczi
245 25db9ebe Stefan Hajnoczi
    if (!proxy->ioeventfd_started) {
246 b36e3914 Michael S. Tsirkin
        return;
247 25db9ebe Stefan Hajnoczi
    }
248 25db9ebe Stefan Hajnoczi
249 25db9ebe Stefan Hajnoczi
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
250 25db9ebe Stefan Hajnoczi
        if (!virtio_queue_get_num(proxy->vdev, n)) {
251 25db9ebe Stefan Hajnoczi
            continue;
252 25db9ebe Stefan Hajnoczi
        }
253 25db9ebe Stefan Hajnoczi
254 26b9b5fe Paolo Bonzini
        r = virtio_pci_set_host_notifier_internal(proxy, n, false, false);
255 b36e3914 Michael S. Tsirkin
        assert(r >= 0);
256 25db9ebe Stefan Hajnoczi
    }
257 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_started = false;
258 25db9ebe Stefan Hajnoczi
}
259 25db9ebe Stefan Hajnoczi
260 60653b28 Paolo Bonzini
static void virtio_pci_reset(DeviceState *d)
261 7055e687 Michael S. Tsirkin
{
262 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
263 25db9ebe Stefan Hajnoczi
    virtio_pci_stop_ioeventfd(proxy);
264 7055e687 Michael S. Tsirkin
    virtio_reset(proxy->vdev);
265 3cac001e Michael S. Tsirkin
    msix_unuse_all_vectors(&proxy->pci_dev);
266 25db9ebe Stefan Hajnoczi
    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
267 7055e687 Michael S. Tsirkin
}
268 7055e687 Michael S. Tsirkin
269 53c25cea Paul Brook
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
270 53c25cea Paul Brook
{
271 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
272 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
273 a8170e5e Avi Kivity
    hwaddr pa;
274 53c25cea Paul Brook
275 53c25cea Paul Brook
    switch (addr) {
276 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
277 53c25cea Paul Brook
        /* Guest does not negotiate properly?  We have to assume nothing. */
278 53c25cea Paul Brook
        if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
279 ad0c9332 Paolo Bonzini
            val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
280 53c25cea Paul Brook
        }
281 ad0c9332 Paolo Bonzini
        virtio_set_features(vdev, val);
282 53c25cea Paul Brook
        break;
283 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
284 a8170e5e Avi Kivity
        pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
285 1b8e9b27 Michael S. Tsirkin
        if (pa == 0) {
286 25db9ebe Stefan Hajnoczi
            virtio_pci_stop_ioeventfd(proxy);
287 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
288 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
289 1b8e9b27 Michael S. Tsirkin
        }
290 7055e687 Michael S. Tsirkin
        else
291 7055e687 Michael S. Tsirkin
            virtio_queue_set_addr(vdev, vdev->queue_sel, pa);
292 53c25cea Paul Brook
        break;
293 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
294 53c25cea Paul Brook
        if (val < VIRTIO_PCI_QUEUE_MAX)
295 53c25cea Paul Brook
            vdev->queue_sel = val;
296 53c25cea Paul Brook
        break;
297 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NOTIFY:
298 7157e2e2 Stefan Hajnoczi
        if (val < VIRTIO_PCI_QUEUE_MAX) {
299 7157e2e2 Stefan Hajnoczi
            virtio_queue_notify(vdev, val);
300 7157e2e2 Stefan Hajnoczi
        }
301 53c25cea Paul Brook
        break;
302 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
303 25db9ebe Stefan Hajnoczi
        if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
304 25db9ebe Stefan Hajnoczi
            virtio_pci_stop_ioeventfd(proxy);
305 25db9ebe Stefan Hajnoczi
        }
306 25db9ebe Stefan Hajnoczi
307 3e607cb5 Michael S. Tsirkin
        virtio_set_status(vdev, val & 0xFF);
308 25db9ebe Stefan Hajnoczi
309 25db9ebe Stefan Hajnoczi
        if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
310 25db9ebe Stefan Hajnoczi
            virtio_pci_start_ioeventfd(proxy);
311 25db9ebe Stefan Hajnoczi
        }
312 25db9ebe Stefan Hajnoczi
313 1b8e9b27 Michael S. Tsirkin
        if (vdev->status == 0) {
314 1b8e9b27 Michael S. Tsirkin
            virtio_reset(proxy->vdev);
315 1b8e9b27 Michael S. Tsirkin
            msix_unuse_all_vectors(&proxy->pci_dev);
316 1b8e9b27 Michael S. Tsirkin
        }
317 c81131db Alexander Graf
318 c81131db Alexander Graf
        /* Linux before 2.6.34 sets the device as OK without enabling
319 c81131db Alexander Graf
           the PCI device bus master bit. In this case we need to disable
320 c81131db Alexander Graf
           some safety checks. */
321 c81131db Alexander Graf
        if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
322 c81131db Alexander Graf
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
323 3dbca8e6 Stefan Hajnoczi
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
324 c81131db Alexander Graf
        }
325 53c25cea Paul Brook
        break;
326 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
327 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev, vdev->config_vector);
328 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
329 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
330 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
331 aba800a3 Michael S. Tsirkin
        vdev->config_vector = val;
332 aba800a3 Michael S. Tsirkin
        break;
333 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
334 aba800a3 Michael S. Tsirkin
        msix_vector_unuse(&proxy->pci_dev,
335 aba800a3 Michael S. Tsirkin
                          virtio_queue_vector(vdev, vdev->queue_sel));
336 aba800a3 Michael S. Tsirkin
        /* Make it possible for guest to discover an error took place. */
337 aba800a3 Michael S. Tsirkin
        if (msix_vector_use(&proxy->pci_dev, val) < 0)
338 aba800a3 Michael S. Tsirkin
            val = VIRTIO_NO_VECTOR;
339 aba800a3 Michael S. Tsirkin
        virtio_queue_set_vector(vdev, vdev->queue_sel, val);
340 aba800a3 Michael S. Tsirkin
        break;
341 aba800a3 Michael S. Tsirkin
    default:
342 4e02d460 Stefan Hajnoczi
        error_report("%s: unexpected address 0x%x value 0x%x",
343 4e02d460 Stefan Hajnoczi
                     __func__, addr, val);
344 aba800a3 Michael S. Tsirkin
        break;
345 53c25cea Paul Brook
    }
346 53c25cea Paul Brook
}
347 53c25cea Paul Brook
348 aba800a3 Michael S. Tsirkin
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
349 53c25cea Paul Brook
{
350 53c25cea Paul Brook
    VirtIODevice *vdev = proxy->vdev;
351 53c25cea Paul Brook
    uint32_t ret = 0xFFFFFFFF;
352 53c25cea Paul Brook
353 53c25cea Paul Brook
    switch (addr) {
354 53c25cea Paul Brook
    case VIRTIO_PCI_HOST_FEATURES:
355 8172539d Michael S. Tsirkin
        ret = proxy->host_features;
356 53c25cea Paul Brook
        break;
357 53c25cea Paul Brook
    case VIRTIO_PCI_GUEST_FEATURES:
358 704a76fc Michael S. Tsirkin
        ret = vdev->guest_features;
359 53c25cea Paul Brook
        break;
360 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_PFN:
361 53c25cea Paul Brook
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel)
362 53c25cea Paul Brook
              >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
363 53c25cea Paul Brook
        break;
364 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_NUM:
365 53c25cea Paul Brook
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
366 53c25cea Paul Brook
        break;
367 53c25cea Paul Brook
    case VIRTIO_PCI_QUEUE_SEL:
368 53c25cea Paul Brook
        ret = vdev->queue_sel;
369 53c25cea Paul Brook
        break;
370 53c25cea Paul Brook
    case VIRTIO_PCI_STATUS:
371 53c25cea Paul Brook
        ret = vdev->status;
372 53c25cea Paul Brook
        break;
373 53c25cea Paul Brook
    case VIRTIO_PCI_ISR:
374 53c25cea Paul Brook
        /* reading from the ISR also clears it. */
375 53c25cea Paul Brook
        ret = vdev->isr;
376 53c25cea Paul Brook
        vdev->isr = 0;
377 7055e687 Michael S. Tsirkin
        qemu_set_irq(proxy->pci_dev.irq[0], 0);
378 53c25cea Paul Brook
        break;
379 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_CONFIG_VECTOR:
380 aba800a3 Michael S. Tsirkin
        ret = vdev->config_vector;
381 aba800a3 Michael S. Tsirkin
        break;
382 aba800a3 Michael S. Tsirkin
    case VIRTIO_MSI_QUEUE_VECTOR:
383 aba800a3 Michael S. Tsirkin
        ret = virtio_queue_vector(vdev, vdev->queue_sel);
384 aba800a3 Michael S. Tsirkin
        break;
385 53c25cea Paul Brook
    default:
386 53c25cea Paul Brook
        break;
387 53c25cea Paul Brook
    }
388 53c25cea Paul Brook
389 53c25cea Paul Brook
    return ret;
390 53c25cea Paul Brook
}
391 53c25cea Paul Brook
392 df6db5b3 Alexander Graf
static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr,
393 df6db5b3 Alexander Graf
                                       unsigned size)
394 53c25cea Paul Brook
{
395 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
396 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
397 df6db5b3 Alexander Graf
    uint64_t val = 0;
398 aba800a3 Michael S. Tsirkin
    if (addr < config) {
399 df6db5b3 Alexander Graf
        return virtio_ioport_read(proxy, addr);
400 aba800a3 Michael S. Tsirkin
    }
401 aba800a3 Michael S. Tsirkin
    addr -= config;
402 53c25cea Paul Brook
403 df6db5b3 Alexander Graf
    switch (size) {
404 df6db5b3 Alexander Graf
    case 1:
405 df6db5b3 Alexander Graf
        val = virtio_config_readb(proxy->vdev, addr);
406 df6db5b3 Alexander Graf
        break;
407 df6db5b3 Alexander Graf
    case 2:
408 df6db5b3 Alexander Graf
        val = virtio_config_readw(proxy->vdev, addr);
409 8e4a424b Blue Swirl
        if (virtio_is_big_endian()) {
410 8e4a424b Blue Swirl
            val = bswap16(val);
411 8e4a424b Blue Swirl
        }
412 df6db5b3 Alexander Graf
        break;
413 df6db5b3 Alexander Graf
    case 4:
414 df6db5b3 Alexander Graf
        val = virtio_config_readl(proxy->vdev, addr);
415 8e4a424b Blue Swirl
        if (virtio_is_big_endian()) {
416 8e4a424b Blue Swirl
            val = bswap32(val);
417 8e4a424b Blue Swirl
        }
418 df6db5b3 Alexander Graf
        break;
419 82afa586 Benjamin Herrenschmidt
    }
420 df6db5b3 Alexander Graf
    return val;
421 53c25cea Paul Brook
}
422 53c25cea Paul Brook
423 df6db5b3 Alexander Graf
static void virtio_pci_config_write(void *opaque, hwaddr addr,
424 df6db5b3 Alexander Graf
                                    uint64_t val, unsigned size)
425 53c25cea Paul Brook
{
426 53c25cea Paul Brook
    VirtIOPCIProxy *proxy = opaque;
427 aba800a3 Michael S. Tsirkin
    uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
428 aba800a3 Michael S. Tsirkin
    if (addr < config) {
429 aba800a3 Michael S. Tsirkin
        virtio_ioport_write(proxy, addr, val);
430 aba800a3 Michael S. Tsirkin
        return;
431 aba800a3 Michael S. Tsirkin
    }
432 aba800a3 Michael S. Tsirkin
    addr -= config;
433 df6db5b3 Alexander Graf
    /*
434 df6db5b3 Alexander Graf
     * Virtio-PCI is odd. Ioports are LE but config space is target native
435 df6db5b3 Alexander Graf
     * endian.
436 df6db5b3 Alexander Graf
     */
437 df6db5b3 Alexander Graf
    switch (size) {
438 df6db5b3 Alexander Graf
    case 1:
439 df6db5b3 Alexander Graf
        virtio_config_writeb(proxy->vdev, addr, val);
440 df6db5b3 Alexander Graf
        break;
441 df6db5b3 Alexander Graf
    case 2:
442 8e4a424b Blue Swirl
        if (virtio_is_big_endian()) {
443 8e4a424b Blue Swirl
            val = bswap16(val);
444 8e4a424b Blue Swirl
        }
445 df6db5b3 Alexander Graf
        virtio_config_writew(proxy->vdev, addr, val);
446 df6db5b3 Alexander Graf
        break;
447 df6db5b3 Alexander Graf
    case 4:
448 8e4a424b Blue Swirl
        if (virtio_is_big_endian()) {
449 8e4a424b Blue Swirl
            val = bswap32(val);
450 8e4a424b Blue Swirl
        }
451 df6db5b3 Alexander Graf
        virtio_config_writel(proxy->vdev, addr, val);
452 df6db5b3 Alexander Graf
        break;
453 82afa586 Benjamin Herrenschmidt
    }
454 53c25cea Paul Brook
}
455 53c25cea Paul Brook
456 da146d0a Avi Kivity
static const MemoryRegionOps virtio_pci_config_ops = {
457 df6db5b3 Alexander Graf
    .read = virtio_pci_config_read,
458 df6db5b3 Alexander Graf
    .write = virtio_pci_config_write,
459 df6db5b3 Alexander Graf
    .impl = {
460 df6db5b3 Alexander Graf
        .min_access_size = 1,
461 df6db5b3 Alexander Graf
        .max_access_size = 4,
462 df6db5b3 Alexander Graf
    },
463 8e4a424b Blue Swirl
    .endianness = DEVICE_LITTLE_ENDIAN,
464 da146d0a Avi Kivity
};
465 aba800a3 Michael S. Tsirkin
466 aba800a3 Michael S. Tsirkin
static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
467 aba800a3 Michael S. Tsirkin
                                uint32_t val, int len)
468 aba800a3 Michael S. Tsirkin
{
469 ed757e14 Yan Vugenfirer
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
470 ed757e14 Yan Vugenfirer
471 1129714f Michael S. Tsirkin
    pci_default_write_config(pci_dev, address, val, len);
472 1129714f Michael S. Tsirkin
473 1129714f Michael S. Tsirkin
    if (range_covers_byte(address, len, PCI_COMMAND) &&
474 1129714f Michael S. Tsirkin
        !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
475 1129714f Michael S. Tsirkin
        !(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
476 1129714f Michael S. Tsirkin
        virtio_pci_stop_ioeventfd(proxy);
477 1129714f Michael S. Tsirkin
        virtio_set_status(proxy->vdev,
478 1129714f Michael S. Tsirkin
                          proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
479 ed757e14 Yan Vugenfirer
    }
480 53c25cea Paul Brook
}
481 53c25cea Paul Brook
482 d2a0ccc6 Michael S. Tsirkin
static unsigned virtio_pci_get_features(DeviceState *d)
483 6d74ca5a Michael S. Tsirkin
{
484 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
485 8172539d Michael S. Tsirkin
    return proxy->host_features;
486 6d74ca5a Michael S. Tsirkin
}
487 6d74ca5a Michael S. Tsirkin
488 7d37d351 Jan Kiszka
static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
489 7d37d351 Jan Kiszka
                                        unsigned int queue_no,
490 7d37d351 Jan Kiszka
                                        unsigned int vector,
491 7d37d351 Jan Kiszka
                                        MSIMessage msg)
492 7d37d351 Jan Kiszka
{
493 7d37d351 Jan Kiszka
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
494 15b2bd18 Paolo Bonzini
    int ret;
495 7d37d351 Jan Kiszka
496 7d37d351 Jan Kiszka
    if (irqfd->users == 0) {
497 7d37d351 Jan Kiszka
        ret = kvm_irqchip_add_msi_route(kvm_state, msg);
498 7d37d351 Jan Kiszka
        if (ret < 0) {
499 7d37d351 Jan Kiszka
            return ret;
500 7d37d351 Jan Kiszka
        }
501 7d37d351 Jan Kiszka
        irqfd->virq = ret;
502 7d37d351 Jan Kiszka
    }
503 7d37d351 Jan Kiszka
    irqfd->users++;
504 7d37d351 Jan Kiszka
    return 0;
505 7d37d351 Jan Kiszka
}
506 7d37d351 Jan Kiszka
507 7d37d351 Jan Kiszka
static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
508 7d37d351 Jan Kiszka
                                             unsigned int vector)
509 7d37d351 Jan Kiszka
{
510 774345f9 Michael S. Tsirkin
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
511 774345f9 Michael S. Tsirkin
    if (--irqfd->users == 0) {
512 774345f9 Michael S. Tsirkin
        kvm_irqchip_release_virq(kvm_state, irqfd->virq);
513 774345f9 Michael S. Tsirkin
    }
514 774345f9 Michael S. Tsirkin
}
515 774345f9 Michael S. Tsirkin
516 f1d0f15a Michael S. Tsirkin
static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
517 f1d0f15a Michael S. Tsirkin
                                 unsigned int queue_no,
518 f1d0f15a Michael S. Tsirkin
                                 unsigned int vector)
519 f1d0f15a Michael S. Tsirkin
{
520 f1d0f15a Michael S. Tsirkin
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
521 f1d0f15a Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
522 f1d0f15a Michael S. Tsirkin
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
523 f1d0f15a Michael S. Tsirkin
    int ret;
524 f1d0f15a Michael S. Tsirkin
    ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
525 f1d0f15a Michael S. Tsirkin
    return ret;
526 f1d0f15a Michael S. Tsirkin
}
527 f1d0f15a Michael S. Tsirkin
528 f1d0f15a Michael S. Tsirkin
static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
529 f1d0f15a Michael S. Tsirkin
                                      unsigned int queue_no,
530 f1d0f15a Michael S. Tsirkin
                                      unsigned int vector)
531 f1d0f15a Michael S. Tsirkin
{
532 7d37d351 Jan Kiszka
    VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
533 15b2bd18 Paolo Bonzini
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
534 7d37d351 Jan Kiszka
    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
535 15b2bd18 Paolo Bonzini
    int ret;
536 7d37d351 Jan Kiszka
537 b131c74a Jan Kiszka
    ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq);
538 7d37d351 Jan Kiszka
    assert(ret == 0);
539 f1d0f15a Michael S. Tsirkin
}
540 7d37d351 Jan Kiszka
541 774345f9 Michael S. Tsirkin
static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
542 774345f9 Michael S. Tsirkin
{
543 774345f9 Michael S. Tsirkin
    PCIDevice *dev = &proxy->pci_dev;
544 774345f9 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
545 774345f9 Michael S. Tsirkin
    unsigned int vector;
546 774345f9 Michael S. Tsirkin
    int ret, queue_no;
547 774345f9 Michael S. Tsirkin
    MSIMessage msg;
548 774345f9 Michael S. Tsirkin
549 774345f9 Michael S. Tsirkin
    for (queue_no = 0; queue_no < nvqs; queue_no++) {
550 774345f9 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, queue_no)) {
551 774345f9 Michael S. Tsirkin
            break;
552 774345f9 Michael S. Tsirkin
        }
553 774345f9 Michael S. Tsirkin
        vector = virtio_queue_vector(vdev, queue_no);
554 774345f9 Michael S. Tsirkin
        if (vector >= msix_nr_vectors_allocated(dev)) {
555 774345f9 Michael S. Tsirkin
            continue;
556 774345f9 Michael S. Tsirkin
        }
557 774345f9 Michael S. Tsirkin
        msg = msix_get_message(dev, vector);
558 774345f9 Michael S. Tsirkin
        ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector, msg);
559 774345f9 Michael S. Tsirkin
        if (ret < 0) {
560 774345f9 Michael S. Tsirkin
            goto undo;
561 7d37d351 Jan Kiszka
        }
562 f1d0f15a Michael S. Tsirkin
        /* If guest supports masking, set up irqfd now.
563 f1d0f15a Michael S. Tsirkin
         * Otherwise, delay until unmasked in the frontend.
564 f1d0f15a Michael S. Tsirkin
         */
565 f1d0f15a Michael S. Tsirkin
        if (proxy->vdev->guest_notifier_mask) {
566 f1d0f15a Michael S. Tsirkin
            ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
567 f1d0f15a Michael S. Tsirkin
            if (ret < 0) {
568 f1d0f15a Michael S. Tsirkin
                kvm_virtio_pci_vq_vector_release(proxy, vector);
569 f1d0f15a Michael S. Tsirkin
                goto undo;
570 f1d0f15a Michael S. Tsirkin
            }
571 f1d0f15a Michael S. Tsirkin
        }
572 7d37d351 Jan Kiszka
    }
573 7d37d351 Jan Kiszka
    return 0;
574 774345f9 Michael S. Tsirkin
575 774345f9 Michael S. Tsirkin
undo:
576 774345f9 Michael S. Tsirkin
    while (--queue_no >= 0) {
577 774345f9 Michael S. Tsirkin
        vector = virtio_queue_vector(vdev, queue_no);
578 774345f9 Michael S. Tsirkin
        if (vector >= msix_nr_vectors_allocated(dev)) {
579 774345f9 Michael S. Tsirkin
            continue;
580 774345f9 Michael S. Tsirkin
        }
581 f1d0f15a Michael S. Tsirkin
        if (proxy->vdev->guest_notifier_mask) {
582 e387f99e Michael S. Tsirkin
            kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
583 f1d0f15a Michael S. Tsirkin
        }
584 774345f9 Michael S. Tsirkin
        kvm_virtio_pci_vq_vector_release(proxy, vector);
585 774345f9 Michael S. Tsirkin
    }
586 774345f9 Michael S. Tsirkin
    return ret;
587 7d37d351 Jan Kiszka
}
588 7d37d351 Jan Kiszka
589 774345f9 Michael S. Tsirkin
static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
590 774345f9 Michael S. Tsirkin
{
591 774345f9 Michael S. Tsirkin
    PCIDevice *dev = &proxy->pci_dev;
592 774345f9 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
593 774345f9 Michael S. Tsirkin
    unsigned int vector;
594 774345f9 Michael S. Tsirkin
    int queue_no;
595 774345f9 Michael S. Tsirkin
596 774345f9 Michael S. Tsirkin
    for (queue_no = 0; queue_no < nvqs; queue_no++) {
597 774345f9 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, queue_no)) {
598 774345f9 Michael S. Tsirkin
            break;
599 774345f9 Michael S. Tsirkin
        }
600 774345f9 Michael S. Tsirkin
        vector = virtio_queue_vector(vdev, queue_no);
601 774345f9 Michael S. Tsirkin
        if (vector >= msix_nr_vectors_allocated(dev)) {
602 774345f9 Michael S. Tsirkin
            continue;
603 774345f9 Michael S. Tsirkin
        }
604 f1d0f15a Michael S. Tsirkin
        /* If guest supports masking, clean up irqfd now.
605 f1d0f15a Michael S. Tsirkin
         * Otherwise, it was cleaned when masked in the frontend.
606 f1d0f15a Michael S. Tsirkin
         */
607 f1d0f15a Michael S. Tsirkin
        if (proxy->vdev->guest_notifier_mask) {
608 e387f99e Michael S. Tsirkin
            kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
609 f1d0f15a Michael S. Tsirkin
        }
610 774345f9 Michael S. Tsirkin
        kvm_virtio_pci_vq_vector_release(proxy, vector);
611 774345f9 Michael S. Tsirkin
    }
612 774345f9 Michael S. Tsirkin
}
613 774345f9 Michael S. Tsirkin
614 a38b2c49 Michael S. Tsirkin
static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
615 a38b2c49 Michael S. Tsirkin
                                       unsigned int queue_no,
616 a38b2c49 Michael S. Tsirkin
                                       unsigned int vector,
617 a38b2c49 Michael S. Tsirkin
                                       MSIMessage msg)
618 774345f9 Michael S. Tsirkin
{
619 774345f9 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
620 774345f9 Michael S. Tsirkin
    EventNotifier *n = virtio_queue_get_guest_notifier(vq);
621 a38b2c49 Michael S. Tsirkin
    VirtIOIRQFD *irqfd;
622 53510bfc Michael Roth
    int ret = 0;
623 774345f9 Michael S. Tsirkin
624 a38b2c49 Michael S. Tsirkin
    if (proxy->vector_irqfd) {
625 a38b2c49 Michael S. Tsirkin
        irqfd = &proxy->vector_irqfd[vector];
626 a38b2c49 Michael S. Tsirkin
        if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) {
627 a38b2c49 Michael S. Tsirkin
            ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg);
628 a38b2c49 Michael S. Tsirkin
            if (ret < 0) {
629 a38b2c49 Michael S. Tsirkin
                return ret;
630 a38b2c49 Michael S. Tsirkin
            }
631 774345f9 Michael S. Tsirkin
        }
632 774345f9 Michael S. Tsirkin
    }
633 774345f9 Michael S. Tsirkin
634 f1d0f15a Michael S. Tsirkin
    /* If guest supports masking, irqfd is already setup, unmask it.
635 f1d0f15a Michael S. Tsirkin
     * Otherwise, set it up now.
636 f1d0f15a Michael S. Tsirkin
     */
637 f1d0f15a Michael S. Tsirkin
    if (proxy->vdev->guest_notifier_mask) {
638 f1d0f15a Michael S. Tsirkin
        proxy->vdev->guest_notifier_mask(proxy->vdev, queue_no, false);
639 f1d0f15a Michael S. Tsirkin
        /* Test after unmasking to avoid losing events. */
640 f1d0f15a Michael S. Tsirkin
        if (proxy->vdev->guest_notifier_pending &&
641 f1d0f15a Michael S. Tsirkin
            proxy->vdev->guest_notifier_pending(proxy->vdev, queue_no)) {
642 f1d0f15a Michael S. Tsirkin
            event_notifier_set(n);
643 f1d0f15a Michael S. Tsirkin
        }
644 f1d0f15a Michael S. Tsirkin
    } else {
645 f1d0f15a Michael S. Tsirkin
        ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
646 7d37d351 Jan Kiszka
    }
647 774345f9 Michael S. Tsirkin
    return ret;
648 7d37d351 Jan Kiszka
}
649 7d37d351 Jan Kiszka
650 a38b2c49 Michael S. Tsirkin
static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
651 7d37d351 Jan Kiszka
                                             unsigned int queue_no,
652 7d37d351 Jan Kiszka
                                             unsigned int vector)
653 7d37d351 Jan Kiszka
{
654 f1d0f15a Michael S. Tsirkin
    /* If guest supports masking, keep irqfd but mask it.
655 f1d0f15a Michael S. Tsirkin
     * Otherwise, clean it up now.
656 f1d0f15a Michael S. Tsirkin
     */ 
657 f1d0f15a Michael S. Tsirkin
    if (proxy->vdev->guest_notifier_mask) {
658 f1d0f15a Michael S. Tsirkin
        proxy->vdev->guest_notifier_mask(proxy->vdev, queue_no, true);
659 f1d0f15a Michael S. Tsirkin
    } else {
660 e387f99e Michael S. Tsirkin
        kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
661 f1d0f15a Michael S. Tsirkin
    }
662 7d37d351 Jan Kiszka
}
663 7d37d351 Jan Kiszka
664 a38b2c49 Michael S. Tsirkin
static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
665 a38b2c49 Michael S. Tsirkin
                                    MSIMessage msg)
666 7d37d351 Jan Kiszka
{
667 7d37d351 Jan Kiszka
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
668 7d37d351 Jan Kiszka
    VirtIODevice *vdev = proxy->vdev;
669 7d37d351 Jan Kiszka
    int ret, queue_no;
670 7d37d351 Jan Kiszka
671 2d620f59 Michael S. Tsirkin
    for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
672 7d37d351 Jan Kiszka
        if (!virtio_queue_get_num(vdev, queue_no)) {
673 7d37d351 Jan Kiszka
            break;
674 7d37d351 Jan Kiszka
        }
675 7d37d351 Jan Kiszka
        if (virtio_queue_vector(vdev, queue_no) != vector) {
676 7d37d351 Jan Kiszka
            continue;
677 7d37d351 Jan Kiszka
        }
678 a38b2c49 Michael S. Tsirkin
        ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg);
679 7d37d351 Jan Kiszka
        if (ret < 0) {
680 7d37d351 Jan Kiszka
            goto undo;
681 7d37d351 Jan Kiszka
        }
682 7d37d351 Jan Kiszka
    }
683 7d37d351 Jan Kiszka
    return 0;
684 7d37d351 Jan Kiszka
685 7d37d351 Jan Kiszka
undo:
686 7d37d351 Jan Kiszka
    while (--queue_no >= 0) {
687 7d37d351 Jan Kiszka
        if (virtio_queue_vector(vdev, queue_no) != vector) {
688 7d37d351 Jan Kiszka
            continue;
689 7d37d351 Jan Kiszka
        }
690 a38b2c49 Michael S. Tsirkin
        virtio_pci_vq_vector_mask(proxy, queue_no, vector);
691 7d37d351 Jan Kiszka
    }
692 7d37d351 Jan Kiszka
    return ret;
693 7d37d351 Jan Kiszka
}
694 7d37d351 Jan Kiszka
695 a38b2c49 Michael S. Tsirkin
static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
696 7d37d351 Jan Kiszka
{
697 7d37d351 Jan Kiszka
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
698 7d37d351 Jan Kiszka
    VirtIODevice *vdev = proxy->vdev;
699 7d37d351 Jan Kiszka
    int queue_no;
700 7d37d351 Jan Kiszka
701 2d620f59 Michael S. Tsirkin
    for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
702 7d37d351 Jan Kiszka
        if (!virtio_queue_get_num(vdev, queue_no)) {
703 7d37d351 Jan Kiszka
            break;
704 7d37d351 Jan Kiszka
        }
705 7d37d351 Jan Kiszka
        if (virtio_queue_vector(vdev, queue_no) != vector) {
706 7d37d351 Jan Kiszka
            continue;
707 7d37d351 Jan Kiszka
        }
708 a38b2c49 Michael S. Tsirkin
        virtio_pci_vq_vector_mask(proxy, queue_no, vector);
709 7d37d351 Jan Kiszka
    }
710 7d37d351 Jan Kiszka
}
711 7d37d351 Jan Kiszka
712 a38b2c49 Michael S. Tsirkin
static void virtio_pci_vector_poll(PCIDevice *dev,
713 a38b2c49 Michael S. Tsirkin
                                   unsigned int vector_start,
714 a38b2c49 Michael S. Tsirkin
                                   unsigned int vector_end)
715 89d62be9 Michael S. Tsirkin
{
716 89d62be9 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
717 89d62be9 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
718 89d62be9 Michael S. Tsirkin
    int queue_no;
719 89d62be9 Michael S. Tsirkin
    unsigned int vector;
720 89d62be9 Michael S. Tsirkin
    EventNotifier *notifier;
721 89d62be9 Michael S. Tsirkin
    VirtQueue *vq;
722 89d62be9 Michael S. Tsirkin
723 2d620f59 Michael S. Tsirkin
    for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
724 89d62be9 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, queue_no)) {
725 89d62be9 Michael S. Tsirkin
            break;
726 89d62be9 Michael S. Tsirkin
        }
727 89d62be9 Michael S. Tsirkin
        vector = virtio_queue_vector(vdev, queue_no);
728 89d62be9 Michael S. Tsirkin
        if (vector < vector_start || vector >= vector_end ||
729 89d62be9 Michael S. Tsirkin
            !msix_is_masked(dev, vector)) {
730 89d62be9 Michael S. Tsirkin
            continue;
731 89d62be9 Michael S. Tsirkin
        }
732 89d62be9 Michael S. Tsirkin
        vq = virtio_get_queue(vdev, queue_no);
733 89d62be9 Michael S. Tsirkin
        notifier = virtio_queue_get_guest_notifier(vq);
734 f1d0f15a Michael S. Tsirkin
        if (vdev->guest_notifier_pending) {
735 f1d0f15a Michael S. Tsirkin
            if (vdev->guest_notifier_pending(vdev, queue_no)) {
736 f1d0f15a Michael S. Tsirkin
                msix_set_pending(dev, vector);
737 f1d0f15a Michael S. Tsirkin
            }
738 f1d0f15a Michael S. Tsirkin
        } else if (event_notifier_test_and_clear(notifier)) {
739 89d62be9 Michael S. Tsirkin
            msix_set_pending(dev, vector);
740 89d62be9 Michael S. Tsirkin
        }
741 89d62be9 Michael S. Tsirkin
    }
742 89d62be9 Michael S. Tsirkin
}
743 89d62be9 Michael S. Tsirkin
744 89d62be9 Michael S. Tsirkin
static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
745 89d62be9 Michael S. Tsirkin
                                         bool with_irqfd)
746 ade80dc8 Michael S. Tsirkin
{
747 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
748 ade80dc8 Michael S. Tsirkin
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
749 ade80dc8 Michael S. Tsirkin
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
750 ade80dc8 Michael S. Tsirkin
751 ade80dc8 Michael S. Tsirkin
    if (assign) {
752 ade80dc8 Michael S. Tsirkin
        int r = event_notifier_init(notifier, 0);
753 ade80dc8 Michael S. Tsirkin
        if (r < 0) {
754 ade80dc8 Michael S. Tsirkin
            return r;
755 ade80dc8 Michael S. Tsirkin
        }
756 89d62be9 Michael S. Tsirkin
        virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
757 ade80dc8 Michael S. Tsirkin
    } else {
758 89d62be9 Michael S. Tsirkin
        virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
759 ade80dc8 Michael S. Tsirkin
        event_notifier_cleanup(notifier);
760 ade80dc8 Michael S. Tsirkin
    }
761 ade80dc8 Michael S. Tsirkin
762 ade80dc8 Michael S. Tsirkin
    return 0;
763 ade80dc8 Michael S. Tsirkin
}
764 ade80dc8 Michael S. Tsirkin
765 d2a0ccc6 Michael S. Tsirkin
static bool virtio_pci_query_guest_notifiers(DeviceState *d)
766 5430a28f mst@redhat.com
{
767 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
768 5430a28f mst@redhat.com
    return msix_enabled(&proxy->pci_dev);
769 5430a28f mst@redhat.com
}
770 5430a28f mst@redhat.com
771 2d620f59 Michael S. Tsirkin
static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
772 54dd9321 Michael S. Tsirkin
{
773 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
774 54dd9321 Michael S. Tsirkin
    VirtIODevice *vdev = proxy->vdev;
775 54dd9321 Michael S. Tsirkin
    int r, n;
776 89d62be9 Michael S. Tsirkin
    bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
777 89d62be9 Michael S. Tsirkin
        kvm_msi_via_irqfd_enabled();
778 54dd9321 Michael S. Tsirkin
779 2d620f59 Michael S. Tsirkin
    nvqs = MIN(nvqs, VIRTIO_PCI_QUEUE_MAX);
780 2d620f59 Michael S. Tsirkin
781 2d620f59 Michael S. Tsirkin
    /* When deassigning, pass a consistent nvqs value
782 2d620f59 Michael S. Tsirkin
     * to avoid leaking notifiers.
783 2d620f59 Michael S. Tsirkin
     */
784 2d620f59 Michael S. Tsirkin
    assert(assign || nvqs == proxy->nvqs_with_notifiers);
785 2d620f59 Michael S. Tsirkin
786 2d620f59 Michael S. Tsirkin
    proxy->nvqs_with_notifiers = nvqs;
787 2d620f59 Michael S. Tsirkin
788 7d37d351 Jan Kiszka
    /* Must unset vector notifier while guest notifier is still assigned */
789 a38b2c49 Michael S. Tsirkin
    if ((proxy->vector_irqfd || vdev->guest_notifier_mask) && !assign) {
790 7d37d351 Jan Kiszka
        msix_unset_vector_notifiers(&proxy->pci_dev);
791 a38b2c49 Michael S. Tsirkin
        if (proxy->vector_irqfd) {
792 a38b2c49 Michael S. Tsirkin
            kvm_virtio_pci_vector_release(proxy, nvqs);
793 a38b2c49 Michael S. Tsirkin
            g_free(proxy->vector_irqfd);
794 a38b2c49 Michael S. Tsirkin
            proxy->vector_irqfd = NULL;
795 a38b2c49 Michael S. Tsirkin
        }
796 7d37d351 Jan Kiszka
    }
797 7d37d351 Jan Kiszka
798 2d620f59 Michael S. Tsirkin
    for (n = 0; n < nvqs; n++) {
799 54dd9321 Michael S. Tsirkin
        if (!virtio_queue_get_num(vdev, n)) {
800 54dd9321 Michael S. Tsirkin
            break;
801 54dd9321 Michael S. Tsirkin
        }
802 54dd9321 Michael S. Tsirkin
803 89d62be9 Michael S. Tsirkin
        r = virtio_pci_set_guest_notifier(d, n, assign,
804 89d62be9 Michael S. Tsirkin
                                          kvm_msi_via_irqfd_enabled());
805 54dd9321 Michael S. Tsirkin
        if (r < 0) {
806 54dd9321 Michael S. Tsirkin
            goto assign_error;
807 54dd9321 Michael S. Tsirkin
        }
808 54dd9321 Michael S. Tsirkin
    }
809 54dd9321 Michael S. Tsirkin
810 7d37d351 Jan Kiszka
    /* Must set vector notifier after guest notifier has been assigned */
811 a38b2c49 Michael S. Tsirkin
    if ((with_irqfd || vdev->guest_notifier_mask) && assign) {
812 a38b2c49 Michael S. Tsirkin
        if (with_irqfd) {
813 a38b2c49 Michael S. Tsirkin
            proxy->vector_irqfd =
814 a38b2c49 Michael S. Tsirkin
                g_malloc0(sizeof(*proxy->vector_irqfd) *
815 a38b2c49 Michael S. Tsirkin
                          msix_nr_vectors_allocated(&proxy->pci_dev));
816 a38b2c49 Michael S. Tsirkin
            r = kvm_virtio_pci_vector_use(proxy, nvqs);
817 a38b2c49 Michael S. Tsirkin
            if (r < 0) {
818 a38b2c49 Michael S. Tsirkin
                goto assign_error;
819 a38b2c49 Michael S. Tsirkin
            }
820 774345f9 Michael S. Tsirkin
        }
821 7d37d351 Jan Kiszka
        r = msix_set_vector_notifiers(&proxy->pci_dev,
822 a38b2c49 Michael S. Tsirkin
                                      virtio_pci_vector_unmask,
823 a38b2c49 Michael S. Tsirkin
                                      virtio_pci_vector_mask,
824 a38b2c49 Michael S. Tsirkin
                                      virtio_pci_vector_poll);
825 7d37d351 Jan Kiszka
        if (r < 0) {
826 774345f9 Michael S. Tsirkin
            goto notifiers_error;
827 7d37d351 Jan Kiszka
        }
828 7d37d351 Jan Kiszka
    }
829 7d37d351 Jan Kiszka
830 54dd9321 Michael S. Tsirkin
    return 0;
831 54dd9321 Michael S. Tsirkin
832 774345f9 Michael S. Tsirkin
notifiers_error:
833 a38b2c49 Michael S. Tsirkin
    if (with_irqfd) {
834 a38b2c49 Michael S. Tsirkin
        assert(assign);
835 a38b2c49 Michael S. Tsirkin
        kvm_virtio_pci_vector_release(proxy, nvqs);
836 a38b2c49 Michael S. Tsirkin
    }
837 774345f9 Michael S. Tsirkin
838 54dd9321 Michael S. Tsirkin
assign_error:
839 54dd9321 Michael S. Tsirkin
    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
840 7d37d351 Jan Kiszka
    assert(assign);
841 54dd9321 Michael S. Tsirkin
    while (--n >= 0) {
842 89d62be9 Michael S. Tsirkin
        virtio_pci_set_guest_notifier(d, n, !assign, with_irqfd);
843 54dd9321 Michael S. Tsirkin
    }
844 54dd9321 Michael S. Tsirkin
    return r;
845 54dd9321 Michael S. Tsirkin
}
846 54dd9321 Michael S. Tsirkin
847 d2a0ccc6 Michael S. Tsirkin
static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign)
848 ade80dc8 Michael S. Tsirkin
{
849 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
850 25db9ebe Stefan Hajnoczi
851 25db9ebe Stefan Hajnoczi
    /* Stop using ioeventfd for virtqueue kick if the device starts using host
852 25db9ebe Stefan Hajnoczi
     * notifiers.  This makes it easy to avoid stepping on each others' toes.
853 25db9ebe Stefan Hajnoczi
     */
854 25db9ebe Stefan Hajnoczi
    proxy->ioeventfd_disabled = assign;
855 ade80dc8 Michael S. Tsirkin
    if (assign) {
856 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
857 25db9ebe Stefan Hajnoczi
    }
858 25db9ebe Stefan Hajnoczi
    /* We don't need to start here: it's not needed because backend
859 25db9ebe Stefan Hajnoczi
     * currently only stops on status change away from ok,
860 25db9ebe Stefan Hajnoczi
     * reset, vmstop and such. If we do add code to start here,
861 25db9ebe Stefan Hajnoczi
     * need to check vmstate, device state etc. */
862 26b9b5fe Paolo Bonzini
    return virtio_pci_set_host_notifier_internal(proxy, n, assign, false);
863 25db9ebe Stefan Hajnoczi
}
864 25db9ebe Stefan Hajnoczi
865 d2a0ccc6 Michael S. Tsirkin
static void virtio_pci_vmstate_change(DeviceState *d, bool running)
866 25db9ebe Stefan Hajnoczi
{
867 d2a0ccc6 Michael S. Tsirkin
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
868 25db9ebe Stefan Hajnoczi
869 25db9ebe Stefan Hajnoczi
    if (running) {
870 89c473fd Michael S. Tsirkin
        /* Try to find out if the guest has bus master disabled, but is
871 89c473fd Michael S. Tsirkin
           in ready state. Then we have a buggy guest OS. */
872 89c473fd Michael S. Tsirkin
        if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
873 89c473fd Michael S. Tsirkin
            !(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
874 89c473fd Michael S. Tsirkin
            proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
875 89c473fd Michael S. Tsirkin
        }
876 25db9ebe Stefan Hajnoczi
        virtio_pci_start_ioeventfd(proxy);
877 ade80dc8 Michael S. Tsirkin
    } else {
878 25db9ebe Stefan Hajnoczi
        virtio_pci_stop_ioeventfd(proxy);
879 ade80dc8 Michael S. Tsirkin
    }
880 ade80dc8 Michael S. Tsirkin
}
881 ade80dc8 Michael S. Tsirkin
882 53c25cea Paul Brook
static const VirtIOBindings virtio_pci_bindings = {
883 ff24bd58 Michael S. Tsirkin
    .notify = virtio_pci_notify,
884 ff24bd58 Michael S. Tsirkin
    .save_config = virtio_pci_save_config,
885 ff24bd58 Michael S. Tsirkin
    .load_config = virtio_pci_load_config,
886 ff24bd58 Michael S. Tsirkin
    .save_queue = virtio_pci_save_queue,
887 ff24bd58 Michael S. Tsirkin
    .load_queue = virtio_pci_load_queue,
888 6d74ca5a Michael S. Tsirkin
    .get_features = virtio_pci_get_features,
889 5430a28f mst@redhat.com
    .query_guest_notifiers = virtio_pci_query_guest_notifiers,
890 ade80dc8 Michael S. Tsirkin
    .set_host_notifier = virtio_pci_set_host_notifier,
891 54dd9321 Michael S. Tsirkin
    .set_guest_notifiers = virtio_pci_set_guest_notifiers,
892 25db9ebe Stefan Hajnoczi
    .vmstate_change = virtio_pci_vmstate_change,
893 53c25cea Paul Brook
};
894 53c25cea Paul Brook
895 befeac45 Michael S. Tsirkin
void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
896 53c25cea Paul Brook
{
897 53c25cea Paul Brook
    uint8_t *config;
898 53c25cea Paul Brook
    uint32_t size;
899 53c25cea Paul Brook
900 53c25cea Paul Brook
    proxy->vdev = vdev;
901 53c25cea Paul Brook
902 53c25cea Paul Brook
    config = proxy->pci_dev.config;
903 53c25cea Paul Brook
904 e75ccf2c Isaku Yamahata
    if (proxy->class_code) {
905 e75ccf2c Isaku Yamahata
        pci_config_set_class(config, proxy->class_code);
906 e75ccf2c Isaku Yamahata
    }
907 ad3d11e6 Hui Kai Ran
    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
908 ad3d11e6 Hui Kai Ran
                 pci_get_word(config + PCI_VENDOR_ID));
909 ad3d11e6 Hui Kai Ran
    pci_set_word(config + PCI_SUBSYSTEM_ID, vdev->device_id);
910 ad3d11e6 Hui Kai Ran
    config[PCI_INTERRUPT_PIN] = 1;
911 53c25cea Paul Brook
912 b2357c48 Alex Williamson
    if (vdev->nvectors &&
913 b2357c48 Alex Williamson
        msix_init_exclusive_bar(&proxy->pci_dev, vdev->nvectors, 1)) {
914 aba800a3 Michael S. Tsirkin
        vdev->nvectors = 0;
915 b2357c48 Alex Williamson
    }
916 aba800a3 Michael S. Tsirkin
917 ed757e14 Yan Vugenfirer
    proxy->pci_dev.config_write = virtio_write_config;
918 ed757e14 Yan Vugenfirer
919 aba800a3 Michael S. Tsirkin
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + vdev->config_len;
920 53c25cea Paul Brook
    if (size & (size-1))
921 53c25cea Paul Brook
        size = 1 << qemu_fls(size);
922 53c25cea Paul Brook
923 da146d0a Avi Kivity
    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
924 da146d0a Avi Kivity
                          "virtio-pci", size);
925 e824b2cc Avi Kivity
    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
926 e824b2cc Avi Kivity
                     &proxy->bar);
927 53c25cea Paul Brook
928 25db9ebe Stefan Hajnoczi
    if (!kvm_has_many_ioeventfds()) {
929 25db9ebe Stefan Hajnoczi
        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
930 25db9ebe Stefan Hajnoczi
    }
931 25db9ebe Stefan Hajnoczi
932 d2a0ccc6 Michael S. Tsirkin
    virtio_bind_device(vdev, &virtio_pci_bindings, DEVICE(proxy));
933 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
934 8172539d Michael S. Tsirkin
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
935 8172539d Michael S. Tsirkin
    proxy->host_features = vdev->get_features(vdev, proxy->host_features);
936 53c25cea Paul Brook
}
937 53c25cea Paul Brook
938 f90c2bcd Alex Williamson
static void virtio_exit_pci(PCIDevice *pci_dev)
939 0f457d91 Michael S. Tsirkin
{
940 da146d0a Avi Kivity
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
941 da146d0a Avi Kivity
942 da146d0a Avi Kivity
    memory_region_destroy(&proxy->bar);
943 b2357c48 Alex Williamson
    msix_uninit_exclusive_bar(pci_dev);
944 0f457d91 Michael S. Tsirkin
}
945 0f457d91 Michael S. Tsirkin
946 16c915ba Amit Shah
static int virtio_rng_init_pci(PCIDevice *pci_dev)
947 16c915ba Amit Shah
{
948 16c915ba Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
949 16c915ba Amit Shah
    VirtIODevice *vdev;
950 16c915ba Amit Shah
951 500054f1 Anthony Liguori
    if (proxy->rng.rng == NULL) {
952 500054f1 Anthony Liguori
        proxy->rng.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
953 500054f1 Anthony Liguori
954 500054f1 Anthony Liguori
        object_property_add_child(OBJECT(pci_dev),
955 500054f1 Anthony Liguori
                                  "default-backend",
956 500054f1 Anthony Liguori
                                  OBJECT(proxy->rng.default_backend),
957 500054f1 Anthony Liguori
                                  NULL);
958 500054f1 Anthony Liguori
959 500054f1 Anthony Liguori
        object_property_set_link(OBJECT(pci_dev),
960 500054f1 Anthony Liguori
                                 OBJECT(proxy->rng.default_backend),
961 500054f1 Anthony Liguori
                                 "rng", NULL);
962 500054f1 Anthony Liguori
    }
963 500054f1 Anthony Liguori
964 16c915ba Amit Shah
    vdev = virtio_rng_init(&pci_dev->qdev, &proxy->rng);
965 16c915ba Amit Shah
    if (!vdev) {
966 16c915ba Amit Shah
        return -1;
967 16c915ba Amit Shah
    }
968 16c915ba Amit Shah
    virtio_init_pci(proxy, vdev);
969 16c915ba Amit Shah
    return 0;
970 16c915ba Amit Shah
}
971 16c915ba Amit Shah
972 16c915ba Amit Shah
static void virtio_rng_exit_pci(PCIDevice *pci_dev)
973 16c915ba Amit Shah
{
974 16c915ba Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
975 16c915ba Amit Shah
976 16c915ba Amit Shah
    virtio_pci_stop_ioeventfd(proxy);
977 16c915ba Amit Shah
    virtio_rng_exit(proxy->vdev);
978 16c915ba Amit Shah
    virtio_exit_pci(pci_dev);
979 16c915ba Amit Shah
}
980 16c915ba Amit Shah
981 16c915ba Amit Shah
static void virtio_rng_initfn(Object *obj)
982 16c915ba Amit Shah
{
983 16c915ba Amit Shah
    PCIDevice *pci_dev = PCI_DEVICE(obj);
984 16c915ba Amit Shah
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
985 16c915ba Amit Shah
986 16c915ba Amit Shah
    object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
987 16c915ba Amit Shah
                             (Object **)&proxy->rng.rng, NULL);
988 16c915ba Amit Shah
}
989 16c915ba Amit Shah
990 16c915ba Amit Shah
static Property virtio_rng_properties[] = {
991 16c915ba Amit Shah
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
992 904d6f58 Anthony Liguori
    /* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s.  If
993 904d6f58 Anthony Liguori
       you have an entropy source capable of generating more entropy than this
994 904d6f58 Anthony Liguori
       and you can pass it through via virtio-rng, then hats off to you.  Until
995 904d6f58 Anthony Liguori
       then, this is unlimited for all practical purposes.
996 904d6f58 Anthony Liguori
    */
997 904d6f58 Anthony Liguori
    DEFINE_PROP_UINT64("max-bytes", VirtIOPCIProxy, rng.max_bytes, INT64_MAX),
998 904d6f58 Anthony Liguori
    DEFINE_PROP_UINT32("period", VirtIOPCIProxy, rng.period_ms, 1 << 16),
999 16c915ba Amit Shah
    DEFINE_PROP_END_OF_LIST(),
1000 16c915ba Amit Shah
};
1001 16c915ba Amit Shah
1002 16c915ba Amit Shah
static void virtio_rng_class_init(ObjectClass *klass, void *data)
1003 16c915ba Amit Shah
{
1004 16c915ba Amit Shah
    DeviceClass *dc = DEVICE_CLASS(klass);
1005 16c915ba Amit Shah
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1006 16c915ba Amit Shah
1007 16c915ba Amit Shah
    k->init = virtio_rng_init_pci;
1008 16c915ba Amit Shah
    k->exit = virtio_rng_exit_pci;
1009 16c915ba Amit Shah
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1010 16c915ba Amit Shah
    k->device_id = PCI_DEVICE_ID_VIRTIO_RNG;
1011 16c915ba Amit Shah
    k->revision = VIRTIO_PCI_ABI_VERSION;
1012 16c915ba Amit Shah
    k->class_id = PCI_CLASS_OTHERS;
1013 16c915ba Amit Shah
    dc->reset = virtio_pci_reset;
1014 16c915ba Amit Shah
    dc->props = virtio_rng_properties;
1015 16c915ba Amit Shah
}
1016 16c915ba Amit Shah
1017 8c43a6f0 Andreas Färber
static const TypeInfo virtio_rng_info = {
1018 16c915ba Amit Shah
    .name          = "virtio-rng-pci",
1019 16c915ba Amit Shah
    .parent        = TYPE_PCI_DEVICE,
1020 16c915ba Amit Shah
    .instance_size = sizeof(VirtIOPCIProxy),
1021 16c915ba Amit Shah
    .instance_init = virtio_rng_initfn,
1022 16c915ba Amit Shah
    .class_init    = virtio_rng_class_init,
1023 16c915ba Amit Shah
};
1024 16c915ba Amit Shah
1025 60653b28 Paolo Bonzini
#ifdef CONFIG_VIRTFS
1026 60653b28 Paolo Bonzini
static int virtio_9p_init_pci(PCIDevice *pci_dev)
1027 60653b28 Paolo Bonzini
{
1028 60653b28 Paolo Bonzini
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
1029 60653b28 Paolo Bonzini
    VirtIODevice *vdev;
1030 60653b28 Paolo Bonzini
1031 60653b28 Paolo Bonzini
    vdev = virtio_9p_init(&pci_dev->qdev, &proxy->fsconf);
1032 60653b28 Paolo Bonzini
    vdev->nvectors = proxy->nvectors;
1033 60653b28 Paolo Bonzini
    virtio_init_pci(proxy, vdev);
1034 60653b28 Paolo Bonzini
    /* make the actual value visible */
1035 60653b28 Paolo Bonzini
    proxy->nvectors = vdev->nvectors;
1036 60653b28 Paolo Bonzini
    return 0;
1037 60653b28 Paolo Bonzini
}
1038 60653b28 Paolo Bonzini
1039 60653b28 Paolo Bonzini
static Property virtio_9p_properties[] = {
1040 60653b28 Paolo Bonzini
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
1041 60653b28 Paolo Bonzini
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
1042 60653b28 Paolo Bonzini
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
1043 60653b28 Paolo Bonzini
    DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
1044 60653b28 Paolo Bonzini
    DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id),
1045 60653b28 Paolo Bonzini
    DEFINE_PROP_END_OF_LIST(),
1046 60653b28 Paolo Bonzini
};
1047 60653b28 Paolo Bonzini
1048 60653b28 Paolo Bonzini
static void virtio_9p_class_init(ObjectClass *klass, void *data)
1049 60653b28 Paolo Bonzini
{
1050 60653b28 Paolo Bonzini
    DeviceClass *dc = DEVICE_CLASS(klass);
1051 60653b28 Paolo Bonzini
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1052 60653b28 Paolo Bonzini
1053 60653b28 Paolo Bonzini
    k->init = virtio_9p_init_pci;
1054 60653b28 Paolo Bonzini
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1055 60653b28 Paolo Bonzini
    k->device_id = PCI_DEVICE_ID_VIRTIO_9P;
1056 60653b28 Paolo Bonzini
    k->revision = VIRTIO_PCI_ABI_VERSION;
1057 60653b28 Paolo Bonzini
    k->class_id = 0x2;
1058 60653b28 Paolo Bonzini
    dc->props = virtio_9p_properties;
1059 60653b28 Paolo Bonzini
    dc->reset = virtio_pci_reset;
1060 60653b28 Paolo Bonzini
}
1061 60653b28 Paolo Bonzini
1062 60653b28 Paolo Bonzini
static const TypeInfo virtio_9p_info = {
1063 60653b28 Paolo Bonzini
    .name          = "virtio-9p-pci",
1064 60653b28 Paolo Bonzini
    .parent        = TYPE_PCI_DEVICE,
1065 60653b28 Paolo Bonzini
    .instance_size = sizeof(VirtIOPCIProxy),
1066 60653b28 Paolo Bonzini
    .class_init    = virtio_9p_class_init,
1067 60653b28 Paolo Bonzini
};
1068 60653b28 Paolo Bonzini
#endif
1069 60653b28 Paolo Bonzini
1070 085bccb7 KONRAD Frederic
/*
1071 085bccb7 KONRAD Frederic
 * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
1072 085bccb7 KONRAD Frederic
 */
1073 085bccb7 KONRAD Frederic
1074 085bccb7 KONRAD Frederic
/* This is called by virtio-bus just after the device is plugged. */
1075 085bccb7 KONRAD Frederic
static void virtio_pci_device_plugged(DeviceState *d)
1076 085bccb7 KONRAD Frederic
{
1077 085bccb7 KONRAD Frederic
    VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
1078 085bccb7 KONRAD Frederic
    VirtioBusState *bus = &proxy->bus;
1079 085bccb7 KONRAD Frederic
    uint8_t *config;
1080 085bccb7 KONRAD Frederic
    uint32_t size;
1081 085bccb7 KONRAD Frederic
1082 085bccb7 KONRAD Frederic
    proxy->vdev = bus->vdev;
1083 085bccb7 KONRAD Frederic
1084 085bccb7 KONRAD Frederic
    config = proxy->pci_dev.config;
1085 085bccb7 KONRAD Frederic
    if (proxy->class_code) {
1086 085bccb7 KONRAD Frederic
        pci_config_set_class(config, proxy->class_code);
1087 085bccb7 KONRAD Frederic
    }
1088 085bccb7 KONRAD Frederic
    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
1089 085bccb7 KONRAD Frederic
                 pci_get_word(config + PCI_VENDOR_ID));
1090 085bccb7 KONRAD Frederic
    pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus));
1091 085bccb7 KONRAD Frederic
    config[PCI_INTERRUPT_PIN] = 1;
1092 085bccb7 KONRAD Frederic
1093 085bccb7 KONRAD Frederic
    if (proxy->nvectors &&
1094 085bccb7 KONRAD Frederic
        msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) {
1095 085bccb7 KONRAD Frederic
        proxy->nvectors = 0;
1096 085bccb7 KONRAD Frederic
    }
1097 085bccb7 KONRAD Frederic
1098 085bccb7 KONRAD Frederic
    proxy->pci_dev.config_write = virtio_write_config;
1099 085bccb7 KONRAD Frederic
1100 085bccb7 KONRAD Frederic
    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev)
1101 085bccb7 KONRAD Frederic
         + virtio_bus_get_vdev_config_len(bus);
1102 085bccb7 KONRAD Frederic
    if (size & (size - 1)) {
1103 085bccb7 KONRAD Frederic
        size = 1 << qemu_fls(size);
1104 085bccb7 KONRAD Frederic
    }
1105 085bccb7 KONRAD Frederic
1106 085bccb7 KONRAD Frederic
    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
1107 085bccb7 KONRAD Frederic
                          "virtio-pci", size);
1108 085bccb7 KONRAD Frederic
    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
1109 085bccb7 KONRAD Frederic
                     &proxy->bar);
1110 085bccb7 KONRAD Frederic
1111 085bccb7 KONRAD Frederic
    if (!kvm_has_many_ioeventfds()) {
1112 085bccb7 KONRAD Frederic
        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
1113 085bccb7 KONRAD Frederic
    }
1114 085bccb7 KONRAD Frederic
1115 085bccb7 KONRAD Frederic
    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
1116 085bccb7 KONRAD Frederic
    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
1117 085bccb7 KONRAD Frederic
    proxy->host_features = virtio_bus_get_vdev_features(bus,
1118 085bccb7 KONRAD Frederic
                                                      proxy->host_features);
1119 085bccb7 KONRAD Frederic
}
1120 085bccb7 KONRAD Frederic
1121 085bccb7 KONRAD Frederic
static int virtio_pci_init(PCIDevice *pci_dev)
1122 085bccb7 KONRAD Frederic
{
1123 085bccb7 KONRAD Frederic
    VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
1124 085bccb7 KONRAD Frederic
    VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev);
1125 085bccb7 KONRAD Frederic
    virtio_pci_bus_new(&dev->bus, dev);
1126 085bccb7 KONRAD Frederic
    if (k->init != NULL) {
1127 085bccb7 KONRAD Frederic
        return k->init(dev);
1128 085bccb7 KONRAD Frederic
    }
1129 085bccb7 KONRAD Frederic
    return 0;
1130 085bccb7 KONRAD Frederic
}
1131 085bccb7 KONRAD Frederic
1132 085bccb7 KONRAD Frederic
static void virtio_pci_exit(PCIDevice *pci_dev)
1133 085bccb7 KONRAD Frederic
{
1134 085bccb7 KONRAD Frederic
    VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
1135 10479a80 KONRAD Frederic
    virtio_pci_stop_ioeventfd(proxy);
1136 085bccb7 KONRAD Frederic
    virtio_exit_pci(pci_dev);
1137 085bccb7 KONRAD Frederic
}
1138 085bccb7 KONRAD Frederic
1139 085bccb7 KONRAD Frederic
/*
1140 085bccb7 KONRAD Frederic
 * This will be renamed virtio_pci_reset at the end of the series.
1141 085bccb7 KONRAD Frederic
 * virtio_pci_reset is still in use at this moment.
1142 085bccb7 KONRAD Frederic
 */
1143 085bccb7 KONRAD Frederic
static void virtio_pci_rst(DeviceState *qdev)
1144 085bccb7 KONRAD Frederic
{
1145 085bccb7 KONRAD Frederic
    VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev);
1146 085bccb7 KONRAD Frederic
    VirtioBusState *bus = VIRTIO_BUS(&proxy->bus);
1147 085bccb7 KONRAD Frederic
    virtio_pci_stop_ioeventfd(proxy);
1148 085bccb7 KONRAD Frederic
    virtio_bus_reset(bus);
1149 085bccb7 KONRAD Frederic
    msix_unuse_all_vectors(&proxy->pci_dev);
1150 085bccb7 KONRAD Frederic
    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
1151 085bccb7 KONRAD Frederic
}
1152 085bccb7 KONRAD Frederic
1153 085bccb7 KONRAD Frederic
static void virtio_pci_class_init(ObjectClass *klass, void *data)
1154 085bccb7 KONRAD Frederic
{
1155 085bccb7 KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1156 085bccb7 KONRAD Frederic
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1157 085bccb7 KONRAD Frederic
1158 085bccb7 KONRAD Frederic
    k->init = virtio_pci_init;
1159 085bccb7 KONRAD Frederic
    k->exit = virtio_pci_exit;
1160 085bccb7 KONRAD Frederic
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1161 085bccb7 KONRAD Frederic
    k->revision = VIRTIO_PCI_ABI_VERSION;
1162 085bccb7 KONRAD Frederic
    k->class_id = PCI_CLASS_OTHERS;
1163 085bccb7 KONRAD Frederic
    dc->reset = virtio_pci_rst;
1164 085bccb7 KONRAD Frederic
}
1165 085bccb7 KONRAD Frederic
1166 085bccb7 KONRAD Frederic
static const TypeInfo virtio_pci_info = {
1167 085bccb7 KONRAD Frederic
    .name          = TYPE_VIRTIO_PCI,
1168 085bccb7 KONRAD Frederic
    .parent        = TYPE_PCI_DEVICE,
1169 085bccb7 KONRAD Frederic
    .instance_size = sizeof(VirtIOPCIProxy),
1170 085bccb7 KONRAD Frederic
    .class_init    = virtio_pci_class_init,
1171 085bccb7 KONRAD Frederic
    .class_size    = sizeof(VirtioPCIClass),
1172 085bccb7 KONRAD Frederic
    .abstract      = true,
1173 085bccb7 KONRAD Frederic
};
1174 085bccb7 KONRAD Frederic
1175 653ced07 KONRAD Frederic
/* virtio-blk-pci */
1176 653ced07 KONRAD Frederic
1177 653ced07 KONRAD Frederic
static Property virtio_blk_pci_properties[] = {
1178 653ced07 KONRAD Frederic
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
1179 653ced07 KONRAD Frederic
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
1180 653ced07 KONRAD Frederic
                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
1181 653ced07 KONRAD Frederic
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
1182 653ced07 KONRAD Frederic
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
1183 653ced07 KONRAD Frederic
    DEFINE_PROP_BIT("x-data-plane", VirtIOBlkPCI, blk.data_plane, 0, false),
1184 653ced07 KONRAD Frederic
#endif
1185 653ced07 KONRAD Frederic
    DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
1186 653ced07 KONRAD Frederic
    DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkPCI, blk),
1187 653ced07 KONRAD Frederic
    DEFINE_PROP_END_OF_LIST(),
1188 653ced07 KONRAD Frederic
};
1189 653ced07 KONRAD Frederic
1190 653ced07 KONRAD Frederic
static int virtio_blk_pci_init(VirtIOPCIProxy *vpci_dev)
1191 653ced07 KONRAD Frederic
{
1192 653ced07 KONRAD Frederic
    VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev);
1193 653ced07 KONRAD Frederic
    DeviceState *vdev = DEVICE(&dev->vdev);
1194 653ced07 KONRAD Frederic
    virtio_blk_set_conf(vdev, &(dev->blk));
1195 653ced07 KONRAD Frederic
    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
1196 653ced07 KONRAD Frederic
    if (qdev_init(vdev) < 0) {
1197 653ced07 KONRAD Frederic
        return -1;
1198 653ced07 KONRAD Frederic
    }
1199 653ced07 KONRAD Frederic
    return 0;
1200 653ced07 KONRAD Frederic
}
1201 653ced07 KONRAD Frederic
1202 653ced07 KONRAD Frederic
static void virtio_blk_pci_class_init(ObjectClass *klass, void *data)
1203 653ced07 KONRAD Frederic
{
1204 653ced07 KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1205 653ced07 KONRAD Frederic
    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
1206 653ced07 KONRAD Frederic
    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
1207 653ced07 KONRAD Frederic
1208 653ced07 KONRAD Frederic
    dc->props = virtio_blk_pci_properties;
1209 653ced07 KONRAD Frederic
    k->init = virtio_blk_pci_init;
1210 653ced07 KONRAD Frederic
    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1211 653ced07 KONRAD Frederic
    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BLOCK;
1212 653ced07 KONRAD Frederic
    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
1213 653ced07 KONRAD Frederic
    pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI;
1214 653ced07 KONRAD Frederic
}
1215 653ced07 KONRAD Frederic
1216 653ced07 KONRAD Frederic
static void virtio_blk_pci_instance_init(Object *obj)
1217 653ced07 KONRAD Frederic
{
1218 653ced07 KONRAD Frederic
    VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj);
1219 653ced07 KONRAD Frederic
    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK);
1220 653ced07 KONRAD Frederic
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
1221 653ced07 KONRAD Frederic
}
1222 653ced07 KONRAD Frederic
1223 653ced07 KONRAD Frederic
static const TypeInfo virtio_blk_pci_info = {
1224 653ced07 KONRAD Frederic
    .name          = TYPE_VIRTIO_BLK_PCI,
1225 653ced07 KONRAD Frederic
    .parent        = TYPE_VIRTIO_PCI,
1226 653ced07 KONRAD Frederic
    .instance_size = sizeof(VirtIOBlkPCI),
1227 653ced07 KONRAD Frederic
    .instance_init = virtio_blk_pci_instance_init,
1228 653ced07 KONRAD Frederic
    .class_init    = virtio_blk_pci_class_init,
1229 653ced07 KONRAD Frederic
};
1230 653ced07 KONRAD Frederic
1231 bc7b90a0 KONRAD Frederic
/* virtio-scsi-pci */
1232 bc7b90a0 KONRAD Frederic
1233 bc7b90a0 KONRAD Frederic
static Property virtio_scsi_pci_properties[] = {
1234 bc7b90a0 KONRAD Frederic
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
1235 bc7b90a0 KONRAD Frederic
                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
1236 bc7b90a0 KONRAD Frederic
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
1237 bc7b90a0 KONRAD Frederic
                       DEV_NVECTORS_UNSPECIFIED),
1238 bc7b90a0 KONRAD Frederic
    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
1239 bc7b90a0 KONRAD Frederic
    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIPCI, vdev.conf),
1240 bc7b90a0 KONRAD Frederic
    DEFINE_PROP_END_OF_LIST(),
1241 bc7b90a0 KONRAD Frederic
};
1242 bc7b90a0 KONRAD Frederic
1243 bc7b90a0 KONRAD Frederic
static int virtio_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev)
1244 bc7b90a0 KONRAD Frederic
{
1245 bc7b90a0 KONRAD Frederic
    VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
1246 bc7b90a0 KONRAD Frederic
    DeviceState *vdev = DEVICE(&dev->vdev);
1247 bc7b90a0 KONRAD Frederic
1248 bc7b90a0 KONRAD Frederic
    if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
1249 bc7b90a0 KONRAD Frederic
        vpci_dev->nvectors = dev->vdev.conf.num_queues + 3;
1250 bc7b90a0 KONRAD Frederic
    }
1251 bc7b90a0 KONRAD Frederic
1252 bc7b90a0 KONRAD Frederic
    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
1253 bc7b90a0 KONRAD Frederic
    if (qdev_init(vdev) < 0) {
1254 bc7b90a0 KONRAD Frederic
        return -1;
1255 bc7b90a0 KONRAD Frederic
    }
1256 bc7b90a0 KONRAD Frederic
    return 0;
1257 bc7b90a0 KONRAD Frederic
}
1258 bc7b90a0 KONRAD Frederic
1259 bc7b90a0 KONRAD Frederic
static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data)
1260 bc7b90a0 KONRAD Frederic
{
1261 bc7b90a0 KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1262 bc7b90a0 KONRAD Frederic
    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
1263 bc7b90a0 KONRAD Frederic
    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
1264 bc7b90a0 KONRAD Frederic
    k->init = virtio_scsi_pci_init_pci;
1265 bc7b90a0 KONRAD Frederic
    dc->props = virtio_scsi_pci_properties;
1266 bc7b90a0 KONRAD Frederic
    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1267 bc7b90a0 KONRAD Frederic
    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
1268 bc7b90a0 KONRAD Frederic
    pcidev_k->revision = 0x00;
1269 bc7b90a0 KONRAD Frederic
    pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI;
1270 bc7b90a0 KONRAD Frederic
}
1271 bc7b90a0 KONRAD Frederic
1272 bc7b90a0 KONRAD Frederic
static void virtio_scsi_pci_instance_init(Object *obj)
1273 bc7b90a0 KONRAD Frederic
{
1274 bc7b90a0 KONRAD Frederic
    VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj);
1275 bc7b90a0 KONRAD Frederic
    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
1276 bc7b90a0 KONRAD Frederic
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
1277 bc7b90a0 KONRAD Frederic
}
1278 bc7b90a0 KONRAD Frederic
1279 bc7b90a0 KONRAD Frederic
static const TypeInfo virtio_scsi_pci_info = {
1280 bc7b90a0 KONRAD Frederic
    .name          = TYPE_VIRTIO_SCSI_PCI,
1281 bc7b90a0 KONRAD Frederic
    .parent        = TYPE_VIRTIO_PCI,
1282 bc7b90a0 KONRAD Frederic
    .instance_size = sizeof(VirtIOSCSIPCI),
1283 bc7b90a0 KONRAD Frederic
    .instance_init = virtio_scsi_pci_instance_init,
1284 bc7b90a0 KONRAD Frederic
    .class_init    = virtio_scsi_pci_class_init,
1285 bc7b90a0 KONRAD Frederic
};
1286 bc7b90a0 KONRAD Frederic
1287 e378e88d KONRAD Frederic
/* virtio-balloon-pci */
1288 e378e88d KONRAD Frederic
1289 24a6e7f4 KONRAD Frederic
static void balloon_pci_stats_get_all(Object *obj, struct Visitor *v,
1290 24a6e7f4 KONRAD Frederic
                                      void *opaque, const char *name,
1291 24a6e7f4 KONRAD Frederic
                                      Error **errp)
1292 24a6e7f4 KONRAD Frederic
{
1293 24a6e7f4 KONRAD Frederic
    VirtIOBalloonPCI *dev = opaque;
1294 24a6e7f4 KONRAD Frederic
    object_property_get(OBJECT(&dev->vdev), v, "guest-stats", errp);
1295 24a6e7f4 KONRAD Frederic
}
1296 24a6e7f4 KONRAD Frederic
1297 24a6e7f4 KONRAD Frederic
static void balloon_pci_stats_get_poll_interval(Object *obj, struct Visitor *v,
1298 24a6e7f4 KONRAD Frederic
                                                void *opaque, const char *name,
1299 24a6e7f4 KONRAD Frederic
                                                Error **errp)
1300 24a6e7f4 KONRAD Frederic
{
1301 24a6e7f4 KONRAD Frederic
    VirtIOBalloonPCI *dev = opaque;
1302 24a6e7f4 KONRAD Frederic
    object_property_get(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
1303 24a6e7f4 KONRAD Frederic
                        errp);
1304 24a6e7f4 KONRAD Frederic
}
1305 24a6e7f4 KONRAD Frederic
1306 24a6e7f4 KONRAD Frederic
static void balloon_pci_stats_set_poll_interval(Object *obj, struct Visitor *v,
1307 24a6e7f4 KONRAD Frederic
                                                void *opaque, const char *name,
1308 24a6e7f4 KONRAD Frederic
                                                Error **errp)
1309 24a6e7f4 KONRAD Frederic
{
1310 24a6e7f4 KONRAD Frederic
    VirtIOBalloonPCI *dev = opaque;
1311 24a6e7f4 KONRAD Frederic
    object_property_set(OBJECT(&dev->vdev), v, "guest-stats-polling-interval",
1312 24a6e7f4 KONRAD Frederic
                        errp);
1313 24a6e7f4 KONRAD Frederic
}
1314 24a6e7f4 KONRAD Frederic
1315 e378e88d KONRAD Frederic
static Property virtio_balloon_pci_properties[] = {
1316 e378e88d KONRAD Frederic
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
1317 e378e88d KONRAD Frederic
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
1318 e378e88d KONRAD Frederic
    DEFINE_PROP_END_OF_LIST(),
1319 e378e88d KONRAD Frederic
};
1320 e378e88d KONRAD Frederic
1321 e378e88d KONRAD Frederic
static int virtio_balloon_pci_init(VirtIOPCIProxy *vpci_dev)
1322 e378e88d KONRAD Frederic
{
1323 e378e88d KONRAD Frederic
    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev);
1324 e378e88d KONRAD Frederic
    DeviceState *vdev = DEVICE(&dev->vdev);
1325 e378e88d KONRAD Frederic
1326 e378e88d KONRAD Frederic
    if (vpci_dev->class_code != PCI_CLASS_OTHERS &&
1327 e378e88d KONRAD Frederic
        vpci_dev->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
1328 e378e88d KONRAD Frederic
        vpci_dev->class_code = PCI_CLASS_OTHERS;
1329 e378e88d KONRAD Frederic
    }
1330 e378e88d KONRAD Frederic
1331 e378e88d KONRAD Frederic
    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
1332 e378e88d KONRAD Frederic
    if (qdev_init(vdev) < 0) {
1333 e378e88d KONRAD Frederic
        return -1;
1334 e378e88d KONRAD Frederic
    }
1335 e378e88d KONRAD Frederic
    return 0;
1336 e378e88d KONRAD Frederic
}
1337 e378e88d KONRAD Frederic
1338 e378e88d KONRAD Frederic
static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
1339 e378e88d KONRAD Frederic
{
1340 e378e88d KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1341 e378e88d KONRAD Frederic
    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
1342 e378e88d KONRAD Frederic
    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
1343 e378e88d KONRAD Frederic
    k->init = virtio_balloon_pci_init;
1344 e378e88d KONRAD Frederic
    dc->props = virtio_balloon_pci_properties;
1345 e378e88d KONRAD Frederic
    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1346 e378e88d KONRAD Frederic
    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
1347 e378e88d KONRAD Frederic
    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
1348 e378e88d KONRAD Frederic
    pcidev_k->class_id = PCI_CLASS_OTHERS;
1349 e378e88d KONRAD Frederic
}
1350 e378e88d KONRAD Frederic
1351 e378e88d KONRAD Frederic
static void virtio_balloon_pci_instance_init(Object *obj)
1352 e378e88d KONRAD Frederic
{
1353 e378e88d KONRAD Frederic
    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
1354 e378e88d KONRAD Frederic
    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON);
1355 e378e88d KONRAD Frederic
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
1356 24a6e7f4 KONRAD Frederic
1357 24a6e7f4 KONRAD Frederic
    object_property_add(obj, "guest-stats", "guest statistics",
1358 24a6e7f4 KONRAD Frederic
                        balloon_pci_stats_get_all, NULL, NULL, dev,
1359 24a6e7f4 KONRAD Frederic
                        NULL);
1360 24a6e7f4 KONRAD Frederic
1361 24a6e7f4 KONRAD Frederic
    object_property_add(obj, "guest-stats-polling-interval", "int",
1362 24a6e7f4 KONRAD Frederic
                        balloon_pci_stats_get_poll_interval,
1363 24a6e7f4 KONRAD Frederic
                        balloon_pci_stats_set_poll_interval,
1364 24a6e7f4 KONRAD Frederic
                        NULL, dev, NULL);
1365 e378e88d KONRAD Frederic
}
1366 e378e88d KONRAD Frederic
1367 e378e88d KONRAD Frederic
static const TypeInfo virtio_balloon_pci_info = {
1368 e378e88d KONRAD Frederic
    .name          = TYPE_VIRTIO_BALLOON_PCI,
1369 e378e88d KONRAD Frederic
    .parent        = TYPE_VIRTIO_PCI,
1370 e378e88d KONRAD Frederic
    .instance_size = sizeof(VirtIOBalloonPCI),
1371 e378e88d KONRAD Frederic
    .instance_init = virtio_balloon_pci_instance_init,
1372 e378e88d KONRAD Frederic
    .class_init    = virtio_balloon_pci_class_init,
1373 e378e88d KONRAD Frederic
};
1374 e378e88d KONRAD Frederic
1375 f7f7464a KONRAD Frederic
/* virtio-serial-pci */
1376 f7f7464a KONRAD Frederic
1377 f7f7464a KONRAD Frederic
static int virtio_serial_pci_init(VirtIOPCIProxy *vpci_dev)
1378 f7f7464a KONRAD Frederic
{
1379 f7f7464a KONRAD Frederic
    VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(vpci_dev);
1380 f7f7464a KONRAD Frederic
    DeviceState *vdev = DEVICE(&dev->vdev);
1381 f7f7464a KONRAD Frederic
1382 f7f7464a KONRAD Frederic
    if (vpci_dev->class_code != PCI_CLASS_COMMUNICATION_OTHER &&
1383 f7f7464a KONRAD Frederic
        vpci_dev->class_code != PCI_CLASS_DISPLAY_OTHER && /* qemu 0.10 */
1384 f7f7464a KONRAD Frederic
        vpci_dev->class_code != PCI_CLASS_OTHERS) {        /* qemu-kvm  */
1385 f7f7464a KONRAD Frederic
            vpci_dev->class_code = PCI_CLASS_COMMUNICATION_OTHER;
1386 f7f7464a KONRAD Frederic
    }
1387 f7f7464a KONRAD Frederic
1388 f7f7464a KONRAD Frederic
    /* backwards-compatibility with machines that were created with
1389 f7f7464a KONRAD Frederic
       DEV_NVECTORS_UNSPECIFIED */
1390 f7f7464a KONRAD Frederic
    if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
1391 f7f7464a KONRAD Frederic
        vpci_dev->nvectors = dev->vdev.serial.max_virtserial_ports + 1;
1392 f7f7464a KONRAD Frederic
    }
1393 f7f7464a KONRAD Frederic
1394 f7f7464a KONRAD Frederic
    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
1395 f7f7464a KONRAD Frederic
    if (qdev_init(vdev) < 0) {
1396 f7f7464a KONRAD Frederic
        return -1;
1397 f7f7464a KONRAD Frederic
    }
1398 f7f7464a KONRAD Frederic
    return 0;
1399 f7f7464a KONRAD Frederic
}
1400 f7f7464a KONRAD Frederic
1401 f7f7464a KONRAD Frederic
static Property virtio_serial_pci_properties[] = {
1402 f7f7464a KONRAD Frederic
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
1403 f7f7464a KONRAD Frederic
                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
1404 f7f7464a KONRAD Frederic
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
1405 f7f7464a KONRAD Frederic
    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
1406 f7f7464a KONRAD Frederic
    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
1407 f7f7464a KONRAD Frederic
    DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerialPCI, vdev.serial),
1408 f7f7464a KONRAD Frederic
    DEFINE_PROP_END_OF_LIST(),
1409 f7f7464a KONRAD Frederic
};
1410 f7f7464a KONRAD Frederic
1411 f7f7464a KONRAD Frederic
static void virtio_serial_pci_class_init(ObjectClass *klass, void *data)
1412 f7f7464a KONRAD Frederic
{
1413 f7f7464a KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1414 f7f7464a KONRAD Frederic
    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
1415 f7f7464a KONRAD Frederic
    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
1416 f7f7464a KONRAD Frederic
    k->init = virtio_serial_pci_init;
1417 f7f7464a KONRAD Frederic
    dc->props = virtio_serial_pci_properties;
1418 f7f7464a KONRAD Frederic
    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1419 f7f7464a KONRAD Frederic
    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
1420 f7f7464a KONRAD Frederic
    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
1421 f7f7464a KONRAD Frederic
    pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
1422 f7f7464a KONRAD Frederic
}
1423 f7f7464a KONRAD Frederic
1424 f7f7464a KONRAD Frederic
static void virtio_serial_pci_instance_init(Object *obj)
1425 f7f7464a KONRAD Frederic
{
1426 f7f7464a KONRAD Frederic
    VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj);
1427 f7f7464a KONRAD Frederic
    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SERIAL);
1428 f7f7464a KONRAD Frederic
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
1429 f7f7464a KONRAD Frederic
}
1430 f7f7464a KONRAD Frederic
1431 f7f7464a KONRAD Frederic
static const TypeInfo virtio_serial_pci_info = {
1432 f7f7464a KONRAD Frederic
    .name          = TYPE_VIRTIO_SERIAL_PCI,
1433 f7f7464a KONRAD Frederic
    .parent        = TYPE_VIRTIO_PCI,
1434 f7f7464a KONRAD Frederic
    .instance_size = sizeof(VirtIOSerialPCI),
1435 f7f7464a KONRAD Frederic
    .instance_init = virtio_serial_pci_instance_init,
1436 f7f7464a KONRAD Frederic
    .class_init    = virtio_serial_pci_class_init,
1437 f7f7464a KONRAD Frederic
};
1438 f7f7464a KONRAD Frederic
1439 e37da394 KONRAD Frederic
/* virtio-net-pci */
1440 e37da394 KONRAD Frederic
1441 e37da394 KONRAD Frederic
static Property virtio_net_properties[] = {
1442 e37da394 KONRAD Frederic
    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
1443 e37da394 KONRAD Frederic
                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
1444 e37da394 KONRAD Frederic
    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
1445 e37da394 KONRAD Frederic
    DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
1446 e37da394 KONRAD Frederic
    DEFINE_NIC_PROPERTIES(VirtIONetPCI, vdev.nic_conf),
1447 e37da394 KONRAD Frederic
    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetPCI, vdev.net_conf),
1448 e37da394 KONRAD Frederic
    DEFINE_PROP_END_OF_LIST(),
1449 e37da394 KONRAD Frederic
};
1450 e37da394 KONRAD Frederic
1451 e37da394 KONRAD Frederic
static int virtio_net_pci_init(VirtIOPCIProxy *vpci_dev)
1452 e37da394 KONRAD Frederic
{
1453 e37da394 KONRAD Frederic
    VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
1454 e37da394 KONRAD Frederic
    DeviceState *vdev = DEVICE(&dev->vdev);
1455 e37da394 KONRAD Frederic
1456 e37da394 KONRAD Frederic
    virtio_net_set_config_size(&dev->vdev, vpci_dev->host_features);
1457 e37da394 KONRAD Frederic
    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
1458 e37da394 KONRAD Frederic
    if (qdev_init(vdev) < 0) {
1459 e37da394 KONRAD Frederic
        return -1;
1460 e37da394 KONRAD Frederic
    }
1461 e37da394 KONRAD Frederic
    return 0;
1462 e37da394 KONRAD Frederic
}
1463 e37da394 KONRAD Frederic
1464 e37da394 KONRAD Frederic
static void virtio_net_pci_class_init(ObjectClass *klass, void *data)
1465 e37da394 KONRAD Frederic
{
1466 e37da394 KONRAD Frederic
    DeviceClass *dc = DEVICE_CLASS(klass);
1467 e37da394 KONRAD Frederic
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1468 e37da394 KONRAD Frederic
    VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
1469 e37da394 KONRAD Frederic
1470 e37da394 KONRAD Frederic
    k->romfile = "efi-virtio.rom";
1471 e37da394 KONRAD Frederic
    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
1472 e37da394 KONRAD Frederic
    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
1473 e37da394 KONRAD Frederic
    k->revision = VIRTIO_PCI_ABI_VERSION;
1474 e37da394 KONRAD Frederic
    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
1475 e37da394 KONRAD Frederic
    dc->props = virtio_net_properties;
1476 e37da394 KONRAD Frederic
    vpciklass->init = virtio_net_pci_init;
1477 e37da394 KONRAD Frederic
}
1478 e37da394 KONRAD Frederic
1479 e37da394 KONRAD Frederic
static void virtio_net_pci_instance_init(Object *obj)
1480 e37da394 KONRAD Frederic
{
1481 e37da394 KONRAD Frederic
    VirtIONetPCI *dev = VIRTIO_NET_PCI(obj);
1482 e37da394 KONRAD Frederic
    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET);
1483 e37da394 KONRAD Frederic
    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
1484 e37da394 KONRAD Frederic
}
1485 e37da394 KONRAD Frederic
1486 e37da394 KONRAD Frederic
static const TypeInfo virtio_net_pci_info = {
1487 e37da394 KONRAD Frederic
    .name          = TYPE_VIRTIO_NET_PCI,
1488 e37da394 KONRAD Frederic
    .parent        = TYPE_VIRTIO_PCI,
1489 e37da394 KONRAD Frederic
    .instance_size = sizeof(VirtIONetPCI),
1490 e37da394 KONRAD Frederic
    .instance_init = virtio_net_pci_instance_init,
1491 e37da394 KONRAD Frederic
    .class_init    = virtio_net_pci_class_init,
1492 e37da394 KONRAD Frederic
};
1493 e37da394 KONRAD Frederic
1494 0a2acf5e KONRAD Frederic
/* virtio-pci-bus */
1495 0a2acf5e KONRAD Frederic
1496 0a2acf5e KONRAD Frederic
void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
1497 0a2acf5e KONRAD Frederic
{
1498 0a2acf5e KONRAD Frederic
    DeviceState *qdev = DEVICE(dev);
1499 0a2acf5e KONRAD Frederic
    BusState *qbus;
1500 0a2acf5e KONRAD Frederic
    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev, NULL);
1501 0a2acf5e KONRAD Frederic
    qbus = BUS(bus);
1502 cbd19063 KONRAD Frederic
    qbus->allow_hotplug = 1;
1503 0a2acf5e KONRAD Frederic
}
1504 0a2acf5e KONRAD Frederic
1505 0a2acf5e KONRAD Frederic
static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
1506 0a2acf5e KONRAD Frederic
{
1507 0a2acf5e KONRAD Frederic
    BusClass *bus_class = BUS_CLASS(klass);
1508 0a2acf5e KONRAD Frederic
    VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
1509 0a2acf5e KONRAD Frederic
    bus_class->max_dev = 1;
1510 0a2acf5e KONRAD Frederic
    k->notify = virtio_pci_notify;
1511 0a2acf5e KONRAD Frederic
    k->save_config = virtio_pci_save_config;
1512 0a2acf5e KONRAD Frederic
    k->load_config = virtio_pci_load_config;
1513 0a2acf5e KONRAD Frederic
    k->save_queue = virtio_pci_save_queue;
1514 0a2acf5e KONRAD Frederic
    k->load_queue = virtio_pci_load_queue;
1515 0a2acf5e KONRAD Frederic
    k->get_features = virtio_pci_get_features;
1516 0a2acf5e KONRAD Frederic
    k->query_guest_notifiers = virtio_pci_query_guest_notifiers;
1517 0a2acf5e KONRAD Frederic
    k->set_host_notifier = virtio_pci_set_host_notifier;
1518 0a2acf5e KONRAD Frederic
    k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
1519 0a2acf5e KONRAD Frederic
    k->vmstate_change = virtio_pci_vmstate_change;
1520 085bccb7 KONRAD Frederic
    k->device_plugged = virtio_pci_device_plugged;
1521 0a2acf5e KONRAD Frederic
}
1522 0a2acf5e KONRAD Frederic
1523 0a2acf5e KONRAD Frederic
static const TypeInfo virtio_pci_bus_info = {
1524 0a2acf5e KONRAD Frederic
    .name          = TYPE_VIRTIO_PCI_BUS,
1525 0a2acf5e KONRAD Frederic
    .parent        = TYPE_VIRTIO_BUS,
1526 0a2acf5e KONRAD Frederic
    .instance_size = sizeof(VirtioPCIBusState),
1527 0a2acf5e KONRAD Frederic
    .class_init    = virtio_pci_bus_class_init,
1528 0a2acf5e KONRAD Frederic
};
1529 0a2acf5e KONRAD Frederic
1530 83f7d43a Andreas Färber
static void virtio_pci_register_types(void)
1531 53c25cea Paul Brook
{
1532 16c915ba Amit Shah
    type_register_static(&virtio_rng_info);
1533 0a2acf5e KONRAD Frederic
    type_register_static(&virtio_pci_bus_info);
1534 085bccb7 KONRAD Frederic
    type_register_static(&virtio_pci_info);
1535 60653b28 Paolo Bonzini
#ifdef CONFIG_VIRTFS
1536 60653b28 Paolo Bonzini
    type_register_static(&virtio_9p_info);
1537 60653b28 Paolo Bonzini
#endif
1538 653ced07 KONRAD Frederic
    type_register_static(&virtio_blk_pci_info);
1539 bc7b90a0 KONRAD Frederic
    type_register_static(&virtio_scsi_pci_info);
1540 e378e88d KONRAD Frederic
    type_register_static(&virtio_balloon_pci_info);
1541 f7f7464a KONRAD Frederic
    type_register_static(&virtio_serial_pci_info);
1542 e37da394 KONRAD Frederic
    type_register_static(&virtio_net_pci_info);
1543 53c25cea Paul Brook
}
1544 53c25cea Paul Brook
1545 83f7d43a Andreas Färber
type_init(virtio_pci_register_types)